Как console.log весь HTML DOM дерево в порядке с именами атрибутов - PullRequest
0 голосов
/ 12 мая 2018

Итак, я пытаюсь создать функцию, которая будет console.log всего дерева DOM HTML-страницы. Предполагается выводить имя тега каждого HTML-элемента в том порядке, в котором они отображаются - потомки перед братьями и сестрами + имя атрибута.

У меня есть этот рабочий код:

"use strict";

document.addEventListener("DOMContentLoaded", traverse);

function traverse() {
    let elm = document.documentElement;
    displayInfo(elm);
};

function displayInfo(elm){
    //console.log(elm) 
    /* if (elm.childElementCount>0) {
        let children = Array.from(elm.children);
        console.log(children);
        children.forEach( displayInfo );
    }; */
    if (elm.hasAttributes) {
        //console.log(elm.attributes[0]);
    }; 
    var c = elm.childNodes;
    let i;
    for (i = 0; i < c.length; i++) {
        console.log(c[i].nodeName);
        if (c[i].childElementCount>0) {
            //console.log(c[i].childElementCount);
            if (c[i].hasAttributes) {
                //console.log(c[i].attributes[0]);
            };
            let cc = c[i].children;
            let ii;
            for (ii=0; ii < cc.length; ii++) {
                console.log(cc[ii].nodeName);
                if (cc[ii].hasAttributes) {
                    //console.log(cc[ii].attributes[0]);
                };
                if (cc[ii].childElementCount>0) {
                    //console.log(cc[ii].childElementCount);
                    let ccc = cc[ii].children;
                    let iii;
                    for (iii=0; iii < ccc.length; iii++) {
                        console.log(ccc[iii].nodeName);
                        if (ccc[iii].hasAttributes) {
                            //console.log(ccc[iii].attributes[0]);
                        };
                        if (ccc[iii].childElementCount>0) {
                            //console.log(ccc[iii].childElementCount);
                            let cccc = ccc[iii].children;
                            let iiii;
                            for (iiii=0; iiii < cccc.length; iiii++) {
                                console.log(cccc[iiii].nodeName);
                                if (cccc[iiii].hasAttributes) {
                                    //console.log(cccc[iiii].attributes[0]);
                                };
                                if (cccc[iiii].childElementCount>0) {
                                    console.log(cccc[iiii].childElementCount)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
 };

Проблема в том, что я ужасно повторяюсь, плюс я вручную устанавливаю, насколько «глубоко» он будет проходить. Есть ли способ объявить только одну функцию?

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

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Существует только API для этого, который является гораздо более мощным, чем все, что вы могли бы попытаться построить самостоятельно: TreeWalker .

var walker = document.createTreeWalker(
  document.documentElement,
  NodeFilter.SHOW_ELEMENT // only elements
);
while (walker.nextNode()) {
  let current = walker.currentNode;
  console.log(
    current.tagName,
    [...current.attributes].map(({value,name}) => `${name}=${value}`).join()
  );
}
<article>
  <div id="container">container content
    <span>one span</span>
    <span class="nest1">nest1 span<span class="nest2">nest2 span</span></span>
  </div>
</article>
0 голосов
/ 12 мая 2018

Обратите внимание, что hasAttributes - это функция , а не свойство. element.hasAttributes всегда будет true.

Используйте рекурсию, как это:

function displayInfo(node) {
  console.log(node.nodeName);
  if (node.nodeType === 3) {
    console.log('Text node: ' + node.textContent);
    return;
  }
  if (node.hasAttributes()) {
    [...node.attributes].forEach(({ name, value }) => console.log(`${name}=${value}`));
  }
  node.childNodes.forEach(displayInfo);
}
displayInfo(document.documentElement);
<article>
<div id="container">container content
<span>one span</span>
<span class="nest1">nest1 span<span class="nest2">nest2 span</span></span>
</div>
</article>

Упомянутый мной ярлык continue будет выглядеть примерно так:

for (i = 0; i < c.length; i++) {
  console.log(c[i].nodeName);
  if (c[i].childElementCount === 0) continue;
  //console.log(c[i].childElementCount);
  if (c[i].hasAttributes) {
    //console.log(c[i].attributes[0]);
  };
  let cc = c[i].children;

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

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