Восстановление диапазона с помощью узла, startOffset и endOffset

Я пытаюсь восстановить Range() объект в браузере клиентов с помощью websockets.

https://jsfiddle.net/k36goyec/

сначала я получаю объект диапазона в своем браузере и узел что диапазон начинается в:

var range = window.getSelection().getRangeAt(0);
var node  = range.startContainer

Я передаю три параметра через websockets функции Range builder в браузере клиентов.

var text        = node.parentNode.textContent;
var startOffset = range.startOffset
var endOffset   = range.endOffset

эти данные передаются в мой buildRange функция:

/**
 *
 */
buildRange: function(text, startOffset, endOffset){
    var node = this.getNodeByText(text); // get the Node by its contents

    var range = document.createRange();
    range.setStart(node, startOffset);
    range.setEnd(node, endOffset);

    span = document.createElement('span');
    span.style.backgroundColor = this.color;
    $(span).addClass('hl');
    range.surroundContents(span);
},

как вы можете видеть ниже, я получаю узел в браузере клиентов перебрав все элементы на странице, и сравнение его содержания с текстом:

/**
 *
 */
getNodeByText: function(text){
    var all = document.getElementsByTagName("*");
    for (var i = 0; i < all.length; i++) {
        if (all[i].textContent === text) {
            return all[i];
        }

    }
},

Я использую setStart () и setEnd (), чтобы установить диапазон моего выбора на узле.

проблемы!

на

2 ответов


другие уже указали, что непосредственная проблема, с которой вы столкнулись, заключается в том, что при сохранении данных диапазона вы получаете смещение в текстовый узел, но при попытке воссоздать диапазон вы используете смещение в качестве индекса в элемент, и она падает. Если вы исправите это, вы исправите свою непосредственную проблему.

ваш общий подход, однако, хрупкий.

рассмотрим документ с этого:

<p>Farmer John has a thousand <b>goats</b></p>
<p>and his <b>goats</b> ate all his oats.</p>

некоторые проблемы, с моей головы:

  1. Если вы выберете 2-й "козел", ваш алгоритм воссоздаст диапазон на первых" козах", потому что он ищет только элемент, который имеет тот же текст, что и исходный диапазон.

  2. Если вы выбираете диапазон, который начинается с "и "во 2-й строке и заканчивается на" ate", смещения, которые вы получаете из своего исходного диапазона, индексируются в два разных текстовых узлов: один текстовый узел, содержащий текст and his и второй текстовый узел, содержащий текст ate all his oats. ваш алгоритм предполагает, что есть только одна заметка для восстановления в месте назначения. Их может быть несколько.

    та же проблема возникает, если у вас есть выбор, который начинается с одного из выделенных жирным шрифтом слов и заканчивается снаружи.

чтобы иметь что-то надежное, вам нужно выполнить сериализацию диапазона в источнике, который записывает достаточно информации, чтобы обеспечить точную десериализацию в назначение.

есть много способов сделать это. Одним из способов может быть обеспечение того, чтобы одна и та же структура DOM присутствовала в месте происхождения и назначения, и использовать модуль сериализации библиотеки Rangy для выполнения сериализации и десериализации. Если вы можете обеспечить одинаковую структуру DOM на обоих концах, это то, что я бы использовал.

Если вы не можете обеспечить такую же структуру DOM на обоих концах, то вы должны свернуть свой собственный. Вы должны определить ссылку точки, которые одинаковы на обоих концах и идентифицируют начальный узел/смещение и конечный узел/смещение диапазона относительно этих контрольных точек.


решение проблемы:

Я просто не могу надежно получить текстовый узел, я могу получить только сам узел элемента...

чтобы получить фактический текстовый узел ,вы можете использовать.свойство childnodes элемента. Если у вас есть более одного, вы можете проверить nodeType, чтобы определить, какие текстовые узлы. Чтобы узнать, что находится в любом текстовом узле, проверьте свойство nodeValue.