[34] [DFN[[RUBYB[[[イベント・ハンドラー]]]@en[event handler]]]]は、 非[[捕獲]]の[[イベント・リスナー]]として機能するものであり、多くの[[オブジェクト]]に指定することができます [SRC[>>35]]。 [39] [[イベント・ハンドラー]]は、 [DFN[[RUBYB[イベント・ハンドラーIDL属性]@en[event handler IDL attribute]]]] (旧・[DFN[[RUBYB[イベント・ハンドラーDOM属性]@en[event handler DOM attribute]]]]) と[DFN[[RUBYB[イベント・ハンドラー内容属性]@en[event handler content attribute]]]]の2種類の方法で指定することができます [SRC[>>35]]。 * 仕様書 [REFS[ - [35] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2013-05-05 06:42:10 +09:00]] 版) ]REFS] * 名前 [36] [[イベント・ハンドラー]]の名前は、対応する[[イベント]]の名前 ([DFN[[RUBYB[[[イベント・ハンドラー・イベント型]]]@en[event handler event type]]]]) の前に [CODE[[[on]]]] をつけたものです [SRC[>>35]]。 [37] とはいえ任意の[[イベント型]]の名前に [CODE[[[on]]]] をつければ良いものではなく、 仕様で定義され、[[利用者エージェント]]が実装している[[イベント・ハンドラー]]のみ機能します。 * 値 [38] [[イベント・ハンドラー]]は、 [[null]] か、または[[コールバック]] ([CODE(DOMi)@en[[[EventHandler]]]]) に設定するかのいずれかです。 初期値は [[null]] です。 [SRC[>>35]] [64] [[イベント・ハンドラー]]が最初に非 [[null]] 値に設定された時に、 [[イベント型]]が[[イベント・ハンドラー・イベント型]]であり、 [[捕獲]]が[[偽]]であり、[[コールバック]]が[[イベント・ハンドラー]]に対応する[[イベント・ハンドラー処理算法]]であるような[[イベント・リスナー]]が対象となる[[オブジェクト]]の[[イベント・リスナー]]のリストの末尾に追加されます。 [SRC[>>35]] ;; [65] [[null]] に設定されている間は[[イベント・リスナー]]は追加されません。また [[null]] に変更されたり、別の非 [[null]] 値に変更されたりしても[[イベント・リスナー]]は登録されたままになります。 ;; [66] [[イベント・ハンドラー]]と[[イベント・リスナー]]や[[イベント・ハンドラー処理算法]]は別のものとなります。 [[イベント・ハンドラー]]から [CODE(JS)@en[[[arguments]].[[callee]]]] でアクセスできるのは[[イベント・ハンドラー]]です。[[イベント・リスナー]]や[[イベント・ハンドラー処理算法]]に [[JavaScript]] からアクセスする方法はありません。 * イベント・ハンドラー IDL 属性 [40] [[イベント・ハンドラーIDL属性]]は[[イベント・ハンドラー]]の名前 (>>36) と同名の [[IDL属性]]です [SRC[>>35]]。 [41] ほとんどの場合、その [[IDL属性]]が所属する[[オブジェクト]]の[[イベント・ハンドラー]]に対応します。 例外的に [CODE(HTMLe)@en[[[body]]]] [[要素]]や [CODE(HTMLe)@en[[[frameset]]]] [[要素]]の[[イベント・ハンドラーIDL属性]]は [CODE(DOMi)@en[[[Window]]]] [[オブジェクト]]の[[イベント・ハンドラー]]に対応します。 [42] 対応する[[オブジェクト]]が存在しない場合 (例えば [CODE(DOMi)@en[[[Window]]]] に属さない [CODE(HTMLe)@en[[[body]]]] の場合)、[[イベント・ハンドラーIDL属性]]は[[取得時]]に [[null]] を返し、[[設定時]]に何もしないよう動作しなければ[['''なりません''']] [SRC[>>35]]。 [46] そうでない場合 [SRC[>>35]]、 - [[取得時]]には対応する[[イベント・ハンドラー]]の現在値を返さなければ[['''なりません''']]。 [[null]] かもしれません。 -- [[内部誤り値]]のときは[[イベント・ハンドラー]]を [[null]] に設定し、 [RUBYB[誤り条件]@en[error condition]]に対応する[[例外]]を[[投げ]]なければ[['''なりません''']]。 - [[設定時]]には対応する[[イベント・ハンドラー]]を新しい値に設定しなければ[['''なりません''']]。 ** 特別なイベント・ハンドラーIDL属性 - [43] [CODE(HTMLe)@en[[[body]]]] や [CODE(HTMLe)@en[[[frameset]]]] の[[イベント・ハンドラーIDL属性]] -- 当該[[オブジェクト]]ではなく [CODE(DOMi)@en[[[Window]]]] の[[イベント・ハンドラー]]に対応します。 - [44] [CODE(DOMi)@en[[[MessagePort]]]] の [CODE(DOMa)@en[[[onmessage]]]] -- 副作用を持ちます。 - [45] [CODE(DOMi)@en[[[Window]]]] の [CODE(DOMa)@en[[[onerror]]]] -- [[DOMイベント]]以外でも使われます。 * イベント・ハンドラー内容属性 [47] [[イベント・ハンドラー内容属性]]は[[イベント・ハンドラー]]の名前 (>>36) と同名の[[内容属性]]です [SRC[>>35]]。 [48] [[属性値]]は[[自動セミコロン挿入]]の後 [[JavaScript]] [CODE[[[FunctionBody]]]] [[生成規則]]に[[一致]]する [[JavaScript]] [[コード]]でなければ[['''なりません''']] [SRC[>>35]]。 ;; [49] すなわち、 [[JavaScript]] の[[関数]]の括弧の中身でなければなりません。 [50] [[スクリプトが有効]]な[[閲覧文脈]]にある [CODE(DOMi)@en[[[Document]]]] が所有する[[要素]]の[[イベント・ハンドラー内容属性]]が設定された時、次のように処理しなければ[['''なりません''' [SRC[>>35]]。 ;; [51] そのような[[文書]]に [[adopt]] された時も同様と思われます。 [FIG[ = [52] 対応する[[イベント・ハンドラー]]を [[null]] に設定します。 = [53] [[JavaScript]] の[[スクリプト実行環境]]を準備します。 = [54] [VAR@en[body]] を[[イベント・ハンドラー内容属性]]の新しい値とします。 = [55] [VAR@en[body]] が [CODE@en[[[FunctionBody]]]] として構文解析可能でないか、 構文解析によって [[early error]] を検出した場合は、[[イベント・ハンドラー内容属性を誤りに設定]]し、 停止します。 = [56] [VAR@en[body]] が [[Use Strict Directive]] を含む [[Directive Prologue]] ([CODE(JS)[[["use strict"]]]]) から始まるかどうかを [VAR@en[strict]] とします。 = [57] >>53 の[[スクリプト実行環境]]を使って次のような[[関数]]オブジェクトを作り、 [[スクリプト]]の [[list of code entry-points]] に入れます。 =- 引数リスト [VAR[FormalParameterList]]: [CODE(DOMi)@en[[[Window]]]] の [CODE(DOMa)@en[[[onerror]]]] [[属性]]なら [VAR[event]], [VAR[source]], [VAR[lineno]], [VAR[column]] の4つ、それ以外なら [VAR[event]] の1つ =- 関数本体 [VAR@en[FunctionBody]]: >>55 の構文解析結果 =- 字句環境 [VAR@en[Scope]]: =-= [CODE[[VAR@en[Scope]] := [[NewObjectEnvironment]]([[要素]]の [CODE(DOMi)@en[[[Document]]]], [[大域環境]])]] =-= [[要素]]が[[フォーム所有子]]を持つなら、 [CODE[[VAR@en[Scope]] := [[NewObjectEnvironment]]([[要素]]の[[フォーム所有子]], [VAR@en[Scope]])]] =-= [CODE[[VAR@en[Scope]] := [[NewObjectEnvironment]]([[要素]], [VAR@en[Scope]])]] =- [VAR@en[Strict]]: >>56 の [VAR@en[strict]] = [58] [[スクリプトの大域オブジェクト]]、[[スクリプトの閲覧文脈]]、 [[スクリプトの文書]]、[[スクリプトの参照元情報源]]、[[スクリプトのURL文字符号化]]、 [[スクリプトの基底URL]]を当該[[要素]]による[[節点からスクリプト設定の決定]]により設定します。 = [59] 対応する[[イベント・ハンドラー]]を >>57 の[[関数]]とします。 ]FIG] [60] [DFN[[RUBYB[[[イベント・ハンドラー内容属性を誤りに設定]]]@en[set the event handler content attribute to an error]]]]するとは、対応する[[イベント・ハンドラー]]を[DFN[[RUBYB[[[内部誤り値]]]@en[internal error value]]]]に設定することをいいます。 [[内部誤り値]]は[RUBYB[誤り条件]@en[error condition]]を表現するもので、 [[イベント・ハンドラー内容属性]]が設定された[[資源]]の [[URL]] や[[行番号]]を記録するものです。 [SRC[>>35]] [61] [[イベント・ハンドラー内容属性]]が削除された時は対応する[[イベント・ハンドラー]]を [[null]] に設定しなければなりません。 [SRC[>>35]] ;; [62] [[スクリプトが有効]]でない[[閲覧文脈]]に属しているか[[閲覧文脈]]に属していない[[文書]]に [[adopt]] された場合も同様でしょうかね・・・。 ;; [63] [[閲覧文脈]]に属さない[[文書]]が所有する[[要素]]の[[イベント・ハンドラー内容属性]]の場合は設定しても[[イベント・ハンドラー]]は変更されません [SRC[>>35]]。 * イベント・ハンドラー処理算法 [67] [[イベント・ハンドラー]] [VAR@en[H]] と[[イベント]] [VAR@en[E]] に関する[DFN[[RUBYB[[[イベント・ハンドラー処理算法]]]@en[the event handler processing algorithm]]]]は次のように定義されています [SRC[>>35]]: [FIG[ = [68] [VAR@en[H]] が [[null]] なら停止します。 = [69] [VAR@en[H]] が[[内部誤り値]]なら[[イベント・ハンドラー]]を [[null]] に設定し、当該 [CODE(DOMi)@en[[[Document]]]] の [CODE(DOMi)@en[[[Window]]]] の [CODE(DOMa)@en[[[onerror]]]] を使って[[エラー]]を報告し、停止します。 = [70] [VAR@en[H]] の[[コールバック]]を呼び出します。 -- 引数は [VAR@en[E]] とします。 -- [[callback this value]] は [VAR@en[E]] の [CODE(DOMa)@en[[[currentTarget]]]] とします。 -- [VAR@en[return value]] を[[返り値]]とします。 = [71] [[イベント型][]が [CODE(DOMa)@en[[[mouseover]]]] なら、 [VAR@en[return value]] が [[WebIDL]] の[[真]]値の時[[イベント]]を[[取り消し]]します。 = [72] そうでなく [VAR@en[E]] が [CODE(DOMi)@en[[[BeforeUnloadEvent]]]] なら、 [VAR@en[return value]] が [[WebIDL]] の[[文字列]]値であって [VAR@en[E]] の [CODE(DOMa)@en[[[returnValue]]]] が[[空文字列]]である時、 [CODE(DOMa)@en[[[returnValue]]]] を [VAR@en[return value]] に設定します。 = [73] それ以外なら、[VAR@en[return value]] が [[WebIDL]] の[[偽]]値の時[[イベント]]を[[取り消し]]します。 ]FIG] [EG[ [74] >>70 の [[callback this value]] の規定と、 [CODE(HTMLe)@en[[[body]]]] の [CODE(HTMLa)@en[[[onload]]]] が [CODE(DOMi)@en[[[Window]]]] [[オブジェクト]]の[[イベント・ハンドラー]]であることから、 [PRE(HTML example code)[ ]PRE] ... は文書の読み込み時に [CODE["[object Window]"]] が、[[クリック]]時に [CODE["[object HTMLBodyElement]"]] が [SRC[>>35]] [CODE(JS)@en[[[alert]]]] されることとなります。 ]EG] * イベント・ハンドラーの一覧 [8] この種の[[属性]]のリストは[[事象取扱器属性の一覧]]を参照してください。 * 事象取扱器内容属性 @@ XXX ** スクリプト言語の指定 - [1] [[HTML]] の on[VAR[*]] 属性 (非推奨。) で [[JavaScript]] を使う時に、先頭に [[javascript:]] って書く DQN がなぜか多いな。 - [2] >>1 まあ [[Content-Script-Type:]] 問題についての[[不思議マーク付け]]的解法なのかもしれんが。。。(w - [3] >>1-2 にしても、文法エラーにならずに動く (こともある。) なんて、一体どうなっているんだ? JavaScript 的にはどういう扱いになってるんだろう? それとも [[UA]] の補正なのかな? - [4] >>3 [[ラベル]]。 [5] >>1-4 [[WinIE]] だとそれが“ちゃんと”はたらいて、 [CODE[vbscript:]] と書くと [[VBScript]] になったりしちゃいます。 [10] >748 名前:Name_Not_Found[sage] 投稿日:2005/10/08(土) 04:12:41 ID:??? > HTML のイベント属性に javascript: を書くことについて。 - 文法的には、ただのラベルである。 - そこそこ誰でも知っていて、なんとなく使ったり読んだりしている。 - WinIE が、javascript, jscript, vbscript, vbs, perlscript に反応する。   (プラットフォームも含め、過不足あれば指摘してくれ。) - しかし、きちんとした仕様説明が見当たらない (探せなかっただけかもしれないが)。 ラベル ttp://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/12_Statements.html#LabelledStatement   FOO: for ( .. ) for ( .. ) if ( .. ) continue FOO; におけるラベル FOO と同じ。 ラベルの例をもう一つ。   

alert(6)

どうやら、良く練られた拡張ではなく、姑息な特例だと言わざるを得ない。 ;; [CITE@ja[+ JavaScript の質問用スレッド vol.41 +]] ** 内部での表現 [9] [CITE[Hawk's W3 Laboratory : DHTML Tips : イベントハンドラに関する考察]] [DEL[]] > :更新日時: 2004年09月22日 > 結論から言うと、この「属性の中身のコード」は、対象となる要素に対応するHTMLElementオブジェクトのプロパティに、関数の形で格納されています。イベント発生時にはそのオブジェクトのメソッドとして実行されるわけです。 > 実体が関数であることは、イベント内でargumentsを参照できることから分かります。更に一歩進んでarguments.calleeにアクセスすれば実体の関数そのものにアクセスできます。 > 以下の例では関数の内容を表示しています。alert(arguments.callee);という記述が "そのまま"表示されるのが確認できるでしょう。 > [PRE(HTML example code)[ リンク ]PRE] ただし、実際に試してみれば分かりますが、表示内容(すなわち実装方法)はブラウザによって大きく2系統に分かれます。上記の例はIEでは以下のように表示されるはずです。 > [PRE[ function anonymous() { alert(arguments.callee); } ]PRE] > anonymous(匿名)とは無名のFunctionオブジェクトに仮に付けられた名です。つまりIEでは、単に属性値のスクリプトコードを実行するだけの関数が生成され、対象となるオブジェクトのプロパティに格納されることになります。 > 一方で、NN4.XおよびGeckoベースのブラウザでは以下のようになります。 > [PRE[ function onmouseover(event) { alert(arguments.callee); } ]PRE] > Operaではこうです。 > [PRE[ function anonymous(event) { alert(arguments.callee); } ]PRE] > KHTMLベースのブラウザではこうなります。 [PRE[ function (event) { alert(arguments.callee); } ]PRE] > 名前の有無や名前が無い場合の表現など、瑣末な違いはありますが、いずれもeventという仮引数が存在していることが大きな特徴です。この仮引数はイベントオブジェクト(NN4.Xにおいてはevent object、その他の場合はDOM2 EventsにおけるEventインターフェイスを実装したオブジェクト)を表しています。 > NN4.Xのイベントモデルでも、DOM2 Eventsでも、イベントに関する情報はイベントオブジェクトの形で、イベントハンドラとして登録された関数の第一引数に渡されます。だからこのような形の関数になるのは理にかなっているのですが、そのとき仮引数の名前が”event”になることなどは特に標準化されていないので注意が必要です。 > またこのeventという名前は、偶然にも?IEのwindow.eventと同じなので、 > [PRE(HTML example code)[ リンク ]PRE] このように記述すれば、関数fooにはブラウザを問わず第一引数にeventオブジェクトが渡されます(もっともfoo内での条件分岐は必要になりますが)。 ;; [11] [[関数]]内で[[関数]]名を使って再起呼び出しできるのかな? * [CODE(JS)@en[window.event]] [6] [[WinIE7]], [[Opera]], [[WebKit]] は対応しているみたいです。 [7] [[Firefox3]] は対応していないみたいです。 ;; [12] [[事象取扱器属性]]の時だけでなく、 [CODE(DOMm)@en[[[attachEvent]]]] した[[事象取扱器]]の時にも設定されているの? [13] [CITE@en[(X)HTML5 Tracking]] ([TIME[2009-09-30 00:13:50 +09:00]] 版) [14] [CITE['''['''whatwg''']''' Additional onxxxx event attributes for DOM Level3 Events]] ([TIME[2010-12-01 08:26:00 +09:00]] 版) [15] [CITE@en[Web Applications 1.0 r5933 Be better about how we define the creation of scripts for event handler attributes (specifically, how we interact with the JS spec).]] ( ([TIME[2011-03-04 09:52:00 +09:00]] 版)) [16] [CITE[''''''[''''''whatwg'''''']'''''' on* attributes on DOM elements]] ( ([TIME[2011-06-18 08:37:31 +09:00]] 版)) [17] [CITE[IRC logs: freenode / #whatwg / 20110728]] ( ([TIME[2011-08-07 22:56:46 +09:00]] 版)) [18] [CITE[IRC logs: freenode / #whatwg / 20111117]] ( ([TIME[2011-11-19 14:21:09 +09:00]] 版)) [19] [CITE[''''''[''''''whatwg'''''']'''''' API design restrictions due to barewords in onxxx="" attributes]] ( ([TIME[2011-12-03 12:41:47 +09:00]] 版)) [20] [CITE@en[Writing forward-compatible websites - MDN]] ( ([TIME[2011-12-03 12:41:52 +09:00]] 版)) [21] [CITE[IRC logs: freenode / #whatwg / 20120427]] ( ([TIME[2012-05-06 12:41:01 +09:00]] 版)) [22] [CITE[IRC logs: freenode / #whatwg / 20120518]] ( ([TIME[2012-05-31 20:23:25 +09:00]] 版)) [23] [CITE@en[''''''[''''''proximity'''''']'''''' HTML's WebIDL Function]] ( ([[Marcos Caceres]] 著, [TIME[2012-05-28 20:25:42 +09:00]] 版)) [24] [CITE[IRC logs: freenode / #whatwg / 20120620]] ( ([TIME[2012-07-04 21:39:52 +09:00]] 版)) [25] [CITE@en[Web Applications 1.0 r7235 Improve compatibiliy for legacy features.]] ( ([TIME[2012-08-10 03:02:00 +09:00]] 版)) [26] [CITE[''''''[''''''whatwg'''''']'''''' Specification unclear about how HTMLElement.prototype.onscroll's getter/setter should behave for "body" elements]] ( ([TIME[2012-12-04 06:17:20 +09:00]] 版)) [27] [CITE@en[Web Applications 1.0 r7560 Remove some IDL shadowing. See also bug 20225.]] ( ([TIME[2012-12-04 09:43:00 +09:00]] 版)) [28] [CITE@en[Web Applications 1.0 r7561 Recent changes to body also apply to frameset.]] ( ([TIME[2012-12-05 03:47:00 +09:00]] 版)) [29] [CITE@en[WICD Mobile 1.0]] ( ([TIME[2010-08-17 16:50:39 +09:00]] 版)) [30] [CITE[''''''[''''''whatwg'''''']'''''' Specification unclear about how HTMLElement.prototype.onscroll's getter/setter should behave for "body" elements]] ( ([TIME[2013-01-08 08:36:05 +09:00]] 版)) [31] [CITE@en[Web Applications 1.0 r7638 Factor out some common event handler declarations in IDL.]] ( ([TIME[2013-01-08 08:45:00 +09:00]] 版)) [32] [CITE@en[Web Applications 1.0 r7667 Clean up how we define event handlers that are shadowed for Window on .]] ( ([TIME[2013-01-30 04:18:00 +09:00]] 版)) [33] [CITE@en[Web Applications 1.0 r7668 Fix bug 18626 and actually do what the previous checkin was trying to do.]] ( ([TIME[2013-01-30 05:12:00 +09:00]] 版))