Zaznacz cały tekst DIV jednym kliknięciem myszy

136

Jak podświetlić / zaznaczyć zawartość znacznika DIV, gdy użytkownik kliknie DIV ... Pomysł polega na tym, że cały tekst jest podświetlony / zaznaczony, aby użytkownik nie musiał ręcznie zaznaczać tekstu myszą i potencjalnie przegapić fragment tekstu?

Na przykład, powiedzmy, że mamy DIV jak poniżej:

<div id="selectable">http://example.com/page.htm</div>

... a gdy użytkownik kliknie którykolwiek z tych adresów URL, cały tekst adresu URL jest podświetlany, dzięki czemu może łatwo przeciągnąć wybrany tekst w przeglądarce lub skopiować cały adres URL prawym przyciskiem myszy.

Dzięki!

Acyra
źródło

Odpowiedzi:

194

function selectText(containerid) {
    if (document.selection) { // IE
        var range = document.body.createTextRange();
        range.moveToElementText(document.getElementById(containerid));
        range.select();
    } else if (window.getSelection) {
        var range = document.createRange();
        range.selectNode(document.getElementById(containerid));
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}
<div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>

Teraz musisz przekazać ID jako argument, który w tym przypadku jest „wybieralny”, ale jest bardziej globalny, co pozwala na użycie go w dowolnym miejscu wiele razy bez używania, jak wspomniał chiborg, jQuery.

Denis Sadowski
źródło
8
BTW, możesz łatwo zmienić to w obsługę zdarzeń kliknięcia jQuery, zastępując document.getElementById('selectable')this. Następnie możesz dyskretnie dodać tę funkcjonalność do kilku elementów, na przykład kilku elementów div w kontenerze: jQuery('#selectcontainer div').click(selectText);
chiborg
3
Działa to dobrze w Chrome, FF, Safari (Mac) oraz Chrome i IE (Windows 9+, 8 nie testowane). Ale wygląda na to, że nie działa w Safari na iPadzie Mini (iOS6) lub iPhonie 4, nie jestem pewien co do innego iOS lub Androida.
prototyp
1
Zgodnie z tym artykułem zapytanie if (window.getSelection) {powinno być pierwsze w przypadku Opery ( quirksmode.org/dom/range_intro.html )
prototyp,
1
To rozwiązanie wydaje się nie działać w ie11. Każdy pomysł, dlaczego?
Swiss Mister
5
W wersji Chrome 36+ zwróci to błąd „Nieciągłe wybieranie nie jest obsługiwane”. Rozwiązaniem jest dodanie window.getSelection().removeAllRanges();przedwindow.getSelection().addRange(range);
nHaskins
122

UPDATE 2017:

Aby wybrać zawartość węzła, wywołaj:

window.getSelection().selectAllChildren(
    document.getElementById(id)
);

Działa to we wszystkich nowoczesnych przeglądarkach, w tym IE9 + (w trybie standardowym).

Wykonalny przykład:

function select(id) {
  window.getSelection()
    .selectAllChildren(
      document.getElementById("target-div") 
    );
}
#outer-div  { padding: 1rem; background-color: #fff0f0; }
#target-div { padding: 1rem; background-color: #f0fff0; }
button      { margin: 1rem; }
<div id="outer-div">
  <div id="target-div">
    Some content for the 
    <br>Target DIV
  </div>
</div>

<button onclick="select(id);">Click to SELECT Contents of #target-div</button>


Oryginalna odpowiedź poniżej jest przestarzała, ponieważ window.getSelection().addRange(range); została wycofana

Oryginalna odpowiedź:

Wszystkie powyższe przykłady używają:

    var range = document.createRange();
    range.selectNode( ... );

ale problem polega na tym, że wybiera sam węzeł, w tym znacznik DIV itp.

Aby wybrać tekst węzła zgodnie z pytaniem OP, musisz zamiast tego zadzwonić:

    range.selectNodeContents( ... )

Tak więc pełny fragment będzie wyglądał następująco:

    function selectText( containerid ) {

        var node = document.getElementById( containerid );

        if ( document.selection ) {
            var range = document.body.createTextRange();
            range.moveToElementText( node  );
            range.select();
        } else if ( window.getSelection ) {
            var range = document.createRange();
            range.selectNodeContents( node );
            window.getSelection().removeAllRanges();
            window.getSelection().addRange( range );
        }
    }
isapir
źródło
Możesz także użyć thiszamiast pobierania elementu na podstawie identyfikatora, o ile znajduje się on w clickdetektorze elementu .
Zach Saucier
44

Istnieje czyste rozwiązanie CSS4:

.selectable{
    -webkit-touch-callout: all; /* iOS Safari */
    -webkit-user-select: all; /* Safari */
    -khtml-user-select: all; /* Konqueror HTML */
    -moz-user-select: all; /* Firefox */
    -ms-user-select: all; /* Internet Explorer/Edge */
    user-select: all; /* Chrome and Opera */

}

user-selectto specyfikacja modułu CSS na poziomie 4, która obecnie jest wersją roboczą i niestandardową właściwością CSS, ale przeglądarki dobrze ją obsługują - zobacz # search = user-select .

Przeczytaj więcej o wyborze użytkownika tutaj na MDN i baw się nim tutaj w w3scools

Mino
źródło
3
+1 niesamowite, niesamowite, eleganckie rozwiązanie! Przetestowano we wrześniu 2017 r. I działa bez zarzutu na FireFox i Chrome, ALE NIE W MICROSOFT EDGE !? Jakieś pomysły, dlaczego nie i jak to naprawić? dzięki!
Sam
13

Odpowiedź Neuroxika była bardzo pomocna. Miałem tylko problem z Chrome, bo kiedy kliknąłem na zewnętrzny div, to nie działało. Mogę rozwiązać ten problem, usuwając stare zakresy przed dodaniem nowego zakresu:

function selectText(containerid) {
    if (document.selection) {
        var range = document.body.createTextRange();
        range.moveToElementText(document.getElementById(containerid));
        range.select();
    } else if (window.getSelection()) {
        var range = document.createRange();
        range.selectNode(document.getElementById(containerid));
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}
<div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>
Josillo Debian
źródło
9

W przypadku rzeczy, które można edytować (nie zwykłych danych wejściowych, musisz użyć selectNodeContents (zamiast tylko selectNode).

UWAGA: Wszystkie odniesienia do "document.selection" i "createTextRange ()" dotyczą IE 8 i niższych ... Prawdopodobnie nie będziesz musiał wspierać tego potwora, jeśli próbujesz robić takie trudne rzeczy.

function selectElemText(elem) {

    //Create a range (a range is a like the selection but invisible)
    var range = document.createRange();

    // Select the entire contents of the element
    range.selectNodeContents(elem);

    // Don't select, just positioning caret:
    // In front 
    // range.collapse();
    // Behind:
    // range.collapse(false);

    // Get the selection object
    var selection = window.getSelection();

    // Remove any current selections
    selection.removeAllRanges();

    // Make the range you have just created the visible selection
    selection.addRange(range);

}
pion
źródło
6

Korzystając z pola tekstowego, możesz użyć tego: (przez Google)

<form name="select_all">

    <textarea name="text_area" rows="10" cols="80" 
    onClick="javascript:this.form.text_area.focus();this.form.text_area.select();">

    Text Goes Here 

    </textarea>
</form>

Widzę, że tak robi większość witryn internetowych. Po prostu stylizują go za pomocą CSS, aby nie wyglądał jak obszar tekstowy.

Tyler Carter
źródło
dlaczego nie tylko this.focus();this.select();?
Taha Paksu
5

Ten fragment kodu zapewnia wymaganą funkcjonalność . Musisz tylko dodać zdarzenie do tego elementu div, który aktywuje w nim fnSelect. Szybki hack, którego całkowicie nie powinieneś robić i prawdopodobnie nie zadziała, wyglądałby następująco:

document.getElementById("selectable").onclick(function(){
    fnSelect("selectable");
});

Oczywiście zakładając, że link do fragmentu został uwzględniony.

Simon Scarfe
źródło
5

Uważam, że przydatne jest zawinięcie tej funkcji jako wtyczki jQuery:

$.fn.selectText = function () {
    return $(this).each(function (index, el) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        } else if (window.getSelection) {
            var range = document.createRange();
            range.selectNode(el);
            window.getSelection().addRange(range);
        }
    });
}

Staje się więc rozwiązaniem wielokrotnego użytku. Następnie możesz to zrobić:

<div onclick="$(this).selectText()">http://example.com/page.htm</div>

I wybierze test w div.

vitmalina
źródło
1
Pamiętaj, aby wywołać metodę window.getSelection (). RemoveAllRanges (); jak w kodzie Josillo. Ponadto: zalecałbym umieszczenie window.getSelect jako pierwszej opcji, ponieważ jest to standard HTML5, a document.selection jest starym rozwiązaniem zastępczym IE dla IE8 i wcześniejszych.
Jan Aagaard
3

A co z tym prostym rozwiązaniem? :)

<input style="background-color:white; border:1px white solid;" onclick="this.select();" id="selectable" value="http://example.com/page.htm">

Jasne, że nie jest to konstrukcja div, jak wspomniałeś, ale nadal działa dla mnie.

Niko Lay
źródło
1
Zwięzłe rozwiązanie, ale nie uwzględnia to tekstu w elemencie innym niż pole wejściowe lub pole tekstowe.
JoePC,
3

Niko Lay: A co z tym prostym rozwiązaniem? :)

`<input style="background-color:white; border:1px white solid;" onclick="this.select();" id="selectable" value="http://example.com/page.htm">`

.....

Kod przed:

<textarea rows="20" class="codearea" style="padding:5px;" readonly="readonly">

Kod po:

<textarea rows="20" class="codearea" style="padding:5px;" readonly="readonly" onclick="this.select();" id="selectable">

Tylko ta część onclick = "this.select ();" id = "do wyboru" w moim kodzie działało dobrze. Zaznacza wszystko w moim polu kodu jednym kliknięciem myszy.

Dzięki za pomoc Niko Lay!

Igor B.
źródło
0
$.fn.selectText = function () {
    return $(this).each(function (index, el) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        } else if (window.getSelection) {
            var range = document.createRange();
            range.selectNode(el);
            window.getSelection().addRange(range);
        }
    });
}

Powyższa odpowiedź nie działa w Chrome, ponieważ addRange usuwa poprzednio dodany zakres. Nie znalazłem na to żadnego rozwiązania poza fałszywym wyborem z css.

Krzysztof Gibała
źródło
Dla kogoś ten kod może być pomocny, ponieważ przetestowałem go i stwierdziłem, że działa w najnowszej wersji Chrome: $ .fn.selectText = function () {return $ (this) .each (function (index, el) {if (document. selection) {var range = document.body.createTextRange (); range.moveToElementText (el); range.select ();} else if (window.getSelection) {var range = document.createRange (); range.selectNode (el ); window.getSelection (). removeAllRanges (); window.getSelection (). addRange (range);}}); }
Haider Abbas
0

Łatwo to osiągnąć dzięki ustawieniu wyboru przez użytkownika właściwości css na all. Lubię to:

div.anyClass {
  user-select: all;
}

tirmey
źródło