DOMの関数型構築

Linq to XMLのJavaScript移植、もポチポチと進めています。

var xml = new XElement("customer", new XAttribute("id", "c001"),
              new XElement("firstName", "Paolo"),
              new XElement("lastName", "Pialorsi"),
              new XElement("addresses",
                  new XElement("address", new XAttribute("type", "email"), "paolo@devleap.it"),
                  new XElement("address", new XAttribute("type", "url"), "http://www.devleap.it/"),
                  new XElement("address", new XAttribute("type", "home"), "Brescia - Italy")
              )
          );

alert(xml.Source.outerHTML); // .Sourceは気にしないでください(最終的には隠蔽されるので)

これは何と、C#にコピペしても動く。つまり互換性100%(笑) 所謂マークアップビルダになります。私がC#っ子だから、というのもあるけれど、JSON風に書くより好き。JSON風だとそれぞれのライブラリが属性対応のため変則的な書き方ルールが用いられていて、それを覚えなきゃいけないけれど、これなら要素に属性と値を突っ込むだけなので学習コストがほとんどない。と、思う。IntelliSenseのサポートも効くし(現在linq.jsをIntelliSenseが効くよう整備中です、土日に書きすすめて公開、したいなあ)。そのかわりnewだらけでちょっと冗長に過ぎるところはあるかもしれない。

// ユーザー名と発言と投稿を持ったクラス
var Twit = function(user, text)
{
    this.user = user;
    this.text = text;
}

// とりあえずサンプルデータ
var data1 = new Twit("ika", "いかはいかが");
var data2 = new Twit("tako", "たこやき");
var data3 = new Twit("sakana", "丸焼き");

// XmlHttpほげほげだのJSONだのな結果の例として配列
var list = [data1, data2, data3];

// リストをSelectでXElementに射影すると自動的に展開される
var xml = new XElement("twitter",
              new XElement("account", "neuecc"),
              new XElement("twits", E.From(list).Select(function(t)
              {
                  return new XElement("twit", new XAttribute("user", t.user), t.text)
              }))
          );

alert(xml.Source.outerHTML); // .Sourceは気にしないでください(最終的には隠蔽されるので)

例をもう一つ。例が適当かつ分かり辛くてすみませんなのですが、Selectで射影しておくと、展開されます。何らかのオブジェクトを繰り返してDOMにする、というシーンは多いと思うのですが、forはもう必要ありません。むしろfor禁止。ループは悪。「この配列を」「この形に展開する」と宣言的に記述するだけで良いのです。

var table = new XElement("table",
                new XElement("tr",
                    new XElement("td", "column1"),
                    new XElement("td", "column2"),
                    new XElement("td", "column3")
                ),
                E.Repeat("tr", 5).Select(function(tagName)
                {
                    return new XElement(tagName,
                        E.Range(1, 3).Select(function(i)
                        {
                            return new XElement("td",
                                new XAttribute("style", (i % 2 == 0) ? "background:red" : "background:green"),
                                "row" + i);
                        })
                    )
                })
            );

// FirefoxではouterHTML動きませんけど、最終的には隠蔽されるので(ry
document.body.innerHTML = table.Source.outerHTML;

簡単なTableの生成例。これrowになってませんね、あはは。まあ、いいや。関数の引数の中に式を書くという感覚が最初はキモかったのですが、今では平然と書くようになってしまいました。何というLinq中毒……。しかし、JavaScriptだとfunction(){return }のせいでゴチャゴチャして分かり難いものになってしまう。ラムダ式欲しいなあ。{とかreturnとかいらない。Firefox3では省略出来るけど、Chromeはまだ出来ないみたい……。

Firefox3は使えば使うほど嫌いになるという素敵ブラウザなので、本気でChromeに乗り換える気はありますよ!アドオンがなければ自分で作ればいいじゃない、と思うことにしますので、作りたいですね。一応Hello,Worldは書いた。

<script type="text/javascript" src="linq.js"></script>
<script type="text/javascript" src="linq.xml.js"></script>
<script type="text/javascript">
    // Initialize
    X.Initialize(function()
    {
        X.ID("panel").AttachEvent("click", panel_onclick);
    });

    // EventHandler
    function panel_onclick(sender, event)
    {
        X.ID("titleLabel").SetValue(event.screenX);
    }
</script>

<div id="panel" class="toolstrip-button">
    <span id="titleLabel">Hello, World!</span>
</div>

ええ、ただのHTMLです。ステータスバーのところにHello,Worldが出てクリックできるという、それだけのもの。Chromeの拡張はまだ何が出来るか分からないというか何も出来ないというか、それグリモンでいいよね、的なことしか出来ない感じなので、その間、今のうちにlinq.xml.jsを完成させよう。何かもう意地でも自分は使う、な方向に傾いてる気がしますが。jQuery?何それ。

Profile

Yoshifumi Kawai

Cysharp, Inc
CEO/CTO

Microsoft MVP for Developer Technologies(.NET)
April 2011
|
July 2025

X:@neuecc GitHub:neuecc

Archive