Есть ли какой-нибудь код, который можно использовать для определения местоположения элемента и смещения по его родительскому объекту и текстовому индексу? - PullRequest
0 голосов
/ 21 января 2010

Я имею в виду, возьмем в качестве примера следующие коды HTML, игнорируя пробелы.

<p>
  paragraph-text
  <span>
   span text
   <i>it</i>
  </span>
</p>

У меня есть объект pNode и индекс «a» в «span text» в pNode.innerHTML в целом, то есть здесь 23, поскольку pNode.innerHTML = «абзац-текст span text it ", тег open span также должен учитываться.

Есть ли какая-нибудь существующая библиотека, которую можно использовать как transform (pElement, 23), чтобы я мог получить ожидаемый элемент и смещение «spanElement and 2»?

Спасибо, аванс. С уважением,

Steve

Ответы [ 2 ]

1 голос
/ 21 января 2010

То, о чем вы говорите, звучит примерно как DOM Range , который реализован во всех основных браузерах, кроме Internet Explorer. Указывать расположение в терминах смещения символов в HTML не очень хорошая идея, поскольку реализации innerHTML значительно различаются. Диапазон DOM имеет начальную и конечную границы, каждая из которых указывается в терминах узла и смещения в этом узле. В случае вашего примера вы можете создать Range, который представляет местоположение:

var span = pNode.childNodes[1];
var spanText = span.firstChild;
var range = document.createRange();

// Next line takes into account whitespace at the start of the text node
range.setStart(spanText, 6); 

// For illustration, create a range that contains the letter "a" and selects it
range.setEnd(spanText, 7);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

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

IE определяет совершенно другой объект, называемый TextRange , который имеет принципиально иной текстовый подход, но служит практически той же цели. Чтобы получить эквивалент TextRange для предыдущего примера, вы можете использовать следующее:

var textRange = document.body.createTextRange();
textRange.moveToElementText(pNode);
textRange.moveStart("character", 17);
textRange.collapse();

// For illustration, create a range that contains the letter "a" and selects it
textRange.moveEnd("character", 1);
textRange.select();
1 голос
/ 21 января 2010

Возможно, вы могли бы сделать это, получив innerHTML, изменив символ, смещение которого вы ищете, а затем повторно проанализировав и расшифровав результирующие текстовые узлы, чтобы найти тот, где закончилось изменение data.

например.

function findTextFromMarkupIndex(el1, ix) {
    // make comparison element
    var el2= document.createElement(el1.tagName);
    // replace any other use of * in its HTML out of the way
    var html= el1.innerHTML.split('*').join('x');
    // insert a * at the given index in HTML
    el2.innerHTML= html.substring(0, ix)+'*'+html.substring(ix);
    // search the resulting DOM for the * and return the matching descandent from the original
    return findTextInComparison(el1, el2, '*');
}

function findTextInComparison(el1, el2, text) {
    for (var i= 0; i<el1.childNodes.length; i++) {
        var child1= el1.childNodes[i];
        var child2= el2.childNodes[i];
        if (child2.nodeType===3) { // TEXT_NODE
            var ix= child2.data.indexOf(text);
            if (ix!==-1)
                return [child1, ix];
        } else if (child2.nodeType===1) { // ELEMENT_NODE
            var result= findTextInComparison(child1, child2, text);
            if (result!==null)
                return result;
        }
    }
    return null;
}

Не проверено, но должно работать, для символов в текстовом содержимом в любом случае. Вы можете расширить его, чтобы также заглянуть внутрь значений атрибутов, если вам это необходимо, но вы не можете делать индексные точки внутри разметки, такие как ссылка на элемент или сущность / символ. Чтобы это работало, вам, по сути, нужно написать целый HTML-парсер.

Это звучит как необычное требование, что именно вы пытаетесь сделать? Индексы в innerHTML могут быть довольно хрупкими, поскольку точный формат вывода разметки для этого свойства вообще не стандартизирован.

...