2014-09-18 3 views
1

Есть ли событие DOM, которое срабатывает при изменении элемента parentElement? Если нет, есть ли способ лучше, чем опрос с таймаутом?Обнаружение изменений родительского элемента DOM

Мне особенно интересно узнать, когда parentElement изменяется от null до определенного элемента. То есть, когда элемент DOM привязан к дереву документа где-то.

EDIT

Учитывая вопросы в комментариях, вот пример, который показывает, как создать элемент с nullparentElement:

var element = document.createElement('div'); 

console.assert(element.parentElement == null); 

Родитель установить только один раз он добавляется в DOM:

document.body.appendChild(element); 

console.assert(element.parentElement != null); 

Обратите внимание, что элементы, созданные с помощью jQuery, будут поэтому имеет null родителя при создании:

console.assert($('<div></div>').get(0).parentElement == null); 
+0

Вы пытаетесь выслушать, если элемент обернут в другой? – enguerranws

+2

Как родительский элемент может быть нулевым, если дочерний объект уже находится в DOM? Я что-то упустил? – Krumia

+1

Да, это тоже мой вопрос, все элементы будут иметь хотя бы элемент html в качестве родителя? – enguerranws

ответ

3

AFAIK нет такого «родителя слушателя».

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

http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/

Он использует CSS @keyframes во время вставки и ожидает в результате события анимации, который говорит ему, что элемент был вставлен.

+1

Пожалуйста, добавьте резюме этого внешнего ресурса здесь, в противном случае, когда (не «если») эта страница умирает, ваш ответ становится бесполезным. –

+0

Спасибо за ответ. Это определенно интересная идея. Жаль, что нужно прибегать к этому. Добро пожаловать в SO btw :) –

1

1) таких parentElementHasChanged event не существует.

2) Обходной путь PISquared указал, что это сработает, но выглядит очень странно для меня.

3) На практике нет необходимости в таком событии. Элемент parentChange будет отображаться только в элементе, если это позиция в изменениях DOM. Чтобы это произошло, вам нужно запустить некоторый код для элемента, который делает это, и весь этот код должен использовать родные parent.removeChild(), parent.appendChild, parent.insertBefore() или parent.replaceChild() где-то. Один и тот же код может выполнить обратный вызов после этого, поэтому обратный вызов будет событием.

4) Вы создаете код библиотеки. Библиотека может предоставить одну функцию для всех DOM-вставок/абстракций, которая обертывает четыре родные функции и «запускает событие». Это последнее и единственное, что приходит мне на ум, чтобы избежать частого поиска родительского элемента.

5) Если есть необходимость включать нативную Event API, вы можете создать ParentChanged событие с CustomEvent

element.addEventListener('parentChanged', handler); // only when Event API needed 

function manipulateElementsDOMPosition(element, target, childIndex, callback, detail) { 
    if (!target.nodeType) { 
     if (arguments.length > 4) return element; 
     detail = callback; callback = childIndex; childIndex = target; target = null; 
    } 
    if (typeof childIndex === 'function') detail = callback, callback = childIndex; 
    var oldParent = element.parentElement, 
     newParent = target, 
     sameParent = oldParent === newParent, 
     children = newParent.children, 
     cl = children.length, 
     ix = sameParent && cl && [].indexOf.call(children, element), 
     validPos = typeof childIndex === 'number' && cl <= childIndex; 
    if (childIndex === 'replace') { 
     (newParent = target.parentElement).replaceChild(element, target); 
     if (sameParent) return element; 
    } else { 
     if (samePar) { 
      if (!oldParent || ix == childIndex || 
       childIndex === 'first' && ix === 0 || 
       childIndex === 'last' && ix === (cl - 1)) return element; 
      oldParent.removeChild(element); 
     } else if (oldParent) oldParent.removeChild(element); 
     if (!cl || childIndex === 'last') { 
      newParent.appendChild(element); 
     } else if (childIndex === 'first') { 
      newParent.insertBefore(element, children[0]) 
     } else if (validPos) { 
      newParent.insertBefore(element, children[childIndex]); 
     } else return element;  
    } 
    console.log(element, 'parentElement has changed from: ', oldParent, 'to: ', newParent); 
    element.dispatchEvent(new CustomEvent('parentChanged', detail)); // only when Event API needed 
    if (typeof callback === 'function') callback.call(element, oldParent, newParent, detail); 
    return element; 
} 

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

// remove element 
manipulateElementsDOMPosition(element /*optional:*/, callback, detail); 
// prepend element in target 
manipulateElementsDOMPosition(element, target, 'first' /*optional:*/, callback, detail); 
// append element in target 
manipulateElementsDOMPosition(element, target, 'last' /*optional:*/, callback, detail); 
// add element as third child of target, do nothing when less than two children there 
manipulateElementsDOMPosition(element, target, 3 /*optional:*/, callback, detail); 
// replace a target-element with element 
manipulateElementsDOMPosition(element, target, 'replace' /*optional:*/, callback, detail); 
Смежные вопросы