2010-05-26 5 views
1

Я хочу, чтобы получить все узлы, присутствующие в частности DIV element.see ниже тестовой страницы (FireFox)getElementsByTagName не возвращает узлы комментариев в JavaScript

<HTML> 
<HEAD> 
    <TITLE> New Document </TITLE> 
    <META NAME="Generator" CONTENT="EditPlus"> 
    <META NAME="Author" CONTENT=""> 
    <META NAME="Keywords" CONTENT=""> 
    <META NAME="Description" CONTENT=""> 
<script> 
function processTags() 
{ 
    var chNodes = document.getElementById('foo').childNodes ; 
console.log(chNodes); 
console.log("------"); 

    var chNodes = document.getElementById('foo').getElementsByTagName('*') ; 
console.log(chNodes); 
} 
</script> 
</HEAD> 

<BODY onload="processTags();"> 
    <div id="foo"> 
    <!-- this is a comment -->this is some text ? <span>this is inside span</span> 
    <div><p>test</p>test<div> 
    </div> 
</BODY> 
</HTML> 

Но это не дает мне комментарии тег .. Каков наилучший способ получить все теги?

+1

BTW никто не делает все-заглавные буквы имен HTML элемент больше. Просто говорю'. ;) – Tomalak

+0

@Tomalak: возможно, это был скопированный и слегка измененный 'innerHTML' /' внешнийHTML'? :-P –

ответ

4

Сердце проблемы заключается в том, что эти методы ...

document.getElementById(...) 
document.getElementsByTagName(...) 

... вернуться элементы, как указано по их именам. Однако комментарии и текстовые узлы не являются элементами. Это узлы, но не элементы.

Так что вам нужно сделать некоторые традиционные старомодные сценарии DOM, используя childNodes, как предложил Винсент Роберт. Так - как вы указываете в комментарии к нему - что .childNodes идет только один «слой» глубок, вам нужно определить рекурсивную функцию, чтобы найти комментарий узлы: (я назвать рудник document.getCommentNodes())

document.getCommentNodes = function() { 
    function traverseDom(curr_element) { // this is the recursive function 
     var comments = new Array(); 
     // base case: node is a comment node 
     if (curr_element.nodeName == "#comment" || curr_element.nodeType == 8) { 
      // You need this OR because some browsers won't support either nodType or nodeName... I think... 
      comments[comments.length] = curr_element; 
     } 
     // recursive case: node is not a comment node 
     else if(curr_element.childNodes.length>0) { 
      for (var i = 0; i<curr_element.childNodes.length; i++) { 
       // adventures with recursion! 
       comments = comments.concat(traverseDom(curr_element.childNodes[i])); 
      } 
     } 
     return comments; 
    } 
    return traverseDom(document.getElementsByTagName("html")[0]); 
} 
+1

Вы тестировали это в IE? В документации MSDN для [childNodes] (http: //msdn.microsoft.com/en-us/library/ms537445 \ (v = VS.85 \) .aspx) указано, что он возвращает только элементы HTML и объекты TextNode через childNodes. Документация для [nodeType] (http: //msdn.microsoft.com/en-us/library/ms534191 \ (v = VS.85 \) .aspx) соответствует этому, показывая возможные значения как «1 (Элемент) 'или' 3 (TextNode) '. Пища для размышлений ... –

+0

@ У Энди Е - Нет, я этого не делал! Я считал само собой разумеющимся, что он будет работать в IE, поскольку я использовал что-то похожее, чтобы найти текстовые узлы раньше :(Хороший звонок. –

3

Вы можете использовать .childNodes для извлечения всех детей вместо .getElementsByTagName('*'), который будет возвращать только дочерние элементы.

Вот функция для извлечения всех потомков узла DOM:

function getDescendantNodes(node) 
{ 
    var ret = []; 
    if(node) 
    { 
     var childNodes = node.childNodes; 
     for(var i = 0, l = childNodes.length; i < l; ++i) 
     { 
      var childNode = childNodes[i]; 
      ret.push(childNode); 
      ret = ret.concat(getDescendantNodes(childNode)); 
     } 
    } 
    return ret; 
} 

Использование:

getDescendantNodes(document.getElementById("foo")); 
+0

.childNodes работает только на одном уровне – Sourabh

+2

@Sourabh - Тогда пришло время для приключений с рекурсией! –

+0

добавил рекурсивную версию для извлечения всех потомков узла –

0

Вы должны были бы использовать innerHtml, а затем использовать парсер, чтобы найти комментарии в Это.

+0

Это интересная идея; поскольку комментарии не могут быть определены внутри себя, их, вероятно, можно было бы извлечь или проанализировать гораздо легче, чем полностью разобрать HTML. –

1

Типы узлов (не исчерпывающий):

  • Элемент
  • Текст
  • Комментарий

getElementsByTagName только поднимает узлы элемента. childNodes, nextSibling и т. Д. Забрать все виды узлов. nextElementSibling только подбирает элементы.

0

Комментарии являются узлами в дереве DOM, но у них нет имени тега. Метод getElementsByTagName возвращает только узлы с именем тега.

Если вам нужны все узлы, вам нужно пройти дерево DOM, используя коллекцию childNodes каждого элемента.

3

Если вы не заботитесь о IE, вы могли бы избежать рекурсивного подхода и, возможно, повышения производительности (непроверенные) с помощью TreeWalker с помощью document.createTreeWalker:

function getCommentNodes(containerNode) { 
    var treeWalker = document.createTreeWalker(containerNode, 
     NodeFilter.SHOW_COMMENT, null, false); 
    var comments = []; 
    while (treeWalker.nextNode()) { 
     comments.push(treeWalker.currentNode); 
    } 
    return comments; 
} 

console.log(getCommentNodes(document.body)); 
0
var getComments = function(oNode) { 
    var oChild, 
     aComments = []; 
    oNode = oNode || document; 
    for (var n=0; n<oNode.childNodes.length; n++) { 
     oChild = oNode.childNodes[n]; 
     switch (oChild.nodeType) { 
      case 1: // Element 
       aComments = aComments.concat(getComments(oChild)); 
       break; 
      case 8: // Comment 
       aComments.push(oChild); 
       break; 
     } 
    } 
    return aComments; 
} 
Смежные вопросы