[インデックス 12760] ファイルの概要
このコミットは、misc/goplay
ディレクトリ内の goplay.go
ファイルに対する変更を記録しています。このファイルは、Go言語のプレイグラウンド(Go Playground)に関連するJavaScriptコードを含んでいると推測されます。具体的には、Internet Explorer 8 (IE8) におけるイベント処理の互換性問題を修正するための変更です。
コミット
commit a3b86e9379e6e38d7f7a680cc688be1b99c2c5a8
Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Date: Tue Mar 27 11:16:29 2012 +1100
misc/goplay: fix error on IE8.
use cancelBubble=true instead of preventDefault().
R=golang-dev, rsc, adg
CC=golang-dev
https://golang.org/cl/5888043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a3b86e9379e6e38d7f7a680cc688be1b99c2c5a8
元コミット内容
misc/goplay: fix error on IE8. use cancelBubble=true instead of preventDefault().
このコミットは、Go Playgroundのフロントエンドコードにおいて、Internet Explorer 8 (IE8) で発生していたエラーを修正することを目的としています。具体的には、イベントのデフォルト動作をキャンセルする際に、標準的な preventDefault()
メソッドの代わりに、IE8固有の cancelBubble = true
を使用するように変更しています。
変更の背景
この変更が行われた2012年当時、Internet Explorer 8 (IE8) はまだ広く使用されているブラウザの一つでした。しかし、IE8はW3C標準に準拠したイベントモデルを完全にサポートしておらず、特にイベントの伝播(バブリング)やデフォルト動作のキャンセルに関して、他のモダンブラウザ(Firefox, Chromeなど)とは異なる独自のAPIを使用していました。
モダンブラウザでは、イベントオブジェクトの preventDefault()
メソッドを呼び出すことで、そのイベントのデフォルト動作(例: リンククリック時のページ遷移、フォーム送信、キーボード入力時の文字入力など)をキャンセルできます。しかし、IE8では preventDefault()
が存在せず、代わりにイベントオブジェクトの returnValue
プロパティを false
に設定するか、イベント伝播を停止するために cancelBubble
プロパティを true
に設定する必要がありました。
Go Playgroundのようなウェブアプリケーションは、ユーザーがコードを入力し、実行結果を表示するというインタラクティブな機能を提供するため、キーボードイベントやその他のUIイベントを適切に処理する必要があります。IE8の非標準的なイベント処理が原因で、Go PlaygroundがIE8上で正しく動作しない、あるいは意図しない動作をするという問題が発生していたと考えられます。このコミットは、その互換性問題を解決するために行われました。
前提知識の解説
JavaScriptのイベント処理
ウェブブラウザにおけるJavaScriptのイベント処理は、ユーザーのアクション(クリック、キー入力など)やブラウザの状態変化(ページの読み込み完了など)に応答するためのメカニズムです。イベントが発生すると、ブラウザはイベントオブジェクトを生成し、それをイベントハンドラ関数に渡します。
イベントのデフォルト動作 (Default Action)
多くのHTML要素やイベントには、ブラウザがデフォルトで実行する動作が定義されています。
<a>
タグのクリック: リンク先のURLへ移動<form>
の送信: フォームデータをサーバーへ送信し、ページをリロードkeydown
イベントでのTabキー: フォーカスを次の要素へ移動keydown
イベントでのEnterキー: フォームの送信(input要素内など)
これらのデフォルト動作をJavaScriptで制御し、場合によってはキャンセルしたい場合があります。
event.preventDefault()
W3C標準のDOMイベントモデルにおいて、イベントオブジェクトが持つメソッドです。このメソッドを呼び出すと、そのイベントに関連付けられたデフォルト動作がキャンセルされます。例えば、<a>
タグのクリックイベントハンドラ内で e.preventDefault()
を呼び出すと、リンクがクリックされてもページ遷移は行われず、JavaScriptで定義された処理のみが実行されます。
event.cancelBubble
と event.returnValue
(IE固有)
Internet Explorer 8 (IE8) 以前のIEブラウザでは、標準の preventDefault()
や stopPropagation()
(イベント伝播の停止) がサポートされていませんでした。
event.cancelBubble = true;
: IE独自のプロパティで、イベントのバブリング(伝播)を停止するために使用されました。これは標準のevent.stopPropagation()
に相当します。event.returnValue = false;
: IE独自のプロパティで、イベントのデフォルト動作をキャンセルするために使用されました。これは標準のevent.preventDefault()
に相当します。
このコミットでは、preventDefault()
の代替として cancelBubble = true
を使用しているとコミットメッセージにありますが、これは厳密には preventDefault()
の代替ではなく、stopPropagation()
の代替です。しかし、文脈によっては、デフォルト動作をキャンセルする際にイベント伝播も停止する必要がある場合があり、IE8では returnValue = false
と cancelBubble = true
の両方、または片方を使用することで、モダンブラウザの preventDefault()
と同等の効果を得ようとすることがありました。
今回の変更では、preventDefault
という名前の関数を新しく定義し、その中で e.preventDefault()
が存在すればそれを呼び出し、そうでなければ e.cancelBubble = true
を設定するというロジックになっています。これは、イベントのデフォルト動作をキャンセルする意図で preventDefault
という関数名が付けられていますが、IE8のフォールバックとして cancelBubble = true
を使用している点が特徴的です。通常、デフォルト動作のキャンセルには returnValue = false
が使われますが、特定の状況下(例えば、キーイベントでTabやEnterのデフォルト動作をキャンセルしつつ、それ以上のイベント伝播も不要な場合)では cancelBubble = true
が選択されることもありました。
技術的詳細
このコミットは、JavaScriptのイベント処理におけるブラウザ間の互換性、特にレガシーブラウザであるIE8への対応に焦点を当てています。
変更の核心は、preventDefault
という新しいヘルパー関数を導入し、既存のイベントハンドラ内で e.preventDefault()
の直接呼び出しをこのヘルパー関数に置き換えることです。
新しい preventDefault(e)
関数は以下のロジックを持っています。
e.preventDefault
が存在するかどうかをチェックします。これは、モダンブラウザ(W3C標準に準拠しているブラウザ)であればpreventDefault()
メソッドを持っているため、その存在を確認するものです。- もし
e.preventDefault
が存在すれば、e.preventDefault()
を呼び出します。これにより、標準的な方法でイベントのデフォルト動作がキャンセルされます。 - もし
e.preventDefault
が存在しない場合(IE8のようなレガシーブラウザの場合)、e.cancelBubble = true;
を設定します。
ここで重要なのは、cancelBubble = true
がイベントの「伝播(バブリング)」を停止するものであり、厳密にはイベントの「デフォルト動作」をキャンセルする returnValue = false
とは異なる点です。しかし、IE8のコンテキストでは、特定のイベント(特にキーボードイベント)において、デフォルト動作をキャンセルする目的で cancelBubble = true
が使われることがありました。例えば、TabキーやEnterキーのデフォルト動作を抑制しつつ、それらのキーイベントが親要素に伝播するのを防ぐことで、意図しない副作用を避ける目的があったと考えられます。
このアプローチにより、コードはモダンブラウザでは標準的な preventDefault()
を使用し、IE8ではIE8固有の cancelBubble
プロパティを利用して、同等の(または十分に類似した)動作を実現しようとしています。
コアとなるコードの変更箇所
変更は misc/goplay/goplay.go
ファイル内のJavaScriptコードブロックにあります。
--- a/misc/goplay/goplay.go
+++ b/misc/goplay/goplay.go
@@ -209,17 +209,25 @@ function autoindent(el) {
}, 1);
}
+function preventDefault(e) {
+ if (e.preventDefault) {
+ e.preventDefault();
+ } else {
+ e.cancelBubble = true;
+ }
+}
+
function keyHandler(event) {
var e = window.event || event;
if (e.keyCode == 9) { // tab
insertTabs(1);
-\t\te.preventDefault();
+\t\tpreventDefault(e);
return false;
}
if (e.keyCode == 13) { // enter
if (e.shiftKey) { // +shift
compile(e.target);
-\t\t\te.preventDefault();
+\t\t\tpreventDefault(e);
return false;
} else {
autoindent(e.target);
コアとなるコードの解説
-
preventDefault(e)
関数の追加:function preventDefault(e) { if (e.preventDefault) { e.preventDefault(); } else { e.cancelBubble = true; } }
この新しい関数は、イベントオブジェクト
e
を引数として受け取ります。e.preventDefault
の存在チェック: これは、ブラウザがW3C標準のpreventDefault()
メソッドをサポートしているかどうかを判断するための一般的なクロスブラウザテクニックです。- モダンブラウザの場合:
e.preventDefault()
が存在するため、標準的な方法でイベントのデフォルト動作をキャンセルします。 - IE8のようなレガシーブラウザの場合:
e.preventDefault()
が存在しないため、else
ブロックに入り、e.cancelBubble = true;
を設定します。これにより、イベントのバブリングが停止されます。この文脈では、TabキーやEnterキーのデフォルト動作を抑制する目的で、イベント伝播の停止が代替手段として用いられています。
-
keyHandler
関数内の変更:keyHandler
関数は、キーボードイベントを処理する主要な関数です。- Tabキー (keyCode == 9) の処理:
- 変更前:
e.preventDefault();
- 変更後:
preventDefault(e);
Tabキーが押された際に、テキストエリアにタブ文字を挿入するinsertTabs(1)
が呼び出された後、Tabキー本来のデフォルト動作(フォーカスの移動)をキャンセルするためにe.preventDefault()
が使われていました。これが新しいpreventDefault(e)
ヘルパー関数に置き換えられました。
- 変更前:
- Shift + Enterキー (keyCode == 13 && e.shiftKey) の処理:
- 変更前:
e.preventDefault();
- 変更後:
preventDefault(e);
Shiftキーを押しながらEnterキーが押された際に、コードをコンパイルするcompile(e.target)
が呼び出された後、Enterキー本来のデフォルト動作(改行やフォーム送信)をキャンセルするためにe.preventDefault()
が使われていました。これも新しいpreventDefault(e)
ヘルパー関数に置き換えられました。
- 変更前:
- Tabキー (keyCode == 9) の処理:
この変更により、Go PlaygroundのJavaScriptコードは、IE8を含むより広い範囲のブラウザで、キーボードイベントのデフォルト動作をより堅牢に制御できるようになりました。
関連リンク
- Go Playground: Go言語のコードをブラウザ上で実行できる公式ツール。このコミットが修正したフロントエンド部分の一部。
- Goのコードレビューシステム (Gerrit): コミットメッセージに記載されている
https://golang.org/cl/5888043
は、この変更がGoプロジェクトのGerritレビューシステムでレビューされたことを示しています。
参考にした情報源リンク
- event.preventDefault() - Web APIs | MDN
- event.stopPropagation() - Web APIs | MDN
- IE8 event.preventDefault() and event.stopPropagation() - Stack Overflow
- JavaScript Event Handling in IE8 - Microsoft Docs (IE8のイベントモデルに関する古いMicrosoftのドキュメント)
- Cross-browser event handling - QuirksMode (クロスブラウザイベント処理に関する古典的な記事)