2013-05-19 2 views
4

Мне нужно получить текст (или весь внутренний html) узла, усеченный на текущем каретке (текстовый курсор) в элементе с contenteditable, установленным на true. Я пробовал использовать range.setStart() и т. Д., Но я не могу сделать головы и хвосты ...JS - как получить текст между началом узла и текущим курсором (текстовым курсором)?

Редактировать: Для уточнения некоторых событий я хочу, чтобы сценарий извлекал текст с начала узел, который в настоящее время фокусируется на позиции каретки (где мигающая вертикальная линия в настоящее время находится в том случае, если редактируемое поле имеет фокус) и сохраняет ее в переменной. Действие, аналогичное тому, что произойдет, если пользователь нажал Ctrl + Shift + домой и CTRL + C

Пример: Учитывая HTML:

<span contenteditable=true>Hello, world<br> Good bye, World</span> 

И если предположить, что каретка находится между «хорошо» и «до свидания» Я хотел бы получить

"Hello, world<br> Good"

+0

Просьба представить более подробную информацию ... – mate64

+0

Это почти все, что нужно. На некоторых событиях я хочу извлечь текст с начала узла, который в настоящее время сосредоточен на позиции каретки, и использовать его позже в скрипте. Действие похоже на то, что произойдет, если пользователь нажал ctrl + shift + home и ctrl + c –

+0

Что вы подразумеваете под кареткой? Какой узел? – Fresheyeball

ответ

6

Вы можете сделать это довольно легко, используя Rangy и jQuery.

Вот jsFiddle, демонстрирующий этот подход. Комментарии объясняют, что происходит.

$("contenteditable-element").click(function() { 
    // Get the current selection with Rangy 
    var sel = rangy.getSelection() 
    // Insert a temporary caret element at the caret position 
    // (which is inside the contenteditable element) 
    if (sel.rangeCount) sel.getRangeAt(0).insertNode($("<caret />")[0]); 
    // Read the html inside the contenteditable element 
    var innerHTML = $("contenteditable-element").html(); 
    // Clean up, get rid of the caret element 
    $("caret").remove(); 
    // Only keep the text before the first occurrence of the caret element 
    innerHTML = innerHTML.substr(0, innerHTML.indexOf('<caret>')); 
}); 
0

Может быть, это будет толкать вас в правильном направлении: Get a range's start and end offset's relative to its parent container

Я построил скрипку, который показывает функцию при работе с вашим примером: http://jsfiddle.net/Kn8qr/2/

function getCaret(element) { 
var caretOffset = 0; 
if (typeof window.getSelection != "undefined") { 
    var range = window.getSelection().getRangeAt(0); 
    var preCaretRange = range.cloneRange(); 
    preCaretRange.selectNodeContents(element); 
    preCaretRange.setEnd(range.endContainer, range.endOffset); 
    caretOffset = preCaretRange.toString().length; 
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") { 
    var textRange = document.selection.createRange(); 
    var preCaretTextRange = document.body.createTextRange(); 
    preCaretTextRange.moveToElementText(element); 
    preCaretTextRange.setEndPoint("EndToEnd", textRange); 
    caretOffset = preCaretTextRange.text.length; 
} 
var elCont=element.innerHTML; 

var truncCont=elCont.substr(0,caretOffset); 

alert(truncCont); 
} 

Кредит на это уходит автор функции, я просто редактировал ABIT.

0

Посмотрите на этот ответ: https://stackoverflow.com/a/16575647/1532004 Я думаю, что он делает что-то подобное. Перхапы, которые он стреляет по луне, но он получил рабочее решение :)

5

Я хотел бы предложить следующий подход:

  • создать диапазон, охватывающее содержание, которое Вы хотите
  • вызов cloneContents() метод диапазона, чтобы получить DocumentFragment, представляющим содержимое полигона
  • создать <div> или <body> и добавьте к нему фрагмент
  • получите элемент innerHTML

Пример: http://jsfiddle.net/sUSYG/

Код:

function getHtmlPrecedingSelectionIn(container) { 
    var html = ""; 
    if (window.getSelection && document.createRange) { 
     var sel = window.getSelection(); 
     if (sel.rangeCount > 0) { 
      var selRange = sel.getRangeAt(0); 
      var range = document.createRange(); 
      range.selectNodeContents(container); 
      range.setEnd(selRange.startContainer, selRange.startOffset); 

      var frag = range.cloneContents(); 
      var el = document.createElement("body"); 
      el.appendChild(frag); 
      html = el.innerHTML; 
     } 
    } 
    return html; 
} 

Предостережения:

  • это не будет работать в IE < = 8, хотя это не так уж трудно сделать (либо путем кодирования чего-либо с использованием его другого API выбора/диапазона или с помощью библиотеки, такой как Rangy)
  • HTML не гарантированно является подстрокой исходного HTML редактируемого диапазона.
Смежные вопросы