Zaznaczanie tekstu w elemencie (podobnie jak podświetlanie myszką)

Chciałbym, aby użytkownicy kliknęli link, a następnie wybierali tekst HTML w innym elemencie (NIE an input).

Przez "select" mam na myśli ten sam sposób, w jaki zaznaczasz tekst, przeciągając myszką nad nim. To był niedźwiedź do badań, ponieważ wszyscy mówią o "Wybierz" lub "wyróżnij" w innych kategoriach.

Czy to możliwe? Mój kod do tej pory:

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();
}
Czy coś mi umyka?
Author: Maistrenko Vitalii, 2009-06-12

16 answers

Zwykły Javascript

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>

Oto robocze demo . Dla tych z Was, którzy szukają wtyczki jQuery, zrobiłem jeden z nich zbyt.


JQuery (oryginalna odpowiedź)

Znalazłem na to rozwiązanie w w tym wątku . Udało mi się zmodyfikować podane informacje i zmieszać je z odrobiną jQuery, aby stworzyć całkowicie niesamowitą funkcję do zaznaczania tekstu w dowolnym elemencie, niezależnie od przeglądarki: {]}

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);
    }
}
 545
Author: Jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 23:44:58

Oto wersja bez sniffingu przeglądarki i bez polegania na 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);
 113
Author: Tim Down,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-23 08:09:01

Kod Jasona nie może być używany dla elementów wewnątrz ramki iframe (ponieważ zakres różni się od okna i dokumentu). Naprawiłem ten problem i zmodyfikowałem go tak, aby był używany jak każdy inny plugin jQuery (chainable):

Przykład 1: zaznaczenie całego tekstu wewnątrz znaczników za pomocą jednego kliknięcia i dodania klasy "selected":

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

Przykład 2: Po kliknięciu przycisku wybierz element wewnątrz ramki Iframe:

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

Uwaga: Pamiętaj, że źródło iframe powinno znajdować się w tej samej domenie, aby zapobieganie błędom zabezpieczeń.

JQuery Plugin:

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;
}
Testowałem go w IE8, Firefox, Opera, Safari, Chrome (aktualne wersje). Nie jestem pewien, czy działa w starszych wersjach IE (szczerze nie obchodzi mnie to).
 17
Author: lepe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-13 03:59:18

Ten wątek zawiera naprawdę wspaniałe rzeczy. Ale nie jestem w stanie zrobić to dobrze na tej stronie za pomocą FF 3.5b99 + FireBug ze względu na "błąd bezpieczeństwa".

Yipee!! Udało mi się wybrać cały prawy pasek boczny z tym kodem mam nadzieję, że pomoże: {]}
    var r = document.createRange();
    var w=document.getElementById("sidebar");  
    r.selectNodeContents(w);  
    var sel=window.getSelection(); 
    sel.removeAllRanges(); 
    sel.addRange(r); 

PS:- nie mogłem używać obiektów zwracanych przez selektory jquery jak

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

   //this throws **security exception**

   r.selectNodeContents(w);
 12
Author: TheVillageIdiot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-12 07:29:43

Szukałem tego samego, moje rozwiązanie było takie:

$('#el-id').focus().select();
 6
Author: Auston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 19:08:32

Spodobała mi się odpowiedź lepe ' a poza kilkoma rzeczami:

  1. przeglądarka-sniffing, jQuery lub no nie jest optymalna
  2. suche
  3. nie działa w IE8 jeśli rodzic obj nie obsługuje createTextRange
  4. zdolność Chrome do korzystania setBaseAndExtent należy wykorzystać (IMO)
  5. nie zaznacza tekstu obejmującego wiele elementów DOM (elementów w" zaznaczonym " elemencie). Innymi słowy, jeśli wywołasz selText na div zawierającym wiele elementy span, to Nie wybierze tekst każdego z tych elementów. To był dla mnie przełom, YMMV.
Oto, co wymyśliłem, ukłonem w stronę odpowiedzi lepe ' a na inspirację. Jestem pewien, że będę wyśmiewany, ponieważ jest to może trochę ciężkie ręce (i faktycznie może być bardziej, ale dygresję). Ale to działa i unika sniffing przeglądarki i o to chodzi.
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;
}
To wszystko. Niektóre z tego, co widzisz, to czytelność i / lub wygoda. Sprawdzone przez na Macu w najnowszych wersjach Opery, Safari, Chrome, Firefox i IE. Testowane również w IE8. Również zazwyczaj deklaruję zmienne tylko wtedy, gdy są potrzebne wewnątrz bloków kodu, ale jslint zasugerował, że wszystkie powinny być zadeklarowane na górze. Ok jslint.

Edit Zapomniałem dodać jak to powiązać z kodem op:

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

Cheers

 5
Author: Madbreaks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-10 00:05:37

Zaktualizowana wersja, która działa w chrome:

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/

 4
Author: Kimtho6,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-18 14:26:12

Możesz użyć następującej funkcji, aby wybrać zawartość dowolnego elementu:

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

Tę funkcję można wywołać w następujący sposób:

$('#selectme').selectText();
 4
Author: Wolfack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 06:13:48

Lepe-u mnie działa świetnie dzięki! Umieściłem Twój kod w pliku wtyczki, a następnie użyłem go w połączeniu z każdym stwierdzeniem, dzięki czemu możesz mieć wiele znaczników pre i wiele linków "Wybierz wszystkie" na jednej stronie i wybiera poprawny pre, aby wyróżnić: {]}

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

 3
Author: DaveR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-30 12:25:14

Dla dowolnego znacznika można wybrać cały tekst wewnątrz tego znacznika za pomocą tego krótkiego i prostego kodu. Podświetli cały obszar znacznika żółtym kolorem i zaznaczy wewnątrz niego tekst jednym kliknięciem.

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);
};
 3
Author: knjhaveri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-02 18:21:19

Spójrz na obiekt wyboru (silnik Gecko) i obiekt TextRange (Silnik Trident.) Nie wiem o żadnych frameworków JavaScript, które mają wsparcie dla cross-browser dla tego zaimplementowane, ale nigdy nie szukałem go, więc jest możliwe, że nawet jQuery ma go.

 2
Author: Blixt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-12 06:41:05

Metoda Tima działa idealnie w moim przypadku-wybranie tekstu w div zarówno dla IE jak i FF po zastąpieniu następującego stwierdzenia:

range.moveToElementText(text);

Z następującym:

range.moveToElementText(el);

Tekst w div jest wybierany przez kliknięcie na niego za pomocą funkcji jQuery:

$(function () {
    $("#divFoo").click(function () {
        selectElementText(document.getElementById("divFoo"));
    })
});
 1
Author: Hong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-21 11:04:17

Oto kolejne proste rozwiązanie, aby uzyskać zaznaczony tekst w postaci łańcucha znaków, możesz go łatwo użyć do dodania potomka elementu div do kodu:

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();
 1
Author: Nadeem Yasin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-26 08:27:54

Dodano jQuery.browser.webkit do "else if" dla Chrome. Nie można tego uruchomić w Chrome 23.

Zrobiłem poniższy skrypt do wyboru treści w znaczniku <pre>, który ma 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 );
        }
    } );
} );
 0
Author: Derk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-19 09:21:23

Zgodnie z dokumentacją jQuery select():

Uruchamia Zdarzenie select każdego dopasowanego elementu. Powoduje to, że wszystkie funkcje powiązane z tym zdarzeniem select są wykonywane i wywołuje domyślną akcję select przeglądarki na pasujących elementach.

Jest twoje wyjaśnienie, dlaczego jQuery select() nie będzie działać w tym przypadku.

 0
Author: Kees de Kooter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-07 14:47:55

Moim szczególnym przypadkiem użycia było wybranie zakresu tekstu wewnątrz edytowalnego elementu span, który, o ile widzę, nie jest opisany w żadnej z odpowiedzi tutaj.

Główna różnica polega na tym, że musisz przekazać węzeł typu Text do obiektu Range, zgodnie z opisem w dokumentacji Range.setStart():

Jeśli startNode jest węzłem typu Text, Comment lub CDATASection , wtedy startOffset jest liczbą znaków od początku startNode. Dla innych typów węzłów, startOffset jest liczbą Potomków węzły pomiędzy początkiem węzła startNode.

Węzeł Text jest pierwszym węzłem potomnym elementu span, więc aby go uzyskać, uzyskaj dostęp childNodes[0] elementu span. Reszta jest taka sama jak w większości innych odpowiedzi.

Oto przykład kodu:

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

Inna Odpowiednia dokumentacja:
Zakres
wybór
dokument.createRange()
okno.getSelection()

 0
Author: Domysee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-06 07:17:30