Kanasan.JS JavaScript 第 5 版読書会 #82009年09月30日 03時41分

Kanasan.JS JavaScript 第 5 版読書会 #8 に行ってきました。今回は初めての京都での開催、それも町家でという風情あふれる読書会。真夏真冬はちょっとつらいかもしれませんが、春秋はこういった場所での勉強会というのも乙なものですね。名古屋の DeLLa.JS では茶室での開催もあったそうでうらやましいことです。

ちなみに会場「お結び庵」の運営は home's vi ("h" を抜くと「おむすび」) という法人によるものだそうで。なんとなく名前に親近感を感じてしまうのは気のせいでしょうか。

読書範囲は「17.5 キーイベント」から「18章 フォームとフォーム要素」まで。ブラウザごとに変な癖があるということが少なく (完全にばらばらか結構統一されているか)、さくさくと読めました。

キーボードショートカット

サイ本では、Web アプリケーションはキーボードショートカットをサポートすべきといっており、WCAG (ウェブコンテンツ・アクセシビリティ・ガイドライン) 2.0 (日本語訳) にもすべての機能をキーボードから利用できるようにするという指針があります。

しかし、製作者側でのショートカットキーの指定は、(特にアルファベットを含む場合) ブラウザやユーザー側で設定されたショートカットキーとの衝突や、サイト間での一貫性の欠如といった問題をはらんでいます。

個人的に、製作者側は、キーボードアクセス可能にするにあたって、

Tab
ウィジェット間の移動
矢印
ウィジェット内の項目の移動
Enter
確定、実行
スペース
状態の切り替え
Delete
削除

といったある程度意味の定まったキーに対しては動作を指定すべきだが、アルファベットを含むショートカットキーは使用を避けるか、少なくとも無効にできるようにすべきだと思っています。

関連リンク

自前でキーボードショートカットを実装するウェブサイトは、キーボードでブラウジングする人のことをもっと考えてあげてください - by edvakf in hatena
Web サイトが提供するキーボードショートカットを使うのは、普段からキーボードでブラウジングしている人たちであるという指摘と、キーボードショートカットを提供するスクリプトの書き方について。
accesskeyにはアクセシビリティが無い - Archiva
HTML の accesskey 属性の問題点に関して。
accesskeyの使い方を比較(Google,Yahoo!,MySpace,mixi,モバゲー,ニコ動,etc) | 携帯サイトをつくろう。
携帯サイトではショートカットキーがある程度統一されているという話。

delete 演算子の使用

「17.6 onload イベント」のサンプルコードで、不要になったプロパティを delete 演算子で削除していますが、個人的には null を代入するほうが好みです。

最近の JavaScript エンジンでは、同じ構造を持つオブジェクト同士は同一の「クラス」に属するものとして扱います。あるオブジェクトのプロパティを delete 演算子を使って削除すると、そのオブジェクトの構造と属する「クラス」が変化することになり、速度的に不利になる場合があります。とはいってもスクリプト全体の実行時間からすれば気にするほどではなく、どちらを選ぶかは趣味の問題でしょう。

テキスト入力に対するイベント

テキスト入力欄 (input type="text"、textarea) の入力値の変化を通知するものとして change イベントがありますが、これは入力欄からフォーカスが外れるタイミングでしか発生しません。キー入力に逐次対応したいときは keydown、keypress イベントを、それ以外の手段による変更にも対応したいときはさらにタイマー (setTimeout、setInterval) を組み合わせるのが一般的なようです。

手段を問わず (少なくとも一定時間内の) 入力値の変化を監視するために、HTML5 では input イベントが定義されています。Firefox 1.0、Safari 3、Opera 9 以上が対応していますが、Opera では (10.00の時点でも) 切り取りやドラッグ & ドロップによる値の変更に反応しない (その場合フォーカスが外れた時点で input イベントが発生する)、WebKit (Safari、Chrome) では IME で未確定の入力にも反応するなど、実装にばらつきがあります。

ちなみに、切り取り、貼り付けに反応するものとして、IE の cutpaste イベントがあり、Firefox 3 以上、Safari もこれを実装しています (element.onpaste - MDC)。このイベントはバブルしますが、IE では文書要素 (html 要素) までしかバブルしないようです。

name 属性の名前空間

サイ本 18.3.1 節 (日本語版 p. 466) には

<form name="everything">

document.everything

で参照する例が出てきますが、この方法では document のプロパティ名とフォーム名が競合したときに困るので、name 属性ではなく id 属性を使い、document.getElementById などでアクセスしたほうがいいです。

勘違いされがちですが、form、img、a 要素の name 属性が要素を一意に識別するためのものなのに対し、input、textarea、select 要素の name 属性はサーバーに送信するコントロール名を指定するためのものと、同名の属性でも役割がまったく異なります。form 要素に限らず、前者に関しては id 属性を使ったほうが、他の要素との一貫性も取れて楽でしょう。

ただし、IE 7 以下では name 属性も id 属性と同じ名前空間に入ってくる (document.getElementById("foo") で name="foo" な要素が返ることがある) ので、フォームコントロールの name 属性と、ある要素の id 属性とが同じ値を取らないようにしたほうがいいかもしれません。

フォームコントロールの値中での改行

フォームコントロールの値が改行を含むとき、その改行コードはブラウザによってさばらばらです。IE の場合、value プロパティに \r\n を含む文字列を設定しても、取得時にはすべて \r\n になっています。このような状況に対応するため、私は次のように改行コードを統一することがあります。

var value = control.value.replace(/\r\n?/g, "\n");

なお、この改行コード変換用正規表現は、Perl では正しくないそうですが、JavaScript では問題ないと思います。

IE での属性セレクタ

IE 7 以上は CSS の属性セレクタに対応していますが、スクリプトから属性に変更を加えても表示が更新されないというバグがあります (IE 8 でも発生)。その場合でも class 属性などをいじると、それまでの変更が表示に反映されるようです。

<style type="text/css">
[title="foo"] { color: #c63; }
</style>
element.setAttribute('title', 'foo');
// IE では、ここで終了すると element の色が変化しない

element.className += '';
// この時点で element の色が変化する