So the solution to the bug I had yesterday was fixed with a call to element::cloneNode to avoid aliasing. This introduced, to my great consternation, another bug — some DOM nodes were reverting to their default value. Had I written this down in my (as yet hypothetical) bug journal, it might have become more clear. Instead, I slaved away in Firebug for a few hours without results.
Thinking about it clearly, the problem had to be in cloneNode. I ended up having to write the following recursive fix-up function:
/**
* List of all DOM event handler names.
*/
var dom_events =
['onblur', 'onfocus', 'oncontextmenu', 'onload',
'onresize', 'onscroll', 'onunload', 'onclick',
'ondblclick', 'onmousedown', 'onmouseup', 'onmouseenter',
'onmouseleave', 'onmousemove', 'onmouseover',
'onmouseout', 'onchange', 'onreset', 'onselect',
'onsubmit', 'onkeydown', 'onkeyup', 'onkeypress',
'onabort', 'onerror']; // ondasher, onprancer, etc.
/**
Fixes copy errors introduced by {@link element#cloneNode}, e.g. failure to copy classically-registered event handlers and the value property.
@param {element} o The original DOM element
@param {element} copy The result of o.cloneNode()
@return {element} A modified copy with event handlers maintained
*/
function fix_dom_clone(o, copy) {
if (!(dom_obj(o) && dom_obj(copy))) { return; }
for (var i = 0;i < dom_events.length;i++) {
var event = dom_events[i];
if (event in o) { copy[event] = o[event]; }
}
if ('value' in o) { copy.value = o.value; }
// recur
var o_kids = o.childNodes;
var c_kids = copy.childNodes;
for (i = 0;i < o_kids.length;i++) {
fix_dom_clone(o_kids[i], c_kids[i]);
}
}
Oof. Unsurprisingly, there are a few efficiency issues.
My bug was weird and unexpected, and the W3C DOM level 2 spec doesn't allude to problems like this, but looking at a Mozilla bug report on the topic, it seems that the W3C DOM level 3 spec says that "[u]ser data associated to the imported node is not carried over". I guess if that's true for event handlers, it's also true for the value property. Oh well. I'd feel better about this irritating API "feature" if they said "associated with".