prettify

baseline

DOM prototype extensions

DOM should be OO. Fortunately it is to fix with javascript.
The problem is that the code becomes very verbose (and not elegant) when I want to create a part of a web page in code.
When I want to create a table in code, I create a documentFragment and call a MakeTable function:
DOM is not object oriented so for just one row and two cells:
function MakeTable(sDivId) {
    var oFra = document.createDocumentFragment();
    var oTable = document.createElement("table");
    oFra.appendChild(oTable);
    var oTbody = document.createElement("tbody");
    oTable.appendChild(oTbody);

    var oTr = document.createElement("tr");
    oTbody.appendChild(oTr);
    var oTd = document.createElement("td");
    oTr.appendChild(oTd);
    var oText = document.createTextNode("one");
    oTd.appendChild(oText);
    oTd = document.createElement("td");
    oTr.appendChild(oTd);
    oText = document.createTextNode("two");
    oTd.appendChild(oText);

    document.getElementById(sDivId).appendChild(oFra);
}
This is how I like it, in almost one statement (and with style):
If attributes containt the characters ":" or ";" as in the example, use encodeURIComponent to hide them.
function MakeTable(sDivId) {
    var oFra = document.createDocumentFragment();
    oFra.a$("table", {border:"1", width:"50%", className:"dataForm", style:"backgroundColor:#eef"}).
    a$("tbody").a$("tr").
    a$("td", { t: "one" }).parentNode.
    a$("td", { t: "one",
        style:"backgroundImage:"+encodeURIComponent("url(data:image/jpeg;base64,....)") });
    document.getElementById(sDivId).appendChild(oFra);
}
What I do is include a method (a$) in the documentFragment (first statement). This method lets me:
pass both parameters (sTag, oAtr)
Adds child (sTag) with attributes (oAtr)
do not pass any parameters
removes all children
pass only sTag parameter
Adds child (sTag) without any attributes
pass only oAtr parameter
Defines attributes, styles, text. They must be written in javascript style (className, htmlFor for attributes and backgroundColor etc for style).
For text content use "t":"one"

ins.js

/* 20111020 ****************************************************/
if (typeof ins !== "object") { var ins = {}; }
var $ = function (sId) { return document.getElementById(sId); }
//========================================================================
ins.oNS = {
    "mathml": "http://www.w3.org/1998/Math/MathML"
   , "svg": "http://www.w3.org/2000/svg"
   , "xlink": "http://www.w3.org/1999/xlink"
   , "xsi": "http://www.w3.org/2001/XMLSchema-instance"
};
ins.a$ = function (sTag, oAtrs) {
    var oChild = this, aTag, sNS;
    if (typeof sTag === "undefined" && typeof oAtrs === "undefined") {
        while (this.hasChildNodes()) this.removeChild(this.lastChild);
        return this;
    }
    if (typeof sTag === "object" && typeof oAtrs === "undefined") {
        return ins.s$.call(this, sTag);
    }
    if (typeof sTag === "string" && sTag !== "") {
        if (sTag.indexOf(":") === -1) {
            oChild = document.createElement(sTag);
        } else {
            aTag = sTag.split(":");
            sNS = aTag[0];
            if (ins.oNS.hasOwnProperty(aTag[0])) {
                oChild = document.createElementNS(ins.oNS[aTag[0]], aTag[1]);
            } else {
                throw "namespace:" + aTag[0];
            }

        }
        if (typeof oAtrs === "object") {
            var oInsertBefore = oAtrs.insertBefore;
            if (typeof oInsertBefore === "object") {
                oChild.removeAttribute("insertBefore");
            }
            ins.s$.call(oChild, oAtrs);
            if (typeof oInsertBefore === "object") {
                this.insertBefore(oChild, oAtrs.insertBefore);
            } else {
                this.appendChild(oChild);
            }
        } else {
            this.appendChild(oChild);
        }
    }
    return oChild;
};
ins.s$ = function (oAtrs) {
    if (typeof oAtrs !== "object") { throw oAtrs; }
    var sAtr, sStyle;
    for (sAtr in oAtrs) {
        if (!oAtrs.hasOwnProperty(sAtr)) { continue; }
        if (typeof oAtrs[sAtr] === "function") {
            this[sAtr] = oAtrs[sAtr];
        } else {
            switch (sAtr) {
                case "style":
                    var aStyle, aStyles = oAtrs[sAtr].split(";");
                    for (sStyle in aStyles) {
                        if (aStyles.hasOwnProperty(sStyle)) {
                            aStyle = aStyles[sStyle].split(":");
                            if (aStyle.length >= 2 && aStyle[0].length > 0) {
                                this.style[aStyle[0]] = decodeURIComponent(aStyle[1]);
                            }
                        }
                    }
                    break;
                case "t":
                    this.appendChild(document.createTextNode(oAtrs[sAtr]));
                    break;
                default:
                    if (typeof oAtrs[sAtr] === "string") {
                        this.setAttribute(sAtr, oAtrs[sAtr]);
                    } else {
                        this[sAtr] = oAtrs[sAtr];
                    }
                    break;
            }
        }
    }
    return this;
};
Element.prototype.a$ = function (sTag, oAtrs) { return ins.a$.call(this, sTag, oAtrs); };
var bFragment = true;
try {
    DocumentFragment.prototype.a$ = function (sTag, oAtrs) { return ins.a$.call(this, sTag, oAtrs); };
} catch (e) { bFragment = false; }
Tested in IE8,IE9,FF4,O10,C6 (@2010.12.14)

No comments:

Post a Comment