JsonML.buildHtmlを作った。ちゃんとテストしてないけど。

今、オープンソースなものを使わないでAjaxアプリを作る仕事をしてるんですが、JsonML.buildHtml的なものが欲しいような気がしたので適当に実装しました。でも、ある程度実装してから、やっぱ使わない方が良い気がしてきました。
まぁ廃棄しよう…と思ったものの、もったいないので晒しときます。

if(typeof(JsonML) == 'undefined') window.JsonML = {};
(function() {
    var AttrMap = {
        "class": "className",
        tabindex: "tabIndex",
        accesskey: "accessKey",
        usemap: "useMap",
        rowspan: "rowSpan",
        colspan: "colSpan",
        cellpadding: "cellPadding",
        cellspacing: "cellSpacing",
        maxlength: "maxLength",
        readonly: "readOnly",
        hidefocus: "hideFocus",
        contenteditable : "contentEditable"
    };

    function _build(obj) {
        var tag = obj[0];
        var attr = (typeof(obj[1]) == "object" && !(obj[1] instanceof Array)) ? obj[1] : null;
        var children;
        var temp = obj[ (!attr) ? 1 : 2 ] || null;
        if(typeof(temp) == "string") {
            children = [temp];
        } else if(temp instanceof Array) {
            children = (temp[0] instanceof Array) ? temp : [temp];
        } else {
            children = null;
        }

        var elem = document.createElement(tag);
        if(!!attr) {
            if(!!attr["style"]) {
                elem.style.cssText = attr.style;
                delete attr.style;
            }
            for(var k in attr) {
                var key = k.toLowerCase();
                var val = attr[k];
                // add event handler
                if(/^on(.+)/.test(key)) {
                    _addListener(elem, (RegExp.$1), val);
                // set attribute
                } else {
                    elem[ AttrMap[key] || key ] = val;
                }
            }
        }
        if(!!children) {
            for(var i = 0, len = children.length; i < len; i++) {
                var c = children[i];
                elem.appendChild((typeof(c) == "string")
                    ? document.createTextNode(c)
                    : arguments.callee(c)
                );
            }
        }
        return elem;
    }

    var _addListener;
    if(!!window.attachEvent) {
        _addListener = function(elem, type, func) {
            elem.attachEvent("on"+type, function() { func(window.event) });
        }
    } else {
        _addListener = function(elem, type, func) {
            elem.addEventListener(type, func, false);
        }
    }

    JsonML.buildHtml = function(jsonml) {
        if(!(jsonml instanceof Array)) return null;

        var df = document.createDocumentFragment();
        if(jsonml[0] instanceof Array) {
            for(var i = 0, len = jsonml.length; i < len; i++) {
                df.appendChild(_build(jsonml[i]));
            }
        } else {
            df.appendChild(_build(jsonml));
        }
        return df;
    };
})();

使う時はこんな感じで。

window.onload = function() {
    // DocumentFragmentが返ってくる
    var df = JsonML.buildHtml(
        [
            ["div", {
                "id": "hoge",
                "style": "border: 1px solid gray",
                "onclick": function() { alert("clicked!") }
            }, [
                ["h1", "hogehoge"],
                ["p", "ほーげーほーげー"]
            ] ],
            ["br"],
            ["hr"]
        ]
    );
    document.body.appendChild(df);
};

注意点

2008/12/18 追記

これ、良く見たらJsonMLの仕様を間違えて実装してるじゃないの。ダメだ…、こんど修正記事書こう…。
あと、上で紹介してるJsonML.Template、今はダウンロードできないかも。id:amachangのとこにコメント書いたんだけど、スルーされちゃったしなぁ。CodeReposにもそれっぽいのは無いし、Tracごとこの世から消えていったというオチなのかなぁ?