I would like to create a specific projection of the DOM tree, with only some attributes instead of DOM nodes.
Let's say we have this HTML:
<div data-foo="bar0">
<div data-foo="bar1">
<div>
<div data-foo="bar2">
</div>
<div data-foo="bar3">
</div>
</div>
</div>
<div data-foo="bar4">
</div>
</div>
I would like to only get the data-foo
attributes, but hold the DOM tree's arrangement. ( Every node, that doesn't have data-foo
attribute shall be ignored. )
I imagine the result of the example above after the harvesting like this: ( As an array / object )
someStorageVariableForTheDOMFootPrint["bar0"]
shall have two indexes in it, bar1
and bar4
.
Going further, bar1
index shall be an array again, containing two indexes bar2
and bar3
. These can all be empty variables, the index, and the array / object structure is important.
No DOM nodes, no context, nothing shall be stored only the data-foo attribute, but in the structure of the DOM tree.
How should I start right?
Basically, what you want to do is create an object graph that's a transformation of your DOM object graph, into a result probably looking something like this:
{
"foo": "bar0",
"children": [
{
"foo": "bar1",
"children": [
{
"foo": "bar2",
"children": []
},
{
"foo": "bar3",
"children": []
}
]
},
{
"foo": "bar4",
"children": []
}
]
}
I got interested, and found it's surprisingly easy to do: Live Example
function graph(element) {
var rv, child, $element, index;
// Wrap the element
$element = $(element);
// Our non-DOM equivalent object
rv = {
foo: $element.attr("data-foo")
};
// Get its children
rv.children = $element.children().get().map(graph);
// If any children are missing foo, replace them with their children
index = 0;
while (index < rv.children.length) {
child = rv.children[index];
if (!child.foo) {
// No foo, replace the element with its children
replaceElementWith(rv.children, index, child.children);
index += child.children.length;
} else {
++index;
}
}
return rv;
}
// Replace the array element at the given position with the elements from
// the given array
function replaceElementWith(array, index, newElements) {
var args = [index, 1];
if (newElements.length) {
args.push.apply(args, newElements);
}
array.splice.apply(array, args);
}