この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2011年7月)

2011年7月29日

Bug-org 552707 While we're expanding selection by dragging, the selection root element should capture mouse events and all scrollable elements should be scrollable
初回投稿日時: 2011年07月29日10時34分53秒
最終更新日時: 2011年07月29日10時35分31秒
カテゴリ: Mozilla Core Mozilla8 バグ修正
SNS: (list)

マウスでテキストを選択中に、選択を開始した要素に一番近い、スクロール可能な要素がマウスをキャプチャしてしまい、それ以外のスクロール可能な要素をスクロールする手段もないし、キャプチャしてる要素の外側の選択状態も変更できるのはおかしい、というバグです。これの修正が今、闘っているregression祭りの元凶です。

まだ対応中のバグで挙動が変更されますので、詳しい説明は後日に回しますが、ざっくりと説明すると、まず、マウスの左ボタンが押された時、選択範囲のルートとなる要素がマウスイベントをキャプチャします。そして、これより外側の要素の内容は選択できません。つまり、意図的に特定要素内に選択範囲を制限できます

<body>
  <div id="div1">
    <p>aaaaaaaaaaaaa</p>
    <p>bbbbbbbbbbbbb</p>
  </div>
  <div id="div2">
    <p>ccccccccccccc</p>
  </div>
</body>

このケースで、マウスのボタンを#div1内で押した場合、#div1内のみが選択できた方が便利だとします。その場合、以下のように記述します。

<script type="text/javascript">
var div1 = document.getElementById("div1");

function div1MouseDownHandler(event)
{
  if (event.button == 0) {
    div1.setCapture(false); // not event.target!
  }
}

div1.addEventListener("mousedown", div1MouseDownHandler, false);
</script>

ただし、文字列のマウスでの選択は特に標準化されている訳ではありませんので、他のブラウザでこの手法で選択範囲を制限できなくてもそれはバグであるという話ではありません。これはあくまでFirefoxでの挙動を利用した手法であることに注意してください。

話を戻すと、これにより、マウスカーソルを選択範囲のルート要素の外側にまで移動すると、その要素は今まで通りにスクロールすることが可能ですが、問題はその内側にある他のスクロール可能な要素です。

これらは、そのスクロール可能な要素の辺(bugzilla上でedgeと呼んでいる部分)にカーソルを移動した時に自動的にスクロールするようにしました。このため、選択中にあらゆるスクロール可能な要素は(ただし、その時に選択可能な要素であること。例えば、textareaやiframeの様に、外側から選択できない要素は除き)、全てスクロールできるようになりました。

関連するかもしれないエントリ

bug-org 552707を含むエントリ