Contenteditable DIV - как определить, находится ли курсор в начале или конце содержимого
У меня есть contenteditable div, который содержит типичный редактор WYSIWYG html (полужирный, якоря, списки).
Мне нужно определить, является ли текущий курсор onKeyDown в начале и в конце div. Причина этого заключается в том, что на основе позиции курсора и нажатой клавиши я могу объединить этот div с предыдущим div в backspace или создать новый следующий div при вводе.
я возился с диапазонами, но когда вы работаете с html внутри стихии все довольно сложно.
Я надеюсь, что я должен упустить какое-то простое решение.
есть ли относительно простой способ определить это - я открыт для использования библиотеки как стройный.
спасибо!
Edit: я думаю что-то в этом роде:
$('.mycontenteditable').bind('keydown', handle_keydown)
handle_keydown = function(e) {
range = window.getSelection().getRangeAt(0)
start_range = document.createRange()
start_range.selectNodeContents(this.firstChild)
start_range.collapse(true) // collapse to start
is_start = start_range.compareBoundaryPoints(Range.START_TO_START,range)
end_range = document.createRange()
end_range.selectNodeContents(this.lastChild)
end_range.collapse(false)
is_end = end_range.compareBoundaryPoints(Range.END_TO_END,range)
}
Я собираюсь столкнуться с какими-либо странными проблемами с чем-то вроде этого?
2 ответов
Я бы использовал аналогичный подход к вашему, за исключением использования toString()
метод Range
объектов, а не cloneContents()
чтобы избежать ненужных клонирования. Кроме того, в IE text собственность TextRange
.
обратите внимание, что это будет иметь проблемы, когда есть начальные и/или конечные разрывы в содержании, потому что toString()
метод комплекс работает так же, как textContent
свойство узла и учитывает только текстовые узлы, поэтому не принимая во внимание разрывы строк, подразумеваемые <br>
или элементы блока. Также CSS не учитывается: например, текст внутри элементов, которые скрыты через display: none
включен.
вот пример:
live demo:http://jsfiddle.net/YA3Pu/1/
код:
function getSelectionTextInfo(el) {
var atStart = false, atEnd = false;
var selRange, testRange;
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount) {
selRange = sel.getRangeAt(0);
testRange = selRange.cloneRange();
testRange.selectNodeContents(el);
testRange.setEnd(selRange.startContainer, selRange.startOffset);
atStart = (testRange.toString() == "");
testRange.selectNodeContents(el);
testRange.setStart(selRange.endContainer, selRange.endOffset);
atEnd = (testRange.toString() == "");
}
} else if (document.selection && document.selection.type != "Control") {
selRange = document.selection.createRange();
testRange = selRange.duplicate();
testRange.moveToElementText(el);
testRange.setEndPoint("EndToStart", selRange);
atStart = (testRange.text == "");
testRange.moveToElementText(el);
testRange.setEndPoint("StartToEnd", selRange);
atEnd = (testRange.text == "");
}
return { atStart: atStart, atEnd: atEnd };
}
вот как я решил это. Мое предлагаемое выше решение иногда работало, но было много крайних случаев, поэтому я в конечном итоге рассмотрел, сколько текста было до или после курсора, и если это было 0 символов, то я был в начале или конце:
handle_keydown = function(e) {
// Get the current cusor position
range = window.getSelection().getRangeAt(0)
// Create a new range to deal with text before the cursor
pre_range = document.createRange();
// Have this range select the entire contents of the editable div
pre_range.selectNodeContents(this);
// Set the end point of this range to the start point of the cursor
pre_range.setEnd(range.startContainer, range.startOffset);
// Fetch the contents of this range (text before the cursor)
this_text = pre_range.cloneContents();
// If the text's length is 0, we're at the start of the div.
at_start = this_text.textContent.length === 0;
// Rinse and repeat for text after the cursor to determine if we're at the end.
post_range = document.createRange();
post_range.selectNodeContents(this);
post_range.setStart(range.endContainer, range.endOffset);
next_text = post_range.cloneContents();
at_end = next_text.textContent.length === 0;
}
все еще не совсем уверен, что есть какие - либо другие крайние случаи, поскольку я не совсем уверен, как это проверить, так как это требует взаимодействия с мышью-вероятно, есть библиотека, чтобы справиться с этим где-то.