jQuery - обтекание <span> вокруг выделенного текста - ошибка дублирующегося экземпляра

Этот вопрос относится к аналогичному вопросу, заданному здесь о том, как применить тег к выделенному тексту. На вопрос был дан ответ, но у этого ответа был один существенный недостаток, заключающийся в том, что если тот же текст, который выбран, существует в другом месте документа, <span> оборачивает дубликат, а не рассматриваемый текст.

Я понимаю, что это может быть против какого-либо протокола stackru, но я публикую здесь без реального понятия о том, как действовать дальше. Моим лучшим предположением было бы как-то найти длину строки перед выделенным текстом (что-то вроде этих строк), но как включить это в саму функцию замены... ну, я мог бы использовать толчок. Кто-нибудь?

(Я вставил решение к предыдущему посту (от Mathias Bynens) ниже.)

    $("p").live("mouseup",function() {
    selection = getSelectedText();
    if(selection.length >= 3) {
        var spn = '<span class="selected">' + selection + '</span>';
        $(this).text($(this).html().replace(selection, spn));

    }
});

//Grab selected text
function getSelectedText(){
    if(window.getSelection){
        return window.getSelection().toString();
    }
    else if(document.getSelection){
        return document.getSelection();
    }
    else if(document.selection){
        return document.selection.createRange().text;
    }
}

3 ответа

Решение

Я обманул и использовал document.execCommand, чтобы обернуть выделенный текст, затем использовал href (третий параметр CreateLink execCommand), чтобы найти элемент, обернуть его тем, что я хотел, и затем удалить ссылку:

$("p").live("mouseup",function() {
    document.execCommand('CreateLink', false, 'uniqueid');
    var sel = $('a[href="uniqueid"]');
    sel.wrap('<span class="selected" />')
    sel.contents().unwrap();
});

document.execCommand поддерживается всеми основными браузерами, поэтому вы должны безопасно взломать его таким образом. В протестированных мною браузерах сам браузер закрывает и открывает для вас теги, поэтому, если вы выбираете от середины одного тега html до середины другого, он должен правильно вкладывать теги.

Я думаю, что ваш ключ в том, чтобы выяснить, что возвращает getSelection и работать с этим.

На Firefox я смог сделать это:

$(document.getSelection().anchorNode).wrap('<div style="color:blue">')

У document.selection.createRange() должна быть похожая вещь, которая позволяет вам найти вещь, которая была выбрана.

так что-то вроде:

$("p").live("mouseup",function() {
    var $sel = getSelectedElem();
    if($.trim($sel.text()).length >= 3) {
        $sel.warp('<span class="selected">');
    }
});

//Grab selected text
function getSelectedElem(){
    if(window.getSelection){
        return $(window.getSelection().anchorNode);
    }
    else if(document.getSelection){
        return $(document.getSelection().anchorNode)
    }
    else if(document.selection){
        //todo figure out what to return here:
        return document.selection.createRange().text;
    }
    return $([]);
}

Как насчет этого?

document.execCommand("insertHTML", false, "<span class='own-class'>"+ document.getSelection()+"</span>");

Источник YeppThat'sMe

Другие вопросы по тегам