development

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

big-blog 2020. 2. 21. 22:28
반응형

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


사용자가 링크를 클릭하게 한 다음 입력이 아닌 다른 요소에서 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();
}

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


일반 자바 스크립트

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에 의존하지 않는 버전입니다.

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);

범위가 창 및 문서와 다르기 때문에 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 버전에서 작동하는지 확실하지 않습니다 (진심으로 상관하지 않습니다).


스레드 에는 정말 멋진 것들이 포함되어 있습니다. 그러나 "보안 오류"로 인해 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);

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

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

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

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();

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

  1. 브라우저 스니핑, jQuery 또는 최적이 아님
  2. 마른
  3. obj의 부모가 createTextRange를 지원하지 않으면 IE8에서 작동하지 않습니다.
  4. setBaseAndExtent 를 사용하는 Chrome의 기능을 활용해야합니다 (IMO)
  5. 여러 DOM 요소 ( "selected"요소 내의 요소)에 걸쳐있는 텍스트를 선택하지 않습니다. , 여러 span 요소를 포함하는 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();
}

건배


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

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/


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

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);
};

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;               
                    });
        });
  });


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


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

range.moveToElementText(text);

다음과 같이 :

range.moveToElementText(el);

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

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

다음은 문자열 형식으로 선택한 텍스트를 얻는 또 다른 간단한 솔루션입니다.이 문자열을 사용하여 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();

내 특별한 유스 케이스는 편집 가능한 범위 요소 내에서 텍스트 범위를 선택하는 것이 었습니다. 내가 볼 수있는 한 여기의 답변에 설명되어 있지 않습니다.

주요 차이점은 유형의 노드를 통과해야한다는 것입니다 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 ()


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 );
        }
    } );
} );

jQuery 문서에 따르면 select():

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

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

참고 URL : https://stackoverflow.com/questions/985272/selecting-text-in-an-element-akin-to-highlighting-with-your-mouse



반응형