LoginSignup
10
9

More than 5 years have passed since last update.

JavaScriptのデータ構造を元にHTMLを生成

Last updated at Posted at 2014-07-31

JavaScript で HTML を動的に作成することはよくやりますが、下記のように直球な方法のは中々面倒くさい。

var sHtml = "<table><thead><tr><th>" + sHoge + "</th></tr></thead></table>";

いろんな便利な方法があるのでしょうが、ググッても私がイメージしてたようなのは中々見つからなかったので、自分で作れないか試してみました。

var gh = {
    gen: null,
    /*
        データ構造を元に HTML 生成。
        引数は 文字列 or 数値 or ハッシュ 想定。
        ハッシュは、'tag', 'inward' が予約KEYで、それ以外はアトリビュートとされる。
        'inward' は 文字列 or 数値 or 配列 想定で、配列には引数と同じものを入れることが出来る。
        以下はテーブル作成例。
        var h = {
            tag: 'table',
            class: 'table table-bordered',
            inward: [
                {
                    tag: 'thead',
                    inward: [
                        {
                            tag: 'tr',
                            inward: [
                                {
                                    tag: 'th',
                                    inward: 'title1'
                                },
                                {
                                    tag: 'th',
                                    inward: 'title2'
                                },
                            ]
                        }
                    ]
                },
                {
                    tag: 'tbody',
                    inward: [
                        {
                            tag: 'tr',
                            inward: [
                                {
                                    tag: 'td',
                                    inward: 'value1'
                                },
                                {
                                    tag: 'td',
                                    inward: [
                                        'value2',
                                        { tag: 'br' },
                                        { tag: 'b', inward: 'fugafuga' }
                                    ]
                                },
                            ]
                        }
                    ]
                },
            ]
        };
        var sHtml = gh.generateHtml(h);
    */
    generateHtml: function(h) {
        if (typeof h == 'string' || typeof h == 'number') {
            return h;
        }
        var sInward  = null;
        var sTag     = null;
        var aAttr    = [];
        for (var key in h) {
            if (key == 'tag') {
                sTag    = h[key];
            }
            else if (key == 'inward') {
                if (typeof h[key] == 'string' || typeof h[key] == 'number') {
                    sInward = h[key];
                }
                else {
                    sInward = '';
                    for (var i = 0; i < h[key].length; i ++) {
                        sInward += arguments.callee(h[key][i]);
                    }
                }
            }
            else {
                if (h[key] == null) {
                    aAttr.push(key);
                } else {
                    aAttr.push(key + '="' + h[key] + '"');
                }
            }
        }
        if (sTag == null) {
            return '';
        }
        var sTagS = '<' + sTag + (aAttr.length == 0 ? '' : ' ' + aAttr.join(' ')) + '>';
        return (sInward == null) ? sTagS : sTagS + sInward + '</' + sTag + '>';
    }
};
gh.gen = {
    /* hBase をベースとして、a の要素(ハッシュ)を加えたもので HTML 生成して a に対応した配列として返す */
    unite: function (hBase, a) {
        var aR  = [];
        for (var i = 0; i < a.length; i ++) {
            var h = {};
            for (var key in hBase) {
                h[key] = hBase[key];
            }
            for (var key in a[i]) {
                h[key] = a[i][key];
            }
            aR.push(gh.generateHtml(h));
        }
        return aR;
    },
    /* 配列から tr,td 生成 */
    array2tr: function (a) {
        var hTr = { tag: 'tr', inward: [] };
        for (var i = 0; i < a.length; i ++) {
            hTr.inward.push({
                tag: 'td',
                inward: a[i]
            });
        }
        return gh.generateHtml(hTr);
    },
    /* a 生成 */
    a: function (h) {
        h.tag   = 'a';
        return gh.generateHtml(h);
    },
    /* option 生成。inward は文字列想定。value 省略時は inward が入る */
    option: function (h) {
        h.tag   = 'option';
        if (! 'value' in h) {
            h.value = h.inward;
        }
        return gh.generateHtml(h);
    }
};

コメントにもありますが、入れ子になったデータ構造を渡すとHTML文字列を作成します。
img タグを作る場合とかはこんな感じでしょうか。

var sHtml = gh.generateHtml({ tag: 'img', src: 'hoge.png' });

unite は下記のように一部のデータ構造が同じものをいっぱい作るときを想定しています。

var a = [
    { name: 'hoge', value: 123 },
    { name: 'fuga', value: 456 }
];
var sHtml = gh.gen.unite({ tag: 'input', type: 'hidden' }, a).join("");

これでも多少は便利よく使えるかとは思うのですが、もっといい感じのがあるはず…とも思うので、知っていたら教えてくださいね。

追記 2014-08-04

dankogai さんから下記を紹介していただきました。
便利すぎる…。のでこっち使ったほうが良いです。
json2dom() & dom2json()

10
9
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9