Javascript для получения текстового значения из элементов HTML не конечного узла (таких как элемент LI) - PullRequest
0 голосов
/ 26 февраля 2012

Я пытаюсь написать скрипт, который будет проходить через исходный код HTML и создать JSON-файл DOM, который затем будет отображаться в виде дерева с помощью d3.js.Проблема, которую я имею, состоит в желании показать не только элемент (TITLE, P, LI и т. Д.), Но и значение элемента.Это достаточно просто, ЕСЛИ я делаю это только для элементов конечного узла (без дочерних элементов).Но иногда мне это нужно для родительских объектов, как в UL ниже для элементов II и B.

        <ul class="level-1">
            <li>I</li>
            <li>II
              <ul class="level-2">
                <li>A</li>
                <li>B
                  <ul class="level-3">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                  </ul>
                </li>
                <li>C</li>
              </ul>
            </li>
            <li>III</li>
        </ul>   

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

   $output.append(', "value": "' + $(child).text() + '"}');

Я пробовал некоторые первоклассные вещи из jQuery, но не смог заставить их работать.Я также хочу сохранить это как можно более общим для подачи в любой источник HTML.Другими словами, я не хочу говорить, что если (nodeName = 'LI') то -для конкретного элемента списка-

  var createJsonOutput = function(domObject) {

    var $currentChildren = domObject.children();
    var $childrenCnt = $currentChildren.length

      $.each($currentChildren, function(idx,child) {
         $output.append('{"name": "' + child.nodeName + '"');

         //does the child have children?
         if ($(child).children().length > 0) {
                $output.append(',"children": [');
                createJsonOutput($(child));
                $output.append(']}');
         } else if (child.nodeName != 'TEXTAREA' && child.nodeName != 'SCRIPT') {
                $output.append(', "value": "' + $(child).text() + '"}');
         } else {
                $output.append('}');
         }

         if ((idx + 1) < $childrenCnt) {
            $output.append(',');
         }
      });
  };

  createJsonOutput($('html'));

ПРИМЕР (неформатированный) JSON:

{"name": "HTML","children": [{"name": "HEAD","children": [{"name": "META", "value": ""},{"name": "TITLE", "value": "Node-Link Tree"},{"name": "SCRIPT"},{"name": "SCRIPT"},{"name": "LINK", "value": ""}]},{"name": "BODY","children": [{"name": "DIV","children": [{"name": "UL","children": [{"name": "LI", "value": "I"},{"name": "LI","children": [{"name": "UL","children": [{"name": "LI", "value": "A"},{"name": "LI","children": [{"name": "UL","children": [{"name": "LI", "value": "1"},{"name": "LI", "value": "2"},{"name": "LI", "value": "3"}]}]},{"name": "LI", "value": "C"}]}]},{"name": "LI", "value": "III"}]}]},{"name": "DIV","children": [{"name": "TEXTAREA"},{"name": "P", "value": "tree time!"}]},{"name": "DIV", "value": ""},{"name": "SCRIPT"}]}]}

Ответы [ 3 ]

2 голосов
/ 26 февраля 2012

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

jQuery.fn.justtext = function() { 
    return $(this).clone()
            .children()
            .remove()
            .end()
            .text();
};

http://viralpatel.net/blogs/2011/02/jquery-get-text-element-without-child-element.html

0 голосов
/ 26 февраля 2012

Я взбил что-то, что, кажется, делает то, что вы хотите.

function objectify(node, recursing) {
    var n, out = [];

    if (node.shift && node.shift.call) {
        while (n = node.shift()) {
            out.push(objectify(n, true));
        }
        return out;
    }

    n = {name: node.tagName};

    if (node.children && node.children.length) {
        n.children = objectify(out.slice.call(node.children), true);
    } else if (node.textContent) {
        n.value = node.textContent;
    }

    return recursing ? n : JSON.stringify(n);
}

// test it
console.log(objectify(document.getElementsByClassName('level-1')[0]));​

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

Вывод из запущенного на вашем UL-примере выше:

{"name":"UL","children":[{"name":"LI","value":"I"},{"name":"LI","children":[{"name":"UL","children":[{"name":"LI","value":"A"},{"name":"LI","children":[{"name":"UL","children":[{"name":"LI","value":"1"},{"name":"LI","value":"2"},{"name":"LI","value":"3"}]}]},{"name":"LI","value":"C"}]}]},{"name":"LI","value":"III"}]}

Это у вас работает?

http://jsfiddle.net/hCDjd/

0 голосов
/ 26 февраля 2012

children () возвращает только элементы-узлы, но, например, II во втором <li/> является текстовым узлом.

Вместо этого вы можете использовать contents () , он также возвращает текстовые узлы

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