Объект диапазона: различия между браузерами на базе Webkit и Mozilla

на данный момент у меня есть некоторые проблемы с написанием абстрактного слоя для браузеров Mozilla и Webkit для использования объекта DOM-диапазона (получение и обработка пользовательских селекций).

Я также пытался взглянуть на фреймворки, такие как Rangy, но это кажется далеко не сложным для моей задачи (я понятия не имею, где именно в коде найти нужную мне информацию. Если бы кто-нибудь мог дать мне подсказку, я был бы благодарен!).

Я хочу просто так:

  • вернуть ссылку на текстовый узел, в котором начинается выделение, и его смещение
  • вернуть ссылку на текстовый узел, в котором заканчивается выделение, и его смещение

Пока что мой слой выглядит следующим образом:

var SEL_ABSTR = {
get_selection: function(window_object) {
    return window_object.getSelection();
},
get_range: function(selection) {
    return (selection.getRangeAt) ? selection.getRangeAt(0) : selection.createRange();
},
get_range_info: function(range, div_ele) {
    var first_node, start_offset;
    var last_node, end_offset;

    if (range.startContainer == div_ele) {
        // selections affects the containing div
        first_node = div_ele.childNodes[0];
        last_node = first_node;
        start_offset = 0;
        end_offset = first_node.nodeValue.length;
    } else if (range.startOffset == range.startContainer.nodeValue.length && range.endOffset == 0) {
        // known bug in Firefox
        alert('firefox bug');
        first_node = range.startContainer.nextSibling.childNodes[0];
        last_node = first_node;
        start_offset = 0;
        end_offset = first_node.nodeValue.length;
    } else {
        first_node = range.startContainer;
        last_node = range.endContainer;
        start_offset = range.startOffset;
        end_offset = range.endOffset;
    }

    return {
        first_node: first_node,
        start_offset: start_offset,
        last_node: last_node,
        end_offset: end_offset,
        orig_diff: end_offset - start_offset
    };
},
};

Я обнаружил две ошибки Mozilla:

  1. Иногда, когда весь текстовый узел (если он единственный) выделен внутри содержащего div, я возвращаю ссылку на этот div вместо ссылки на текстовый узел. Теперь я могу с этим справиться и возвращать ссылку на потомка div, которым является текстовый узел

  2. Иногда я возвращаю ссылку на предыдущего брата с смещением == prevSibling.length и ссылку на nextSibling со смещением == 0. Но правильная ссылка будет посередине. Я тоже могу с этим справиться.

Итак, что еще есть для Mozilla? Вебкит работает отлично!

Надо полагать, что объект DOM-диапазона является стандартным (и я говорю не об IE, а о другой задаче ...)

приветствует!


более конкретные детали здесь:

Это не было предназначено для критики Rangy. Так что мне жаль, если это прозвучало так. Могу себе представить, что работать с этими различными API нелегко само по себе.

Вы правы, я не уточнял задачу, которую я пытаюсь выполнить. Моя структура довольно проста: У меня есть div (с атрибутом contenteditable=true) и текст внутри этого div (один текстовый узел в начале).

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

<div contenteditable="true">
hello I am 
<span class="red">text but I am also <span class="underline">underlined</span></span>
<span class="underline"> also without color</span>
</div>

Алгоритм теперь отлично работает для "симметричных" случаев: Я могу построить сложную структуру, а затем отменить ее. Он прекрасно работает для Safari и Chrome. Теперь, конечно же, мне нужно продолжить разработку алгоритма.

Но пока что у меня проблемы с Mozilla, потому что я не понимаю систему для объектов DOM-диапазона: startContainer, endContainer, startOffset, endOffset

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

  • что startContainer и endContainer всегда указывают на текстовый узел, на который влияет выделение мышью (пустых пролетов нет, они всегда содержат либо другие пролеты, либо текстовый узел), отмечая начало и конец всего выделения
  • что startOffset и endOffset указывают на положение выделения внутри текстового узла в начале и в конце

В вышеприведенном размещенном коде я выделил два случая, в которых Mozilla действует не так, как в webkit.

Так что, если бы я знал правила Mozilla DOM-диапазона, я бы мог иеградировать их в своем слое, чтобы поведение было одинаковым для webkit'а и Mozilla.

Спасибо большое за ответ.

6
задан Tobi 20 September 2011 в 17:33
поделиться