Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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.cancelBubbleevent.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 = falsecancelBubble = 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) 関数は以下のロジックを持っています。

  1. e.preventDefault が存在するかどうかをチェックします。これは、モダンブラウザ(W3C標準に準拠しているブラウザ)であれば preventDefault() メソッドを持っているため、その存在を確認するものです。
  2. もし e.preventDefault が存在すれば、e.preventDefault() を呼び出します。これにより、標準的な方法でイベントのデフォルト動作がキャンセルされます。
  3. もし 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);

コアとなるコードの解説

  1. 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キーのデフォルト動作を抑制する目的で、イベント伝播の停止が代替手段として用いられています。
  2. 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) ヘルパー関数に置き換えられました。

この変更により、Go PlaygroundのJavaScriptコードは、IE8を含むより広い範囲のブラウザで、キーボードイベントのデフォルト動作をより堅牢に制御できるようになりました。

関連リンク

  • Go Playground: Go言語のコードをブラウザ上で実行できる公式ツール。このコミットが修正したフロントエンド部分の一部。
  • Goのコードレビューシステム (Gerrit): コミットメッセージに記載されている https://golang.org/cl/5888043 は、この変更がGoプロジェクトのGerritレビューシステムでレビューされたことを示しています。

参考にした情報源リンク