2015-02-05 3 views
1

Я пытаюсь выяснить, как twitter выполняет сборку и хэштег с использованием элемента contenteditable. Когда пользователь вводит @ или #, текст с этими специальными символами завернут ссылкой.Contenteditable ошибка при переносе текста с элементом ссылки

В моем примере я могу обернуть текст ссылкой, но есть ошибка, которую я еще не разрешил. Когда текст с @ завернут ссылкой, курсор перемещается в начало <div>.

Я не знаю, чего у меня нет, поэтому мне нужна ваша помощь! И если кто-то может объяснить мне, почему это происходит, это будет приветствоваться.

JSFiddle Link

+0

Найдено, что: http://jsfiddle.net/GEm75/ может быть, это может помочь. – MrUpsidown

+0

Я заменю 'span' на' a', он больше не работает –

+0

Проверьте этот вопрос, может помочь вам http://stackoverflow.com/questions/6249095/how-to-set-caretcursor-position-in-contenteditable- element-div/6249440 # 6249440 –

ответ

2

Добро пожаловать в болезненный мир contenteditable! Я обнаружил такие проблемы, как настоящие постоянно, поскольку решение становится более сложным, особенно если вы озабочены достижением последовательного поведения в кросс-браузере.

Я вижу, что вы запрашиваете разметку, которую хотите вставить в свой <div> со значением, найденным на valueOfQuery. Поскольку вы просто вызываете .html() и вводите это поверх своей предыдущей разметки, ваш курсор не имеет понятия, где разместить себя в этот момент.

Вы должны изучить и ознакомиться с Range API, и в этом примере, мы спасаем наш текущий выбор перед вызовом .html() затем восстановить его потом с помощью этих двух функций - saveSelection и restoreSelection

var saveSelection, restoreSelection; 

if (window.getSelection && document.createRange) { 
    saveSelection = function(containerEl) { 
     var range = window.getSelection().getRangeAt(0); 
     var preSelectionRange = range.cloneRange(); 
     preSelectionRange.selectNodeContents(containerEl); 
     preSelectionRange.setEnd(range.startContainer, range.startOffset); 
     var start = preSelectionRange.toString().length; 

     return { 
      start: start, 
      end: start + range.toString().length 
     }; 
    }; 

    restoreSelection = function(containerEl, savedSel) { 
     var charIndex = 0, range = document.createRange(); 
     range.setStart(containerEl, 0); 
     range.collapse(true); 
     var nodeStack = [containerEl], node, foundStart = false, stop = false; 

     while (!stop && (node = nodeStack.pop())) { 
      if (node.nodeType == 3) { 
       var nextCharIndex = charIndex + node.length; 
       if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) { 
        range.setStart(node, savedSel.start - charIndex); 
        foundStart = true; 
       } 
       if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) { 
        range.setEnd(node, savedSel.end - charIndex); 
        stop = true; 
       } 
       charIndex = nextCharIndex; 
      } else { 
       var i = node.childNodes.length; 
       while (i--) { 
        nodeStack.push(node.childNodes[i]); 
       } 
      } 
     } 

     var sel = window.getSelection(); 
     sel.removeAllRanges(); 
     sel.addRange(range); 
    } 
} else if (document.selection) { 
    saveSelection = function(containerEl) { 
     var selectedTextRange = document.selection.createRange(); 
     var preSelectionTextRange = document.body.createTextRange(); 
     preSelectionTextRange.moveToElementText(containerEl); 
     preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange); 
     var start = preSelectionTextRange.text.length; 

     return { 
      start: start, 
      end: start + selectedTextRange.text.length 
     } 
    }; 

    restoreSelection = function(containerEl, savedSel) { 
     var textRange = document.body.createTextRange(); 
     textRange.moveToElementText(containerEl); 
     textRange.collapse(true); 
     textRange.moveEnd("character", savedSel.end); 
     textRange.moveStart("character", savedSel.start); 
     textRange.select(); 
    }; 
} 

затем мы должны изменить нашу текущую реализацию в keyup следующим

var selection = saveSelection($('#result')[0]); // save cursor pos 

$('#result').html(valueOfQuery); 

restoreSelection($('#result')[0], selection); // restore cursor pos 

JSFiddle Link - рабочий пример

Смежные вопросы