改名します2009年04月01日 00時18分

私は普段テキストエディタに Emacs (正確には Meadow) を使っているのですが、nanto_vi という名前のせいか vi 使いに間違えられることが多く、先日も人に挨拶しようと思ったら「僕は Emacs 派なんで」と握手を拒否されてしまいました。ただ静かにエディタを使っていたいだけなのに、このようないわれなき差別を受けるのはもうこりごりです。争いのない平和な世界のためにいいエディタはないかと探していたところ、TeraPad というエディタの存在を思い出しました。

TeraPad は何よりもアイコンが優れており、今でこそやや古さを感じさせるものの、Windows 2000 のころには一番 Windows にマッチするアイコンのエディタといっても過言ではありませんでした。GUI アプリケーションにとってアートワークは命であり、アイコンが漢字一文字だったりした日にはどれだけ機能に秀でていようと使いたくなくなります。以後 vi 派と Emacs 派の宗教論争という古き時代から決別し、グラフィカルな未来へと邁進するという意志をこめ、名前を nanto_terapad と改めます。名前は変わってもブログの更新頻度は変わらないと思うので、今後とも気長にお付き合いしていただければ幸いです。

なんか仲直りできたっぽいんでやっぱ改名はなしで。

Kanasan.JS JavaScript 第 5 版読書会 #72009年04月28日 00時36分

Kanasan.JS JavaScript 第 5 版読書会 #7 に行ってきました (当日のチャットログ)。範囲は前回に引き続き CSS の操作、そしてイベント周りと、一般に「JavaScript」といったとき話題になりやすい部分です。参加者のブログ記事は「JavaScriptでCSSとイベントを扱う from Kanasan.JS | Blog.37to.net」のほか読書会のページからたどれます。

display: inline-block;

サイ本では解説されていませんが、CSS の display プロパティの値 inline-block に関して話が盛り上がりました。inline-block 及びそれがどのようなレイアウトに使えるかについては以下で解説されています。

ところで、上記ページのサンプルはいずれも Firefox 2 以下で -moz-inline-box を使っています。しかし、-moz-inline-box が指定された要素の子要素は XUL のボックスモデルに従って整形されるため、そのままでは期待した表示になりません。ヨモツネットのサンプルではこの問題への対策として子要素に幅を指定していますが、別のアプローチとして子要素に -moz-box-flex プロパティを指定するという方法もあります。実際にこの方法を用いたページ送りのサンプルを作ってみました。HTML と CSS は次のようになります。

<ul>
  <li><a href="http://example.org/">1</a></li>
  <li><a href="http://example.org/">10</a></li>
  <li><a href="http://example.org/">100</a></li>
  <li><a href="http://example.org/">1000000000000</a></li>
</ul>
/* デフォルトのマージン、パディングが影響しないように。 */
ul, li {
  margin: 0;
  padding: 0;
}

ul {
  text-align: center;
}

li {
  display: -moz-inline-box; /* Firefox 2 以下用。 */
  display: inline-block;
  /* 内容の幅が大きいとき自動的に自分の幅も広がるよう、width ではなく
   * min-width を用いる。Firefox 2 以下では -moz-inline-box な要素の
   * min-width がボーダーボックスの最小幅として解釈されてしまうが、
   * ここではボーダー、パディングの幅が 0 なので影響しない。
   */
  min-width: 3em;
}
/* IE 6/7 では、デフォルトで inline でない要素は inline-block を
 * 指定した後、さらに inline を指定しないと inline-block 表示にならない。
 * margin をつけるのは inline-block 間の空白文字が表示されないため。
 */
* + html li {
  display: inline;
  margin: 0 0.2em;
}
* html li {
  display: inline;
  width: 3em; /* IE 6 は min-width 非対応だが width で代用可。 */
  margin: 0 0.2em;
}

li a {
  display: block;
  border: 0.1em solid;
  /* Firefox 2 以下でマージンボックスの幅が包含ブロック (この場合は
   * -moz-inline-box な要素の内容ボックス) の幅いっぱいに広がるように。
   */
  -moz-box-flex: 1;
}
/* IE 6 でボーダーボックス全体がリンクとして機能するように。 */
* html li a {
  height: 0;
}

この方法の利点として、-moz-inline-box な要素の幅が % 単位で指定されていても内容の幅がそれに追従してくれるといったことが挙げられます。

ちなみに、IE 7 以下での inline-block 表示に display: inline; zoom: 1; を用いず、いったん inline-block を指定して別の規則で inline を指定していたり、ひとつの規則内に _width: 3em; /margin: 0 0.2em; とまとめて書くのではなく、* + html ... { margin: ...; } * html ... { width: ...; margin: ...; } と IE 用の規則に分けて書いていたりするのは、できるだけ CSS の書式に則りたいという個人的な趣味によるものです。

MacIE 5 にも対応しようとすれば IE 6/7 向けの指定を /*\*/ ~ /**/ で囲む必要があるのかもしれませんが、確認できる環境がないのでそこまではしていません。Firefox 2 もすでにサポート期限が切れているので、最低限リンクが機能すればレイアウトが期待通りでなくてもかまわないという姿勢もありでしょう。

この例では -moz-inline-box な要素の子要素がブロック要素だったので子要素に -moz-box-flex を指定しましたが、Takazudo Clipping* のサンプルのように -moz-inline-box な要素の内容がテキストノードだったりインライン要素だったりした場合には、-moz-inline-box な要素に -moz-box-pack: center; を指定することで内容を中央ぞろえにできます。

このように、inline-block 表示はちょっと無理をすれば大抵のブラウザで可能ですが、別に無理をしなくてもいいときもあります。ページ送りに関していえば、各項目の幅をそろえなくてもいい (「1」の項目と「10」の項目の幅が異なってもいい)、かつ項目内で行の折り返しが発生してもいい (または内容が数字だけなので折り返しが発生しない) というのなら、そもそも inline-block を使う必要がありません。(IE 6 での不具合を避けるために inline-block を指定することはあるかもしれませんが。)

なお、zoom: 1; という指定はいわゆる CSS ハックの一環として用いられることが多いですが、このときそのまま zoom: 1; と書いてはいけません。/zoom: 1_zoom: 1* html ... { zoom: 1; } など、必ず IE のみに適用されるような書き方をしましょう。これは、WebKit も zoom プロパティをサポートしており、そうしたハックを必要としないブラウザに想定外の影響を与えるのを防ぐためです。もちろん、実際にズーム効果を求めて zoom プロパティを使用する場合はこの限りではありません。

rect 関数の書式

CSS の clip プロパティに rect 関数を指定することで、絶対配置の要素の一部だけ切り抜いて表示できます。rect 関数の引数には切り抜く矩形の各辺の位置を示す値を指定しますが、各引数の区切り文字には注意が必要です。CSS 2 だと、本文中ではスペース区切りなのにサンプルではコンマ区切りになっています。CSS 2.1 だと本文もコンマ区切りに統一され、製作者はコンマ区切りを使うべきであり、ユーザーエージェントはコンマ区切りをサポートしなければならないが、同時にスペース区切りをサポートしても良いということになっています。実際は IE 7 以下がスペース区切りしか受け付けてくれないので、スペース区切りを使うことになるでしょう。

このほかにも clip プロパティと rect 関数の挙動は CSS 2 と CSS 2.1 とで大きく変化しており、「clip CSS 表示と配置 (World Wide Web Guide)」に詳しくまとめられています。

getComputedStyle と currentStyle の違い

ある要素の実際の CSS プロパティの値を調べるのに、IE 以外のブラウザでは getComputedStyle メソッドが、IEでは currentStyle プロパティが使えます。しかし、この両者から得られる値は、前者が使用値 (used value) であるのに対し後者が指定値 (specified value) であるという違いがあります。二つの値に関しては以下の文書が参考になります。

JavaScript から CSS の値を操作するときは、指定値よりも使用値を得られたほうが嬉しい場面が多い気がします。

イベントハンドラ内容属性とスコープ

HTML 要素の属性としてイベントハンドラを記述した場合、そのイベントハンドラを実行する際のスコープにはその要素を表す DOM 要素ノードオブジェクト (これは this から参照できる値でもあります) が含まれます。this.value と書く代わりに単に value と書いても同様に動くということです。サイ本にはこうした動作に関して何も標準が存在しないと書かれていますが、HTML 5 草案ではイベントハンドラを実行する手順が明文化されています。

IE のメモリリーク

IE のメモリリーク問題は、IE 6/7 で部分的には解決されました (IE 6 は更新プログラムを適用した場合)。「部分的」という理由は以下の記事で解説されています。

IE 8 では COM という基盤技術に手を入れることで循環参照によるメモリリーク問題を根本的に解決したようです。

雑感

ブラウザ上で何かしようとするとネックになってくるのが IE の存在です。CSS に関しては IE 8 で大きく前進しましたが、イベントモデルをはじめとする DOM 周りはいまだ独自路線のままです。IE 9 でこれらの点が改善され、Range や XPath といった高度な機能を手軽に扱えるよう、Web 開発者の一人一人が積極的に発言し Microsoft に声を伝えていく必要があると思います。

ちなみに、今回の範囲である DOM Events や DOM Style については、WEB+DB PRESS Vol. 46/47 の連載『JavaScript + ブラウザ探検』でも解説しています。よろしければそちらもご覧ください。