Как я могу определить, был ли динамично созданный элемент DOM добавлен к DOM?

Я создал небольшую библиотечную функциональность для решения этих проблем:

Вместо:

public T DifficultCalculation(T a, T b)
{
    T result = a * b + a; // <== WILL NOT COMPILE!
    return result;
}
Console.WriteLine(DifficultCalculation(2, 3)); // Should result in 8.

Вы могли бы написать:

public T DifficultCalculation(Number a, Number b)
{
    Number result = a * b + a;
    return (T)result;
}
Console.WriteLine(DifficultCalculation(2, 3)); // Results in 8.

Вы можете найти исходный код здесь: https://codereview.stackexchange.com/questions/26022/improvement-requested-for-generic-calculator-and-generic-number

39
задан Jason Bunting 12 May 2009 в 03:11
поделиться

7 ответов

ОБНОВЛЕНИЕ: Для всех, кто заинтересован в этом, вот реализация, которую я наконец использовал:

function isInDOMTree(node) {
   // If the farthest-back ancestor of our node has a "body"
   // property (that node would be the document itself), 
   // we assume it is in the page's DOM tree.
   return !!(findUltimateAncestor(node).body);
}
function findUltimateAncestor(node) {
   // Walk up the DOM tree until we are at the top (parentNode 
   // will return null at that point).
   // NOTE: this will return the same node that was passed in 
   // if it has no ancestors.
   var ancestor = node;
   while(ancestor.parentNode) {
      ancestor = ancestor.parentNode;
   }
   return ancestor;
}

Причина, по которой я хотел это, - предоставить способ синтезирования события onload для элементов DOM. Вот эта функция (хотя я использую что-то немного другое, потому что я использую ее вместе с MochiKit ):

function executeOnLoad(node, func) {
   // This function will check, every tenth of a second, to see if 
   // our element is a part of the DOM tree - as soon as we know 
   // that it is, we execute the provided function.
   if(isInDOMTree(node)) {
      func();
   } else {
      setTimeout(function() { executeOnLoad(node, func); }, 100);
   }
}

Например, эту настройку можно использовать следующим образом:

var mySpan = document.createElement("span");
mySpan.innerHTML = "Hello world!";
executeOnLoad(mySpan, function(node) { 
   alert('Added to DOM tree. ' + node.innerHTML);
});

// now, at some point later in code, this
// node would be appended to the document
document.body.appendChild(mySpan);

// sometime after this is executed, but no more than 100 ms after,
// the anonymous function I passed to executeOnLoad() would execute

Надеюсь, что это полезно для кого-то.

ПРИМЕЧАНИЕ: причина, по которой я остановился на этом решении, а не на ответе Даррила , заключалась в том, что метод getElementById работает, только если вы находитесь в одном документе; У меня есть несколько фреймов на странице, и страницы взаимодействуют между собой сложным образом - когда я пробовал это, проблема заключалась в том, что он не мог '

27
ответ дан 27 November 2019 в 02:37
поделиться

Можете Вы не делать document.getElementById('newElementId'); и видеть, возвращает ли это true. В противном случае как Вы говорят, ожидают 100 мс и попробовали еще раз?

8
ответ дан Darryl Hein 12 November 2019 в 03:33
поделиться

Вы могли запросить document.getElementsByTagName (" * ") .length или создать пользовательскую функцию appendChild как следующее:

var append = function(parent, child, onAppend) {
  parent.appendChild(child);
  if (onAppend) onAppend(child);
}

//inserts a div into body and adds the class "created" upon insertion
append(document.body, document.createElement("div"), function(el) {
  el.className = "created";
});

Обновление

запросом, добавляя информацию из моих комментариев в мое сообщение

было комментарий John Resig на библиотеке Peppy по Ajaxian сегодня, который, казалось, предположил, что его библиотека Sizzle могла бы быть в состоянии обработать события вставки DOM. Мне любопытно видеть, будет ли код для обработки IE также

Следование идеи опросить, я считал, что некоторые свойства элемента не доступны, пока элемент не был добавлен к документу (например, element.scrollTop), возможно, Вы могли опросить это вместо того, чтобы делать весь обход DOM.

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

2
ответ дан Leo 12 November 2019 в 03:33
поделиться

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

я видел реализации DOM-изменения, которые наблюдают изменения путем сравнения document.body.innerHTML для длительности сохраненный .innerHTML, который не точно изящен (но работы). Так как Вы в конечном счете собираетесь проверить, был ли определенный узел добавлен уже, то Вы более обеспечены просто проверка что каждое прерывание.

Улучшения, о которых я могу думать, являются использованием .offsetParent, а не .parentNode, поскольку это, вероятно, сократит несколько родителей из Вашего цикла (см. комментарии). Или использование compareDocumentIndex() на всех кроме IE и тестирование .sourceIndex propery для IE (должен быть-1, если узел не находится в DOM).

Это могло бы также помочь: X браузеров compareDocumentIndex implementaion John Resig .

2
ответ дан Borgar 12 November 2019 в 03:33
поделиться

Ни один из DOMNodeInserted или события DOMNodeInsertedIntoDocument не поддерживается в IE. Другое отсутствие от IE [только] показывает DOM, функция compareDocumentPosition, которая разработана, чтобы сделать то, что предлагает ее имя.

Что касается предложенного решения, я думаю, что там не лучше один (если Вы не делаете некоторые злые шутки как перезапись собственных членских реализаций DOM)

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

я также думаю, что проблемой, которую Вы описали, не является проблема, которую Вы имеете, этот надеется быть скорее одним из потенциальных решений Вас проблема. Можно ли, вероятно, объяснить в деталях вариант использования?

-1
ответ дан Sergey Ilinsky 12 November 2019 в 03:33
поделиться

Вы хотите DOMNodeInserted событие (или DOMNodeInsertedIntoDocument).

Редактирование: совершенно возможно, что эти события не поддерживаются IE, но я не могу протестировать это прямо сейчас.

1
ответ дан eyelidlessness 12 November 2019 в 03:33
поделиться

Вот еще одно решение проблемы, извлеченное из кода jQuery. Следующая функция может использоваться, чтобы проверить, прикреплен ли узел к DOM или нет. "отключен".

function isDisconnected( node ) {
    return !node || !node.parentNode || node.parentNode.nodeType === 11;
}

nodeType === 11 определяет DOCUMENT_FRAGMENT_NODE, который является узлом, не связанным с объектом документа.

Для получения дополнительной информации см. Следующую статью Джона Ресига: http://ejohn.org/blog/dom-documentfragments/

0
ответ дан 27 November 2019 в 02:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: