Расчет смещения выделения текста в элементах гнезда в Javascript - PullRequest
6 голосов
/ 30 июля 2010

Проблема

Я пытаюсь выяснить смещение выделения из определенного узла с помощью JavaScript.

Скажем, у меня есть следующий HTML

<p>Hi there. This <strong>is blowing my mind</strong> with difficulty.</p>

Если я выбираю из , дуя до сложности , это дает мне смещение от узла #text внутри <strong>.Мне нужно смещение строки от <p> s innerHTML и длины выделения.В этом случае смещение будет равно 26, а длина - 40.

Моей первой мыслью было что-то сделать со смещением строк и т. Д., Но вы могли легко получить что-то вроде

<p> Hi there. This <strong>is awesome</strong>. For real. It <strong>is awesome</strong>.</p>
* 1020.* который сломал бы этот метод, потому что есть идентичные узлы.Мне также нужна опция, чтобы выбрасывать узлы.Скажем, у меня есть что-то вроде этого
<p>Hi there. <a href="#" rel="inserted">This <strong>is blowing</a> my mind</strong> with difficulty.</p>

Я хочу выбросить элементы с rel="inserted", когда я делаю вычисления.Я все еще хочу 26 и 40 в результате.

То, что я ищу

Решение должно быть рекурсивным.Если бы было <span> с <strong> в нем, ему все равно нужно было бы перейти к <p>.

. В решении необходимо удалить длину любого элемента с помощью rel="inserted".Содержание важно, но сами теги не являются.Все остальные теги важны.Я бы настоятельно предпочел не удалять какие-либо элементы из DOM, когда я делаю все это.

Я использую document.getSelection(), чтобы получить объект выбора.Это решение должно работать только в WebKit.jQuery - вариант, но я бы предпочел его без него, если это возможно.

Буду признателен за любые идеи.

Я не контролирую HTML, над которым я все это делаю.

Ответы [ 5 ]

3 голосов
/ 31 июля 2010

Кажется, я решил свою проблему. Я закончил, не рассчитав смещение, как я изначально планировал. Я храню «путь» из чанка (он же <p>). Вот код:

function isChunk(node) {
  if (node == undefined || node == null) {
    return false;
  }
  return node.nodeName == "P";
}

function pathToChunk(node) {
  var components = new Array();

  // While the last component isn't a chunk
  var found = false;
  while (found == false) {
    var childNodes = node.parentNode.childNodes;
    var children = new Array(childNodes.length);
    for (var i = 0; i < childNodes.length; i++) {
      children[i] = childNodes[i];
    }        
    components.unshift(children.indexOf(node));

    if (isChunk(node.parentNode) == true) {
      found = true
    } else {
      node = node.parentNode;
    }
  }

  return components.join("/");
}

function nodeAtPathFromChunk(chunk, path) {
  var components = path.split("/");
  var node = chunk;
  for (i in components) {
    var component = components[i];
    node = node.childNodes[component];
  }
  return node;
}

Со всем этим вы можете сделать что-то вроде этого:

var p = document.getElementsByTagName('p')[0];
var piece = nodeAtPathFromChunk(p, "1/0"); // returns desired node
var path = pathToChunk(piece); // returns "1/0"

Теперь мне просто нужно расширить все это, чтобы поддержать начало и конец выделения. Это отличный строительный блок.

3 голосов
/ 30 июля 2010

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

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

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

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

1 голос
/ 05 апреля 2012

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

var text = window.getSelection();
var start = text.anchorOffset;
alert(start);
var end = text.focusOffset - text.anchorOffset;
alert(end);
0 голосов
/ 30 июля 2010

Просто проверьте, является ли выбранный вами элемент абзацем, а если нет, то используйте метод Element.up () в Prototype для выбора родительского элемента первого абзаца.

Например:

if(selected_element.nodeName != 'P') {
  parent_paragraph = $(selected_element).up('p');
}

Тогда просто найдите разницу между смещением текста parent_paragraph и смещением текста вашего selected_element.

0 голосов
/ 30 июля 2010

Может быть, вы могли бы использовать селекторы jQuery, чтобы игнорировать rel = "вставлен"?

$('a[rel!=inserted]').doSomething();

http://api.jquery.com/attribute-not-equal-selector/

Какой код вы используете сейчас, чтобы выбрать из ударов до сложности ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...