Выделение текста в элементе (сродни выделению мышью) - PullRequest
401 голосов
/ 12 июня 2009

Я бы хотел, чтобы пользователи нажимали на ссылку, а затем он выбирал 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();
}

Я упускаю что-то явно очевидное?

Ответы [ 16 ]

580 голосов
/ 12 июня 2009

Простой 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>

Вот демоверсия . Для тех из вас, кто ищет плагин 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);
    }
}
122 голосов
/ 15 мая 2010

Вот версия, в которой браузер не работает и не использует 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);
19 голосов
/ 13 мая 2010

Код Джейсона нельзя использовать для элементов внутри iframe (так как область видимости отличается от окна и документа). Я исправил эту проблему и изменил ее, чтобы использовать ее как любой другой плагин jQuery (цепочка):

Пример 1. Выделение всего текста внутри тегов одним щелчком мыши и добавление класса «selected»:

$(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 (искренне, мне все равно).

16 голосов
/ 12 июня 2009

Эта тема содержит действительно замечательные вещи. Но я не могу сделать это прямо на этой странице, используя FF 3.5b99 + FireBug из-за «Ошибка безопасности».

Yipee !! Я смог выделить всю правую боковую панель с этим кодом, надеюсь, он вам поможет:

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

PS: - Мне не удалось использовать объекты, возвращаемые селекторами jquery, например

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

   //this throws **security exception**

   r.selectNodeContents(w);
7 голосов
/ 21 апреля 2011

Я искал то же самое, мое решение было таким:

$('#el-id').focus().select();
6 голосов
/ 22 ноября 2016

Вы можете использовать следующую функцию для выбора содержимого любого элемента:

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 голосов
/ 09 февраля 2012

Мне понравился ответ Лепе, за исключением нескольких вещей:

  1. Обнюхивание в браузере, jQuery или нет не оптимально
  2. DRY
  3. Не работает в IE8, если родительский объект obj не поддерживает createTextRange
  4. Возможность использования Chrome setBaseAndExtent должна использоваться (IMO)
  5. Не будет выделять текст, охватывающий несколько элементов DOM (элементов внутри «выбранного» элемента). Другими словами, если вы вызовете selText для элемента div, содержащего несколько элементов span, он не выберет текст каждого из этих элементов. Для меня это было условием сделки, YMMV.

Вот то, что я придумал, с кивком Лепе ответил за вдохновение. Я уверен, что меня высмеют, поскольку это, возможно, немного жестко (и на самом деле может быть более, но я отвлекся). Но это работает и позволяет избежать перехвата браузера и в этом смысл .

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

Вот и все. Кое-что из того, что вы видите, предназначено для удобства чтения и / или удобства. Протестировано на Mac в последних версиях Opera, Safari, Chrome, Firefox и IE. Также проверено в IE8. Также я обычно объявляю переменные только в том случае, если / когда это необходимо, внутри блоков кода, но jslint предложил, чтобы они были объявлены сверху. Хорошо, jslint.

Редактировать Я забыл указать, как связать это с кодом оператора:

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

Приветствия

4 голосов
/ 10 января 2012

Обновленная версия, которая работает в 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/

3 голосов
/ 02 февраля 2018

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

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 голосов
/ 30 декабря 2010

Лепе - это прекрасно работает для меня, спасибо! Я поместил ваш код в файл плагина, а затем использовал его вместе с каждым оператором, чтобы вы могли иметь несколько предварительных тегов и несколько ссылок «Выбрать все» на одной странице, и он выбирает правильный предварительный текст для выделения:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...