выбор узла и манипуляция вне дома (в чем прикол jQuery?) - PullRequest
4 голосов
/ 02 декабря 2009

Привет, я хотел бы сделать выбор и манипуляции с домом.

Цель состоит в том, чтобы создать мой виджет из dom и вставить его в dom, только когда он будет готов.

Моя проблема в том, что getElementById не поддерживается для фрагмента документа. Я также попробовал createElement и cloneNode, но он тоже не работает.

Я пытаюсь сделать это простым дерьмом. Я привык делать это с помощью jQuery, который прекрасно с этим справляется. Я пытался найти хитрость в исходном коде jQuery, но пока безуспешно ...

Olivier

Ответы [ 6 ]

1 голос
/ 03 декабря 2009

jQuery сначала попытается использовать getElementById, а если это не сработает, то будет искать все элементы DOM, используя getAttribute("id"), пока не найдет нужный вам элемент.

Например, если вы построили следующую структуру DOM, которая не привязана к document и была назначена javascript var widget:

<div id="widget">
    <p><strong id="target">Hello</strong>, world!</p>
</div>

Затем вы можете сделать следующее:

var target;

// Flatten all child elements in the div
all_elements = widget.getElementsByTagName("*");

for(i=0; i < all_elements.length; i++){
    if(all_widget_elements[i].getAttribute("id") === "target"){
        target = all_widget_elements[i];
        break;
    }
}

target.innerHTML = "Goodbye";

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

Надеюсь, это поможет!

1 голос
/ 02 декабря 2009

Я сделал что-то подобное, но не уверен, будет ли это соответствовать вашим потребностям. Создайте «область удержания», такую ​​как равнина <span id="spanReserve"></span> или <td id="cellReserve"></td>. Затем вы можете сделать что-то подобное в функции JS:

var holdingArea = document.getElementById('spanReserve'); holdingArea.innerHTML = widgetHTMLValue;

0 голосов
/ 11 декабря 2009

У вас действительно есть два инструмента для работы: html () и использование обычных операторов манипуляции jQuery для XML-документа, а затем вставка его в DOM.

Для создания виджета вы можете использовать html():

$('#target').html('<div><span>arbitrarily complex JS</span><input type="text" /></div>');

Полагаю, это не то, что вы хотите. Поэтому обратите внимание на дополнительное поведение селектора jQuery: при передаче второго параметра это может быть его собственный фрагмент XML, и в этих документах могут происходить манипуляции. например.

$('<div />').append('<span>').find('span').text('arbitrarily complex JS'). etc.

Все операторы, такие как append, appendTo, wrap и т. Д., Могут работать с подобными фрагментами, а затем их можно вставлять в DOM.

Однако, предостережение: jQuery использует встроенные функции браузера, чтобы манипулировать этим (насколько я могу судить), поэтому вы получаете разные варианты поведения в разных браузерах. Убедитесь, что правильно сформирован XML. У меня даже было отклонение неправильно сформированных фрагментов HTML. В худшем случае вернитесь и используйте конкатенацию строк и метод html().

0 голосов
/ 03 декабря 2009

Современные браузеры (читай: не IE) имеют метод querySelector в Element API. Вы можете использовать это, чтобы получить и элемент по идентификатору в DocumentFragment.

jQuery использует sizzle.js

То, что он делает с DocumentFragments: глубоко просматривает все элементы фрагмента, проверяя, является ли атрибут элемента (в вашем случае «id») тем, который вы ищете. Насколько мне известно, sizzle.js также использует querySelector, если он доступен, для ускорения процесса.

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

0 голосов
/ 02 декабря 2009

EDIT:

как насчет чего-то простого по этим направлениям:

  DocumentFragment.prototype.getElementById = function(id) {
    for(n in this.childNodes){
      if(id == n.id){
        return n;
      }
    }

    return null;
  }

Почему бы просто не использовать jQuery или API выбора в любой другой используемой вами библиотеке? AFAIK все основные библиотеки поддерживают отбор по фрагментам.

Если вы хотите пропустить большую библиотеку, такую ​​как jQ / Prototype / Dojo / и т.д .., тогда вы можете просто использовать Sizzle - это механизм выбора, который поддерживает jQ и Dojo, и предлагается как автономный. Если и об этом не может быть и речи, тогда я полагаю, что вы могли бы погрузиться в источник Sizzle и посмотреть, что происходит. В целом, хотя кажется, что нужно приложить немало усилий, чтобы избежать нескольких сотен тысяч килобайт с добавленной вероятностью того, что код, который вы создадите, будет медленнее во время выполнения, чем вся работа, выполняемая в Sizzle или другой библиотеке с открытым исходным кодом.

http://sizzlejs.com/

О, также ... я думаю (догадываясь), хитрость jQ в том, что элементы не выходят из DOM. Я могу ошибаться, но я думаю, когда вы делаете что-то вроде:

$('<div></div>');

На самом деле он находится в документе DOM, но не является частью узлов body / head. Хотя это может быть совершенно неверным, это всего лишь предположение.

Так что вы меня любопытно хаха. Я взглянул на шипение .. чем ответ - его не используют методы DOM. Кажется, он использует алгоритм, который сравнивает различные свойства DOMNode, сопоставленные с типами селекторов - если только я не пропускаю что-то ... что вполне возможно :-)

Однако, как отмечено ниже в комментариях, кажется, что Sizzle НЕ работает с DocumentFragments ... Итак, вернемся к исходной точке: -)

0 голосов
/ 02 декабря 2009

Звучит так, будто вы делаете что-то правильное. Не уверен, почему это не работает.



// if it is an existing element
var node = document.getElementById("footer").cloneNode(true);

// or if it is a new element use
// document.createElement("div");

// Here you would do manipulation of the element, setAttribute, add children, etc.
node.childNodes[1].childNodes[1].setAttribute("style", "color:#F00; font-size:128px");

document.documentElement.appendChild(node)



...