Добавить теги вокруг выделенного текста в элементе

Как добавить теги <span> вокруг выделенного текста внутри элемента?

Например, если кто-то выделяет "Джон", я хотел бы добавить вокруг него теги span.

HTML

<p>My name is Jimmy John, and I hate sandwiches. My name is still Jimmy John.</p>

JS

function getSelectedText() {
  t = (document.all) ? document.selection.createRange().text : document.getSelection();

  return t;
}

$('p').mouseup(function(){
    var selection = getSelectedText();
    var selection_text = selection.toString();
    console.log(selection);
    console.log(selection_text);

    // How do I add a span around the selected text?
});

http://jsfiddle.net/2w35p/

Здесь есть один и тот же вопрос: jQuery выберите текст и добавьте к нему пробел в абзаце, но он использует устаревшие методы jquery (например, live) и принятые у ответа есть ошибка.

Ответы

Ответ 1

У меня есть решение. Получите Range файла selecion и deleteContent, а затем вставьте в него новый span.

$('body').mouseup(function(){
    var selection = getSelectedText();
    var selection_text = selection.toString();

    // How do I add a span around the selected text?

    var span = document.createElement('SPAN');
    span.textContent = selection_text;

    var range = selection.getRangeAt(0);
    range.deleteContents();
    range.insertNode(span);
});

Вы можете увидеть DEMO здесь

UPDATE

Абсолютно, выбор будет удаляться одновременно. Поэтому вы можете добавить диапазон выбора с помощью js-кода, если хотите.

Ответ 2

Вы можете просто сделать это.

$('body').mouseup(function(){
   var span = document.createElement("span");
    if (window.getSelection) {
        var sel = window.getSelection();
        if (sel.rangeCount) {
            var range = sel.getRangeAt(0).cloneRange();
            range.surroundContents(span);
            sel.removeAllRanges();
            sel.addRange(range);
        }
    }
});

Fiddle

Ссылка Обтекание выделенного текста node с диапазоном

Ответ 3

Вы можете попробовать следующее:

$('body').mouseup(function(){
   var selection = getSelectedText();
   var innerHTML = $('p').html();
   var selectionWithSpan = '<span>'+selection+'</span>';
   innerHTML = innerHTML.replace(selection,selectionWithSpan);
   $('p').html(innerHTML);    
});

а в вашем fiddle вы снова открываете новый <p> вместо закрытия </p>. Обновите это, пожалуйста.

Ответ 4

ЭТО РАБОТЫ (в основном *)!! (технически, он делает то, что вы хотите, но ему нужен HALP!)

JSFiddle

Это добавляет <span ...> и </span> правильно, даже если в вашем элементе есть несколько экземпляров выделения, и вы заботитесь только об выбранном экземпляре!

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

Я могу добавить теги span, но мне нелегко заменить обычный текст на html. Может быть, вы можете понять это? Мы почти там!! Это использует узлы из getSelection. Узлы могут работать с трудом.

document.getElementById('d').addEventListener('mouseup',function(e){
    var s = window.getSelection();
    var n = s.anchorNode; //DOM node
    var o = s.anchorOffset; //index of start selection in the node
    var f = s.focusOffset; //index of end selection in the node
    n.textContent = n.textContent.substring(0,o)+'<span style="color:red;">'
        +n.textContent.substring(o,f)+'</span>'
        +n.textContent.substring(f,n.textContent.length);
        //adds the span tag
    // document.getElementById('d').innerHTML = n.textContent;
    // this line messes stuff up because of the difference 
    // between a node textContent and it innerHTML.
});