Выделите весь текст DIV одним щелчком мыши

136

Как выделить / выбрать содержимое тега DIV, когда пользователь нажимает на DIV ... идея заключается в том, что весь текст выделяется / выделяется, поэтому пользователю не нужно вручную выделять текст с помощью мыши и, возможно, пропустить немного текста?

Например, скажем, у нас есть DIV, как показано ниже:

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

... и когда пользователь нажимает на любой из этих URL-адресов, весь текст URL-адреса выделяется, чтобы он мог легко перетаскивать выделенный текст в браузере или копировать полный URL-адрес правой кнопкой мыши.

Спасибо!

Acyra
источник

Ответы:

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>

Теперь вам нужно передать идентификатор в качестве аргумента, который в данном случае является «выбираемым», но он более глобален, что позволяет вам использовать его где угодно несколько раз, не используя, как упоминал Чиборг, jQuery.

Денис Садовский
источник
8
Кстати, вы можете легко превратить это в обработчик событий нажатия jQuery, заменив document.getElementById('selectable')на this. Затем вы можете незаметно добавить функциональность к нескольким элементам, например, к нескольким элементам jQuery('#selectcontainer div').click(selectText);
div
3
Это прекрасно работает на Chrome, FF, Safari (Mac), Chrome и IE (Windows 9+, 8 не тестировалась). Но, похоже, он не работает в Safari на iPad Mini (iOS6) или iPhone 4, не уверен насчет других iOS или Android.
прототип
1
Согласно этой статье, запрос if (window.getSelection) {должен быть первым для Opera ( quirksmode.org/dom/range_intro.html )
прототип
1
Это решение, похоже, не работает в ie11. Есть идеи почему?
швейцарский господин
5
В Chrome версии 36+ будет возвращено сообщение об ошибке «Несоответствующий выбор не поддерживается». Решение состоит в том, чтобы добавить window.getSelection().removeAllRanges();раньшеwindow.getSelection().addRange(range);
nHaskins
122

ОБНОВЛЕНИЕ 2017:

Чтобы выбрать содержимое узла, вызовите:

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

Это работает во всех современных браузерах, включая IE9 + (в стандартном режиме).

Runnable Пример:

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>


Исходный ответ ниже устарел, поскольку window.getSelection().addRange(range); устарел

Оригинальный ответ:

Все приведенные выше примеры используют:

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

но проблема в том, что он выбирает сам узел, включая тег DIV и т. д.

Чтобы выбрать текст Узла согласно OP-вопросу, вам нужно позвонить взамен:

    range.selectNodeContents( ... )

Таким образом, полный фрагмент будет:

    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
источник
Вы также можете использовать thisвместо получения элемента на основе идентификатора, если он находится внутри clickслушателя элемента .
Зак Сауцер
44

Есть чистое решение 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-selectявляется спецификацией уровня 4 модуля CSS, которая в настоящее время является черновым и нестандартным свойством CSS, но браузеры хорошо ее поддерживают - см. # search = user-select .

Узнайте больше о выборе пользователя здесь на MDN и поиграйте с ним здесь, в w3scools

Мино
источник
3
+1 потрясающе круто элегантное решение! Протестировано в сентябре 2017 года и работает безупречно на FireFox и Chrome, НО В MICROSOFT EDGE !? Есть идеи, почему нет и как это исправить? Спасибо!
Сэм
13

Ответ Neuroxik был действительно полезным. У меня были только проблемы с Chrome, потому что когда я нажимал на внешний div, он не работал. Я мог бы решить эту проблему, удалив старые диапазоны, прежде чем добавить новый диапазон:

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>
Жозилло Дебиан
источник
9

Для содержимого, редактируемого (не для обычного ввода, вам нужно использовать selectNodeContents (а не просто selectNode).

ПРИМЕЧАНИЕ. Все ссылки на «document.selection» и «createTextRange ()» относятся к IE 8 и ниже ... Скорее всего, вам не нужно поддерживать этого монстра, если вы пытаетесь делать хитрые вещи, подобные этой.

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

}
боб
источник
6

Используя текстовое поле, вы можете использовать это: (через 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>

Вот как я вижу, что большинство сайтов делают это. Они просто стилизуют его с помощью CSS, чтобы он не выглядел как текстовое поле.

Тайлер Картер
источник
почему не просто this.focus();this.select();?
Таха Паксу
5

Этот фрагмент обеспечивает необходимую вам функциональность . Что вам нужно сделать, это добавить событие в тот div, который активирует в нем fnSelect. Быстрый взлом, который вы вообще не должны делать и, возможно, не сработаете, будет выглядеть так:

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

Очевидно, предполагая, что ссылка на фрагмент была включена.

Саймон Скарф
источник
5

Я нашел полезным обернуть эту функцию в плагин 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);
        }
    });
}

Таким образом, это становится многоразовым решением. Тогда вы можете сделать это:

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

И это будет выбран тест в div.

vitmalina
источник
1
Не забудьте вызвать window.getSelection (). RemoveAllRanges (); как в коде Жозилло. Также: я бы рекомендовал использовать window.getSelect в качестве первого варианта, поскольку это стандарт HTML5, а document.selection - это старый запасной вариант IE для IE8 и более ранних версий.
Ян Аагард
3

Как насчет этого простого решения? :)

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

Конечно, это не div-конструкция, как вы упомянули, но все же она работает для меня.

Нико Лэй
источник
1
Краткое решение, но это не учитывает текст в элементе, кроме поля ввода или текстового поля.
JoePC
3

Нико Лэй: Как насчет этого простого решения? :)

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

.....

Код перед:

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

Код после:

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

Только эта часть onclick = "this.select ();" id = "selectable" в моем коде работал нормально. Выбирает все в моем кодовом поле одним щелчком мыши.

Спасибо за помощь Нико Лей!

Игорь Б.
источник
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);
        }
    });
}

Ответ выше не работает в Chrome, потому что addRange удаляет предыдущий добавленный диапазон. Я не нашел никакого решения для этого, кроме поддельного выбора с помощью CSS.

Кристофер Гибала
источник
Для кого-то этот код может быть полезен, поскольку я протестировал и обнаружил, что он работает в последней версии 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);}}); }
Хайдер Аббас
0

Легко достигается с помощью свойства css user-select, установленного на all. Как это:

div.anyClass {
  user-select: all;
}

tirmey
источник