요소에서 텍스트 선택 (마우스로 강조 표시와 유사)


424

사용자가 링크를 클릭하게 한 다음 입력이 아닌 다른 요소에서 HTML 텍스트를 선택합니다 .

"선택"이란 텍스트 위로 마우스를 끌어 텍스트를 선택하는 것과 같은 방법을 의미합니다. 모든 사람들이 다른 용어로 "선택"또는 "강조 표시"에 대해 이야기하기 때문에 이것은 연구에 대한 부담이었습니다.

이것이 가능한가? 지금까지 내 코드 :

HTML :

<a href="javascript:" onclick="SelectText('xhtml-code')">Select Code</a>
<code id="xhtml-code">Some Code here </code>

JS :

function SelectText(element) {
    $("#" + element).select();
}

나는 명백히 명백한 것을 놓치고 있습니까?


답변:


612

일반 자바 스크립트

function selectText(node) {
    node = document.getElementById(node);

    if (document.body.createTextRange) {
        const range = document.body.createTextRange();
        range.moveToElementText(node);
        range.select();
    } else if (window.getSelection) {
        const selection = window.getSelection();
        const range = document.createRange();
        range.selectNodeContents(node);
        selection.removeAllRanges();
        selection.addRange(range);
    } else {
        console.warn("Could not select text in node: Unsupported browser.");
    }
}

const clickable = document.querySelector('.click-me');
clickable.addEventListener('click', () => selectText('target'));
<div id="target"><p>Some text goes here!</p><p>Moar text!</p></div>
<p class="click-me">Click me!</p>

다음은 실제 데모 입니다. jQuery 플러그인을 찾는 사람들을 위해 그 중 하나도 만들었 습니다 .


jQuery (원래 답변)

이 스레드 에서 이에 대한 해결책을 찾았습니다 . 주어진 정보를 수정하고 약간의 jQuery와 혼합하여 브라우저에 관계없이 모든 요소에서 텍스트를 선택하는 완전히 멋진 기능을 만들 수있었습니다.

function SelectText(element) {
    var text = document.getElementById(element);
    if ($.browser.msie) {
        var range = document.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = window.getSelection();
        var range = document.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = window.getSelection();
        selection.setBaseAndExtent(text, 0, text, 1);
    }
}

jQuery를 솔루션은 나에게 catch되지 않은 형식 오류를 제공합니다 : 재산 'MSIE'정의의를 읽을 수 없습니다
egmfrs

@egmfrs yea이 답변이 게시 된 후 jquery가 그들의 browser스니퍼 를 제거했습니다 .
Jason

127

다음은 브라우저 스니핑이없고 jQuery에 의존하지 않는 버전입니다.

function selectElementText(el, win) {
    win = win || window;
    var doc = win.document, sel, range;
    if (win.getSelection && doc.createRange) {
        sel = win.getSelection();
        range = doc.createRange();
        range.selectNodeContents(el);
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (doc.body.createTextRange) {
        range = doc.body.createTextRange();
        range.moveToElementText(el);
        range.select();
    }
}

selectElementText(document.getElementById("someElement"));
selectElementText(elementInIframe, iframe.contentWindow);

의 텍스트를 선택하는 방법이 div contentEditable='true'있습니까?
oldboy

@PrimitiveNom :이 코드는 contenteditable 요소에서 작동하지만 먼저 초점을 맞추어야합니다.
Tim Down

18

범위가 창 및 문서와 다르기 때문에 iframe 내부의 요소에는 Jason의 코드를 사용할 수 없습니다. 그 문제를 해결하고 다른 jQuery 플러그인 (체인 가능)으로 사용하기 위해 수정했습니다.

예제 1 : 클릭 한 번으로 <code> 태그 내의 모든 텍스트 선택 및 "선택"클래스 추가 :

$(function() {
    $("code").click(function() {
        $(this).selText().addClass("selected");
    });
});

예제 2 : 버튼 클릭시 Iframe 내부의 요소를 선택하십시오.

$(function() {
    $("button").click(function() {
        $("iframe").contents().find("#selectme").selText();
    });
});

참고 : 보안 오류를 방지하려면 iframe 소스가 동일한 도메인에 있어야합니다.

jQuery 플러그인 :

jQuery.fn.selText = function() {
    var obj = this[0];
    if ($.browser.msie) {
        var range = obj.offsetParent.createTextRange();
        range.moveToElementText(obj);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        var range = obj.ownerDocument.createRange();
        range.selectNodeContents(obj);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        selection.setBaseAndExtent(obj, 0, obj, 1);
    }
    return this;
}

IE8, Firefox, Opera, Safari, Chrome (현재 버전)에서 테스트했습니다. 이전 IE 버전에서 작동하는지 확실하지 않습니다 (진심으로 상관하지 않습니다).


3
$ .browser는 더 이상 사용되지
James McCormack

2
@JamesMcCormack : 예. $ .browser를 포함하지 않는 다른 솔루션이 여기에 게시되어 있기 때문에 다시 작성할 가치가 있는지 확실하지 않습니다.
lepe

16

스레드 에는 정말 멋진 것들이 포함되어 있습니다. 그러나 "보안 오류"로 인해 FF 3.5b99 + FireBug를 사용하여이 페이지에서 바로 수행 할 수 없습니다.

이피 !! 이 코드로 전체 오른쪽 사이드 바를 선택할 수있었습니다.

    var r = document.createRange();
    var w=document.getElementById("sidebar");  
    r.selectNodeContents(w);  
    var sel=window.getSelection(); 
    sel.removeAllRanges(); 
    sel.addRange(r); 

추신 :-jquery 선택기에서 반환 한 객체를 사용할 수 없었습니다.

   var w=$("div.welovestackoverflow",$("div.sidebar"));

   //this throws **security exception**

   r.selectNodeContents(w);

2
jQuery 객체를 선택하려고 할 때 jQuery에서 요소를 가져와야합니다. var w = $ ( "div.welovestackoverflow", $ ( "div.sidebar")). get (0);
Blixt 2016 년

작동하지 않습니다 ... "개체 가이 방법을 지원하지 않습니다"라는 오류가 발생하고 첫 번째 줄이 강조 표시됩니다. 나는 파고 들었고 "document.body.createTextRange ()"가 있지만 "selectNodeContents"가 작동하지 않는다는 것을 알았습니다. 그리고 이것은 IE에 있습니다
Jason

나는 당신이 발견 한 그 스레드를 읽었습니다 ... 놀라운 ... 나는 모든 브라우저에서 작동하는 그 정보에서 함수를 만들 수있었습니다. 정말 고맙습니다! 내 솔루션이 게시되었습니다
Jason

6

다음 기능을 사용하여 요소의 내용을 선택할 수 있습니다.

jQuery.fn.selectText = function(){
    this.find('input').each(function() {
        if($(this).prev().length == 0 || !$(this).prev().hasClass('p_copy')) { 
            $('<p class="p_copy" style="position: absolute; z-index: -1;"></p>').insertBefore($(this));
        }
        $(this).prev().html($(this).val());
    });
    var doc = document;
    var element = this[0];
    console.log(this, element);
    if (doc.body.createTextRange) {
        var range = document.body.createTextRange();
        range.moveToElementText(element);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();        
        var range = document.createRange();
        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);
    }
};

이 함수는 다음과 같이 호출 할 수 있습니다.

$('#selectme').selectText();

5

나는 똑같은 것을 찾고 있었고, 나의 해결책은 이것이었다 :

$('#el-id').focus().select();

3
focus()이 질문은 비 입력에 사용할 수 없습니다 .
Jason

4
그러나 textarea 요소에서 사용할 수 있습니다-이것은 내가 여기에 도착하는 데 문제가되었습니다. 질문을 끝까지 읽지 못한 것에 대한 나의 잘못.
Auston

4

나는 몇 가지를 제외하고 lepe의 대답을 좋아했습니다.

  1. 브라우저 스니핑, jQuery 또는 최적이 아님
  2. 마른
  3. obj의 부모가 createTextRange를 지원하지 않으면 IE8에서 작동하지 않습니다.
  4. setBaseAndExtent 를 사용하는 Chrome의 기능을 활용해야합니다 (IMO)
  5. 여러 DOM 요소 ( "selected"요소 내의 요소)에서 텍스트를 선택하지 않습니다. 즉 , 여러 범위 요소를 포함하는 div에서 selText 를 호출하면 해당 요소 각각의 텍스트가 선택 되지 않습니다 . 그것은 YMMV의 거래 차단기였습니다.

영감에 대한 lepe의 대답과 함께 내가 생각해 낸 것은 다음과 같습니다. 나는 이것이 약간 무겁기 때문에 조롱 당할 것이라고 확신한다. 그러나 그것은 작동하고 브라우저 스니핑을 피하며 그것이 핵심 입니다.

selectText:function(){

    var range,
        selection,
        obj = this[0],
        type = {
            func:'function',
            obj:'object'
        },
        // Convenience
        is = function(type, o){
            return typeof o === type;
        };

    if(is(type.obj, obj.ownerDocument)
        && is(type.obj, obj.ownerDocument.defaultView)
        && is(type.func, obj.ownerDocument.defaultView.getSelection)){

        selection = obj.ownerDocument.defaultView.getSelection();

        if(is(type.func, selection.setBaseAndExtent)){
            // Chrome, Safari - nice and easy
            selection.setBaseAndExtent(obj, 0, obj, $(obj).contents().size());
        }
        else if(is(type.func, obj.ownerDocument.createRange)){

            range = obj.ownerDocument.createRange();

            if(is(type.func, range.selectNodeContents)
                && is(type.func, selection.removeAllRanges)
                && is(type.func, selection.addRange)){
                // Mozilla
                range.selectNodeContents(obj);
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }
    }
    else if(is(type.obj, document.body) && is(type.obj, document.body.createTextRange)) {

        range = document.body.createTextRange();

        if(is(type.obj, range.moveToElementText) && is(type.obj, range.select)){
            // IE most likely
            range.moveToElementText(obj);
            range.select();
        }
    }

    // Chainable
    return this;
}

그게 다야. 당신이 보는 것 중 일부는 가독성 및 / 또는 편의를위한 것입니다. 최신 버전의 Opera, Safari, Chrome, Firefox 및 IE에서 Mac에서 테스트되었습니다. IE8에서도 테스트되었습니다. 또한 일반적으로 내부 / 코드 블록이 필요할 때만 변수를 선언하지만 jslint는 변수가 모두 최상위로 선언되도록 제안했습니다. 좋아 jslint.

편집 이것을 op의 코드에 묶는 방법을 포함시키는 것을 잊었습니다.

function SelectText(element) {
    $("#" + element).selectText();
}

건배


그래, 그것은 나에게 큰 손길을 보이지만 올바른 것으로 보입니다. 내 주된 단점은 비표준을 사용하는 setBaseAndExtent()것이 단순히 그 지점을 제거 할 수 있고 모든 것이 표준 기반 방식으로 잘 작동 할 때 무의미 해 보이는 것입니다. 기능 감지는 훌륭하지만 완전히 철저히 테스트하는 모든 것에 지칠 것입니다.
Tim Down

음 @TimDown은 활용의 요점은 setBaseAndExtent훨씬 더 효율적이며 추가 된 ifStatemnent가 있어도 "브랜치를 제거"하는 것보다 훨씬 더 낫다는 것입니다. 나는 "피곤할 것"이라는 의견을 정말로 이해하지 못합니다. 그것을 작성하고 잊어라, 당신이해야 할 유일한 것은 그것을 작성하는 것이 아니라 함수를 호출하는 것입니다. :)
Madbreaks 2014 년

@Madbreaks setBaseAndExtent보다 성능이 훨씬 뛰어나면 놀랄 것 addRange입니다. 왜 그럴까요? 내 다른 의견은 모든 DOM 상호 작용으로 확장 된 기능 테스트 방식과 관련이 있습니다. 사용하기 전에 모든 단일 DOM 메서드 및 속성을 테스트하는 코드가 엄청나게 많습니다. 나는 비 승인하지 않는다. 코드를 작성하고 코드에서 몇 가지 가정을 더 기쁘게 생각합니다.
Tim Down

4

크롬에서 작동하는 업데이트 된 버전 :

function SelectText(element) {
    var doc = document;
    var text = doc.getElementById(element);    
    if (doc.body.createTextRange) { // ms
        var range = doc.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();
        var range = doc.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);

    }
}

$(function() {
    $('p').click(function() {
        SelectText("selectme");

    });
});

http://jsfiddle.net/KcX6A/326/


3

모든 태그에 대해이 짧고 간단한 코드로 해당 태그 내의 모든 텍스트를 선택할 수 있습니다. 전체 태그 영역을 노란색으로 강조 표시하고 클릭 한 번으로 그 안의 텍스트를 선택합니다.

document.onclick = function(event) {
    var range, selection;
event.target.style.backgroundColor = 'yellow';
        selection = window.getSelection();
        range = document.createRange();
        range.selectNodeContents(event.target);
        selection.removeAllRanges();
        selection.addRange(range);
};

2

lepe-고마워요! 코드를 플러그인 파일에 넣은 다음 각 명령문과 함께 사용하여 한 페이지에 여러 개의 사전 태그와 여러 개의 "모두 선택"링크를 가질 수 있으며 올바른 사전을 선택하여 강조 표시합니다.

<script type="text/javascript" src="../js/jquery.selecttext.js"></script>
<script type="text/javascript">
  $(document).ready(function() { 
        $(".selectText").each(function(indx) {
                $(this).click(function() {                 
                    $('pre').eq(indx).selText().addClass("selected");
                        return false;               
                    });
        });
  });


1

상기 봐 가지고 Selection 개체 (게코 엔진)과 TextRange 개체 그래서, 난이 구현을위한 크로스 브라우저 지원이 자바 스크립트 프레임 워크에 대해 알고하지 않습니다. (트라이던트 엔진)하지만, 나도 그것을보고 적이 jQuery조차도 가능합니다.


0

Tim의 방법은 내 경우에 완벽하게 작동합니다. 다음 문장을 바꾼 후 IE와 FF 모두 div에서 텍스트를 선택하십시오.

range.moveToElementText(text);

다음과 같이 :

range.moveToElementText(el);

div의 텍스트는 다음 jQuery 함수로 클릭하여 선택됩니다.

$(function () {
    $("#divFoo").click(function () {
        selectElementText(document.getElementById("divFoo"));
    })
});

0

다음은 문자열 형식으로 선택한 텍스트를 얻는 또 다른 간단한 솔루션입니다.이 문자열을 사용하여 div 요소 자식을 코드에 쉽게 추가 할 수 있습니다.

var text = '';

if (window.getSelection) {
    text = window.getSelection();

} else if (document.getSelection) {
    text = document.getSelection();

} else if (document.selection) {
    text = document.selection.createRange().text;
}

text = text.toString();

강조 표시를 만들지 않고 강조 표시된 텍스트를 반환하기위한 것입니다.
MKN 웹 솔루션

0

내 유스 케이스는 편집 가능한 범위 요소 내에서 텍스트 범위를 선택하는 것이 었습니다.

주요 차이점은 유형의 노드를 통과해야한다는 것입니다 Text받는 Range기술로, 객체 Range.setStart ()의 문서에서 :

startNode가 Text, Comment 또는 CDATASection 유형의 노드 인 경우 startOffset은 startNode의 시작부터 문자 수입니다. 다른 노드 유형의 경우 startOffset은 startNode의 시작 사이에있는 하위 노드의 수입니다.

Text노드는 그래서, 액세스를 얻기 위해, 스팬 요소의 첫 번째 자식 노드 childNodes[0]스팬 요소를. 나머지는 대부분의 다른 답변과 동일합니다.

다음은 코드 예제입니다.

var startIndex = 1;
var endIndex = 5;
var element = document.getElementById("spanId");
var textNode = element.childNodes[0];

var range = document.createRange();
range.setStart(textNode, startIndex);
range.setEnd(textNode, endIndex);

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);

다른 관련 문서 :
범위
선택
Document.createRange ()
Window.getSelection ()


-1

jQuery.browser.webkitChrome의 "else if"에 추가되었습니다 . Chrome 23에서 작동하지 않습니다.

가있는 <pre>태그 에서 콘텐츠를 선택하기 위해이 스크립트를 아래에서 만들었 습니다 class="code".

jQuery( document ).ready(function() {
    jQuery('pre.code').attr('title', 'Click to select all');
    jQuery( '#divFoo' ).click( function() {
        var refNode = jQuery( this )[0];
        if ( jQuery.browser.msie ) {
            var range = document.body.createTextRange();
            range.moveToElementText( refNode );
            range.select();
        } else if ( jQuery.browser.mozilla || jQuery.browser.opera  || jQuery.browser.webkit ) {
            var selection = refNode.ownerDocument.defaultView.getSelection();
            console.log(selection);
            var range = refNode.ownerDocument.createRange();
            range.selectNodeContents( refNode );
            selection.removeAllRanges();
            selection.addRange( range );
        } else if ( jQuery.browser.safari ) {
            var selection = refNode.ownerDocument.defaultView.getSelection();
            selection.setBaseAndExtent( refNode, 0, refNode, 1 );
        }
    } );
} );

-1

jQuery 문서에 따르면 select():

일치하는 각 요소의 선택 이벤트를 트리거하십시오. 그러면 해당 select 이벤트에 바인딩 된 모든 기능이 실행되고 일치하는 요소에 대해 브라우저의 기본 선택 작업이 호출됩니다.

select()이 경우 jQuery 가 작동하지 않는 이유에 대한 설명이 있습니다 .


4
CSS 스타일로 텍스트를 강조 표시하려고하지 않습니다. 텍스트를 선택하고 싶습니다.
Jason
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.