1

Need to get all direct nodes from DOM element and don't actually know, how it many and what kind they are. .contents()? Ok, let's see..

$('<div />').html('<p>p</p>').contents() -> [<p>​p​</p>​]

Ok.

$('<div />').html('textNode').contents() -> []

WTF?

$('<div />').html('textNode').append('another').contents() -> ["textNode", "another"]

Ok, so what about single text node?

tshepang
  • 12,111
  • 21
  • 91
  • 136
extempl
  • 2,987
  • 1
  • 26
  • 38
  • 1
    If you use `$('
    ').html('textNode').appendTo('body')` then `.contents()` will have the `textNode`. Seems as jQuery is handling this different as one would expect as long as the structure is not part of the dom.
    – Yoshi Apr 19 '12 at 14:39
  • As I recognised, my problem based not on jQuery, but on JavaScript. `q = $('
    ').html('dsfdsf')[0]` `q.childNodes` -> `[]`, but `console.dir(q)` return HTMLDivElement which has one childNode. Any thoughts about it?
    – extempl Apr 19 '12 at 14:49
  • I work with current HTML structure before appending it to DOM, so `appendTo('body')` not a solution – extempl Apr 19 '12 at 14:50
  • My comment wasn't meant as a solution, more as a reference/note. And by the way you're definitely dealing with a jQuery thing here. – Yoshi Apr 19 '12 at 14:56
  • >definitely dealing with a jQuery `div = document.createElement('div'); div.appendChild(document.createTextNode('dsf')); div.childNodes;` -> `[]` – extempl Apr 19 '12 at 15:01

2 Answers2

2

I don't know if this is helpful. A while ago I built a Document Fragment generator using JSON styled input. I also wrote a (somewhat working) reverse function for it so you could turn your nodeList into a JSON string.

https://gist.github.com/2313580

var reverseFunction = function(DOM /* DOM tree or nodeList */) {
    var tree = [];[].forEach.call(DOM, function(obj) {
        if (obj instanceof Text) {
            tree.push({
                'textContent': obj.textContent
            });
        } else {
            var tmp = {};
            tmp['tagName'] = obj.nodeName;
            for( var data in obj.dataset ) {
                tmp['data-' + data] = obj.dataset[data];
            }
            for (var i = 0, l = obj.attributes.length; i < l; i++) {
                var key = obj.attributes[i].name,
                    val;
                if (key.indexOf('data-') === -1) {
                    switch (key) {
                    case ('class'):
                        key = 'className';
                        break;
                    case ('style'):
                        val = {};
                        obj.attributes[i].value.split(';').forEach(function(rule) {
                            var parts = rule.split(':');
                            val[parts[0]] = parts[1];
                        });
                        break;
                    };
                    tmp[key] = val || obj.attributes[i].value;
                }
            }
            if (obj.childNodes.length > 0) {
                tmp['childNodes'] = reverseFunction(obj.childNodes);
            }
            tree.push(tmp);
        }
    });
    return tree;
};

This does find textNodes and separates them... You may be able to extract something from it.

Update: to answer a comment in your question above...

var div = document.createElement('div');
div.appendChild(document.createTextNode('dsf'));
console.log( div.childNodes.length, div.childNodes, div.childNodes[0].textContent);​

I hope this makes a bit more sense to you know. The array appears empty in the console but it is not. check the length and attempt to access it and you will see.

rlemon
  • 17,518
  • 14
  • 92
  • 123
  • Your script seems legit. `q = $('
    ').html('dsfdsf'); w = reverseFunction(q); w[0].chidlNodes` -> object with single childNode. But it would be nice to understand why it is act so strange
    – extempl Apr 19 '12 at 14:57
  • In my last comment to the question there is version without even touching jQuery. And acting the same - if add another appendChild it will return both, but if only one - empty array. – extempl Apr 19 '12 at 15:07
  • Yep, it helps. Then i can iterate it through `for`. Thanks. – extempl Apr 19 '12 at 15:15
  • element.children() contains text nodes iirc. check caniuse.com for compatibility. – rlemon Apr 19 '12 at 15:19
  • What's interesting - problem was seen in the Google Chrome, but FF returns single text node normally. So, it's Chrome bug – extempl Apr 19 '12 at 15:22
  • yup. there is a reason behind it i'm sure. console.dir( div.childNodes );​ and you'll see everything. read the manpage on .log() https://developers.google.com/chrome-developer-tools/docs/console – rlemon Apr 19 '12 at 15:25
-1

.contents() is concerned with DOM nodes. That string in the 2nd example is not a DOM element.

Paul
  • 2,330
  • 2
  • 19
  • 18