Javascript: как узнать, был ли объект узла вставлен в документ / другой элемент? - PullRequest
12 голосов
/ 12 апреля 2010

Я хотел бы иметь возможность определить, был ли данный узел DOM добавлен / вставлен в другой узел, или он только что из document.createElement () или аналогичный и не был нигде не размещен.

В большинстве браузеров работает только проверка parentNode.

if (!node.parentNode) {
  // this node is not part of a larger document
}

Однако в Internet Explorer кажется, что новые элементы, даже сразу после того, как они были созданы с помощью document.createElement (), уже имеют объект parentNode (типа DispHTMLDocument ??).

Любой другой хороший кросс-браузерный и надежный способ?

Редактировать : похоже, что Internet Explorer неявно создает DocumentFragment (с nodeType, равным 11) и устанавливает его в качестве свойства parentNode узла.

Ответы [ 4 ]

6 голосов
/ 12 апреля 2010

Я думаю, что даже без недостатков IE проверки на наличие parentNode может быть недостаточно. Например:

var d = document.createElement('div');
var s = document.createElement('span');
d.appendChild(s);
if (s.parentNode) {
    // this will run though it's not in the document
}

Если что-то есть в документе, то в конечном итоге одним из его предков станет сам документ. Попробуйте это и посмотрите, как это происходит:

function inDocument(node) {
    var curr = node;
    while (curr != null) {
        curr = curr.parentNode;
        if (curr == document) return true;
    }
    return false;
}

// usage: 
// if (inDocument(myNode)) { .. }

Если вы хотите проверить только на определенную глубину - то есть вы знаете, что ваши вновь созданные элементы не будут вложены дальше, чем фрагмент IE, попробуйте следующее:

function inDocument(node, depth) {
    depth = depth || 1000;
    var curr = node;
    while ((curr != document) && --depth) {
        curr = curr.parentNode;
        if (curr == null) return false;
    }
    return true;
}

inDocument(myNode, 2);  // check only up to two deep.
inDocument(myNode);     // check up to 1000 deep.
5 голосов
/ 12 апреля 2010

Я нашел ответ на свой вопрос. Сожалею! Кажется, в последнее время я много этим занимаюсь.

Фрагменты документа имеют тип_узла 11 и никогда не вставляются в документ, поэтому вы можете проверить его следующим образом:

if (!node.parentNode || node.parentNode.nodeType == 11) {
  // this node is floating free
}

Фрагмент документа необходим только при вставке более одного равноправного узла. IE неявно создает один для всех вновь создаваемых узлов. В любом случае проверка nodeType на 11 работ.

2 голосов
/ 12 апреля 2010

DOM уровня 3 ввел метод compareDocumentPosition для Node, который дает позиционную информацию о том, как два узла связаны друг с другом. Одно из возвращаемых значений - DOCUMENT_POSITION_DISCONNECTED, означающее, что узлы не связаны друг с другом. Можно использовать этот факт, чтобы проверить, не содержится ли узел внутри другого узла, используя:

Boolean(parent.compareDocumentPosition(descendant) & 16)

DOCUMENT_POSITION_DISCONNECTED = 0x01;
DOCUMENT_POSITION_PRECEDING    = 0x02;
DOCUMENT_POSITION_FOLLOWING    = 0x04;
DOCUMENT_POSITION_CONTAINS     = 0x08;
DOCUMENT_POSITION_CONTAINED_BY = 0x10;
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;

Google написал кросс-браузерную реализацию (я думаю, там нет упоминания об IE) функции contains, которую можно найти по адресу http://code.google.com/p/doctype-mirror/wiki/ArticleNodeContains.. Вы можете использовать ее для проверки, является ли данный узел потомок документа

.contains(document, someNode)
0 голосов
/ 10 мая 2011

В какой версии IE вы тестировали это:


if (!node.parentNode) {
  // this node is not part of a larger document
}

возможно, с более старыми версиями IE вы должны попробовать:


if (!node.parentElement) {
  // this node is not part of a larger document
}

вместо.

Хотя в девятках вы получите >> null << с обоими подходами, при условии, что верхний созданный элемент контейнера еще не проанализирован, что, в свою очередь, преобразуется в >> false << именно так, как вы этого хотели. </p>

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