A problem I ran into implementing my MutationObserver shimmed interface is being able to save the state of an elements children for later use. Naively I started by just using $oldnode = $node.cloneNode(true)
which would give me an atomic node at a previous state. The problem with using cloneNode
is when it comes time to compare. Any children in $oldnode
will be !== to the same child in $node
.
I addressed this issue by assigning a unique id to all elements and checking if the unique id of an old node is the same as from an earlier state. This is ugly and noone wants me adding my own unique id property on their elements.
var counter = 0;
var getId = function($ele) {
var id = $ele.nodeType === 3 ? $ele.nodeValue ://text node id is the text content
$ele.id || $ele.getAttribute("mut-id") || ++counter;
if(id === counter) {
$ele.setAttribute("mut-id", id);
}
return id;
};
I'm considering representing an elements clone in a custom datastructure: probably an array of hashes
. Each clone will be an array of objects with a key ele
which stores the real element and a key childs
which will store the state of the elements childNodes
(in an array because nodelists are live) from a previous point of time.
Here's my naive clone implementation:
var map = Array.prototype.map;
var clone = function (children,deep) {
return map.call(children, function(node) {
return {
node: node.nodeType === 3 ? node.cloneNode(false) : node,//clone in case of text changes
children: deep && node.hasChildNodes() ? clone(node.childNodes, deep) : null
};
});
};
So for the following node being held by the variable $node
would be cloned to :
<ul class="test">
<li>
<span>text</span>
<p>stuff<strong>10</strong><i>of</i><span>10</span></p>
</li>
</ul>
child_clone(node.childNodes, false) => [{"node":"<li><span>text</span><p>stuff<strong>10</strong><i>of</i><span>10</span></p></li>","children":null}]
Cloning will probably slower but iterating will be faster as ===
will work in place of my sameNode
helper. Adding items when there are changes may be awkward. It'd probably be most efficient to compare my datastructure to the current state of the node to reduce the need for cloning.
Intuitively I believe my datastructure will be more memory efficent as nodes aren't cloned and are just pointers?