robnyman / domassistant

Automatically exported from code.google.com/p/domassistant
1 stars 0 forks source link

addContent when used with strings remove events and attributes #18

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
addContent internally use, to add content as string,

if (type === "string" || type === "number") {
    this.innerHTML += content;
}

this remove any attribute or event previously added at runtime to the
current node, without any warning, causing bugs quite hard to find

Here follows a simple test case

// start code

elem=document.createElement("div");
innerElem=document.createElement("span");
innerElem.foo="here I am";
$(elem).addContent(innerElem);
alert(elem.firstChild.foo);
$(elem).addContent("<span>...</span>");
alert(elem.firstChild.foo);

// end code

both the alert windows should show "here I am", but the second one will
show "undefined" instead. This is particularly evil when an attached event
disappear without notice.

A workaround would be to parse the string "content" and add the result to
the parent using DOM api. Being DOMParser not supported by explorer, a
possible solution could be (ab)using innerHTML. A possible implementation
of addContent follows:

// start code

function (content) {
    var type = typeof content;
    if (type === "string" || type === "number") {
        var tmpElem=document.createElement("div");
        var body=document.getElementsByTagName("body")[0];
        body.appendChild(tmpElem);
        tmpElem.style.display="none";
        tmpElem.innerHTML=content; // let the browser parse content for us
        content=tmpElem.firstChild;
        body.removeChild(tmpElem);
        type="object";
    }

    if (type === "object" || (type === "function" && !!content.nodeName)) {
        this.appendChild(content);
    }
    return this;
}
// end code

the temporary element is added to "body" to avoid some exceptions I noticed
in firefox when trying to style an element not attached to the page

What version of the product are you using? On what operating system?
DOMAssistantComplete 2.7.4, gentoo linux, firefox 3.0.5

Riccardo Galli

Original issue reported on code.google.com by riqu...@gmail.com on 26 Jan 2009 at 11:25

GoogleCodeExporter commented 9 years ago
I forgot that "content" could have more than a single child, so it will be 
necessary
to iterate over the "tmpElem" children (with nodeType ELEMENT_NODE)

Original comment by riqu...@gmail.com on 27 Jan 2009 at 12:33

GoogleCodeExporter commented 9 years ago
I wrote a possible function that handle multiple first level children in the 
string(
it doesn't attach the element to the body anymore because it seems to work 
anyway).
Tested on firefox 3.0.5 (linux) and safari 3.2.1 (linux via wine)

// to test it, replace the current addContent function with the following code

addContent : function (content) {
    var type = typeof content;
    if (type === "string" || type === "number") {
        var tmpElem=document.createElement("div");
        tmpElem.innerHTML=content; // let the browser parse content for us

        var children=tmpElem.childNodes,child=null,last=null;

        for (var i=children.length-1;i>=0;i--){
            child=children[i];
            if (child.nodeType===child.ELEMENT_NODE) {
                last=this.insertBefore(child,last);
            }
        }
    }
    else if (type === "object" || (type === "function" && !!content.nodeName)) {
        this.appendChild(content);
    }
    return this;
}

Original comment by riqu...@gmail.com on 28 Jan 2009 at 1:12

GoogleCodeExporter commented 9 years ago
Thanks for the comprehensive bug report Riccardo! I'll look into this.

Original comment by chengh...@gmail.com on 28 Jan 2009 at 8:15

GoogleCodeExporter commented 9 years ago
Check SVN for fixed version.

Original comment by chengh...@gmail.com on 19 Apr 2009 at 4:03