このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

動機と構想 -- もっとカンタンならいいよね

現状で、JACALについて解説してみても、流動的だからあまり意味がないでしょう。が、思いついた経緯は単なる事実であるし、おおざっぱな筋書きはそう変わるとは思えないので、動機と構想について記しておきます。

内容:

  1. きっかけ
  2. 事例:カウンター
  3. あー、いろいろとめんどくさい!
  4. タグ一発、チョーかんたん
  5. 隠蔽しないでまとまりをつける -- 関連付けの技術
  6. 名前の由来

●きっかけ

最近、いくつかのJavaScriptライブラリ/フレームワークを調べました。その経緯や結果は何度かここで報告してます。高機能でよく出来たものが既に複数存在します。その他単発的なJavaScriptコードなども含めれば、Web上にJavaScript資産(あるいは資源)は相当に蓄積されています。「もう十分」とは言わないまでも、「不足していて困る」感じはしません。

ですが、既存のJavaScriptアプリケーション(あえて「アプリケーション」という言葉を使う)を、HTMLページ作成者が簡単に利用できるか? というと、そうはなってません。HTMLページでJavaScriptアプリケーションを動作させるには、JavaScriptコード以外に:

  • HTML断片(ページの一部)
  • スタイルシート
  • JavaScriptコードとHTML断片の関連付け
  • ページ初期化コード(scriptタグ内に記述、またはwindow.onloadハンドラ)

などを書き足さねばなりません。こういう作業は決して簡単ではないし、面倒で間違いやすい面もあります。もう少し楽にならないの? 楽になるんじゃないかな -- こう思ったのが先日、10月20日のことです。

●事例:カウンター

とりあえず、次のJavaScriptコード(JSANを前提とする)を見てください。


/* Example/Counter.js
* JSAN Module Name: Example.Counter
*/

if (!Example) var Example = {};

/* コンストラクタ */
Example.Counter = function(elm) {
// elm:Element

this.valueElement = elm;
this.value = 0;
};
/* メソッド */
Example.Counter.prototype.inc = function() {
this.value++;
this.valueElement.innerHTML = this.value;
};
Example.Counter.prototype.dec = function() {
this.value--;
this.valueElement.innerHTML = this.value;
};
Example.Counter.prototype.clear = function() {
this.value = 0;
this.valueElement.innerHTML = this.value;
};
Example.Counter.prototype.init = Example.Counter.prototype.clear;

/* === ページ準備のためのコード === */

Example.Counter.setup = function() {
var valueElement = document.getElementById('counter-value');
window.counter = new Example.Counter(valueElement);
window.counter.init();
};

/* 初期化の予約 */
if (window.attachEvent) {
window.attachEvent("onload", Example.Counter.setup);
} else if (window.addEventListener) {
window.addEventListener("load", Example.Counter.setup, false);
} else {
alert("Cannot set onload-handler");
throw new Error("Cannot set onload-handler");
}

このコードは具合の悪い点がありますが、それは後で指摘することにして、このコードを使ったサンプルをば。

このサンプルのソースを見てもらえばわかりますが、Counter.jsを動作させるために、カウンタの見た目部分(プレゼンテーション)を新たに書いてます。そのとき、次の約束を意識し、注意する必要があります。

  • カウンタ値を表示する要素には、'counter-value'というIDを付ける。
  • カウンタオブジェクト(への参照)が、大域変数counterにセットされる。

カウンタの見た目の調整にCSSを使っているので、カウンタ用HTML断片とCSSスタイルシートのあいだにも約束事ができてしまっています。それらは:

  • 一番外側の要素のクラス名は'counter'である。
  • カウンタ値を表示する要素のクラス名は'counter-value'である。
  • …… (クラス名の規約がその他イッパイ)

デザインに凝って画像を使うなら、画像のパス名なども約束に入ってきます。

※ 不思議なことに、IE6では、上のコード内の「/* 初期化の予約 */」というコメント(Shift_JISで記述)があるとコンパイルが失敗する。削除したり文面を変えるとOKになる。ヤダヤダ。

●あー、いろいろとめんどくさい!

Counter.jsに関して、「JavaScriptコード ⇔ HTML断片」という関連づけの約束があります。この約束のもと、プレゼンテーションを提供するHTML断片は自分で準備しなくてはなりません。CSSを使えば今度は「HTML断片 ⇔ スタイルシート」の関連付けに山のようなお約束が出現します。これらのお約束が守られていることを保証するために人の注意力と手間をかけています。

ところで、Counter.jsには感心しない点があります。


var valueElement = document.getElementById('counter-value');
window.counter = new Example.Counter(valueElement);

としているので、カウンタはページ内に1個しか置けません。それに、'counter-value'というID、counterという大域変数において、名前の衝突の危険があります。こんなコードをモジュールに含めるべきではありません。あと、ページ初期化の予約部分は共通ユーティリティ関数(例:CommonUtils.registerSetup(func))に移しましょう。

これでスッキリします。しかし一方、モジュールから除外したコードは、HTMLページ作成者が準備することになるので、モジュールの使い方はかえって難しくなります。今までは、 <script>JSAN.use("Example.Counter");</script>だけだった(オマジナイと思えばよい)のに、スッキリしたモジュールを使うにはJavaScriptコードを書く能力が要求されるのです。

●タグ一発、チョーかんたん

上で述べたような、めんどうなことをゴチャゴチャしないで、次のごときHTML文書(厳密にはHTML文書ではないが)を書いたらそれでOKだったらうれしいですよね。(「カウンタの例」のソースと見比べてね)


<html>
<body>
<h1>Counter Sample 1</h1>
<Example-Counter /><!-- カウンタ -->
</body>
</html>

このかんたん方式を現実のものにしよう、という試みがJACALです。

タグを書くだけでHTMLページに“動作するコンポネント”を埋め込める、といえばobjectタグを思い浮かべるでしょう。ピンポン -- JACALが提供する(はずの)カスタム・タグは、objectタグと同様なものだと理解してください。objectとの違いは:

  • “動作するコンポンネント”は、JavaScript、(X)HTML、CSSの技術だけで実現される。バイナリ実行形式とは無縁である。
  • “動作するコンポンネント”の埋め込みを指定するタグは、ブラウザに届く前に展開される。ブラウザがJACALのタグを解釈するわけではない。

「ブラウザに届く前に(多くの場合、サーバサイドで)展開される」という点では、「はてな」の<hatena ...>タグとも似てるかもしれません。

●隠蔽しないでまとまりをつける -- 関連付けの技術

HTMLページに埋め込まれるコンポンネントの振る舞い(ビヘイビア)はJavaScriptコードが提供します。コンポネントの見た目(プレゼンテーション)は、HTML断片とCSSスタイルシート(場合により画像など)が提供します。

「コンポネント=ビヘイビア+プレゼンテーション」と言ってもいいですが、ビヘイビアとプレゼンテーションをブラックボックスに詰め込んで隠蔽するようなカプセル化はしません(“複数の構成素にまとまりをつける”という点では一種のカプセル化と言えなくもないか?)。コンポネント化は、一緒に使えるビヘイビアとプレゼンテーションを適切に選んで、それらを関連付けることになります。関連付けの機構を僕はアソシエーションと呼ぶことにしました(用語法は変わるかもしれない)。

よって、JACALのコンポネントは、「ビヘイビア、プレゼンテーション、アソシエーションの三角形」で図示すると適切そうです。

●名前の由来

JACALは、JavaScript Application Componentizing and Associating Language のアクロニムのつもりです。しかし、フルスペルは(表現や語感が適切か自信もないので)忘れてください。動物のジャッカルと同じ発音の固有名詞ということで。

Jackalには、「げす野郎」、「詐欺師」なんて意味もあるようです(「英辞郎」)が、そのうち(ずっと先?)可愛い“ジャッカル君”のキャラクタでも作って対処するとしましょう :-)

See also →JACALグループ: http://jacal.g.hatena.ne.jp/