API выбора и диапазона Rangy являются надмножествами стандартных API выбора и диапазона DOM, поэтому применяется документация из таких мест, как MDN ( Диапазон , Выбор ).
Проблема, с которой вы столкнулись, состоит в том, что границы диапазона выражаются в виде смещения внутри содержащего DOM-узла.Например, в приведенном ниже HTML-коде, где символ каретки обозначен как символ канала:
<p>Foo<br>b|ar</p>
... Начальная и конечная границы диапазона каретки идентичны и установлены на смещение 1 на панели «текстового узла»Msgstr ".
Если вы хотите установить позицию в качестве смещения в текстовом содержимом элемента <p>
, вам потребуется выполнить некоторый обход DOM.Я написал реализацию этого на основе другого моего ответа .Это наивная реализация: она не учитывает какой-либо текст, который может быть сделан невидимым (например, CSS или внутри элемента или, например) и может иметь расхождения в браузере (IE и все остальное) с переносами строк, и принимаетне учитывается свернутый пробел (например, 2 или более последовательных пробела, свернутых в одно видимое пространство на странице).Это сложно сделать правильно, поэтому я не рекомендую это делать.Я планирую написать текстовый модуль для Rangy, который будет обрабатывать все это, но я еще не начал его.
http://jsfiddle.net/ee93P/2/
Код:
function setCaretCharIndex(containerEl, index) {
var charIndex = 0, stop = {};
function traverseNodes(node) {
if (node.nodeType == 3) {
var nextCharIndex = charIndex + node.length;
if (index >= charIndex && index <= nextCharIndex) {
rangy.getSelection().collapse(node, index - charIndex);
throw stop;
}
charIndex = nextCharIndex;
}
// Count an empty element as a single character. The list below may not be exhaustive.
else if (node.nodeType == 1
&& /^(input|br|img|col|area|link|meta|link|param|base)$/i.test(node.nodeName)) {
charIndex += 1;
} else {
var child = node.firstChild;
while (child) {
traverseNodes(child);
child = child.nextSibling;
}
}
}
try {
traverseNodes(containerEl);
} catch (ex) {
if (ex != stop) {
throw ex;
}
}
}