質問: 通常、ブラウザにJpegファイルをドロップした場合、全画面表示されると思います。実際には全画面表示やモーダルではなくページが遷移しているのかと思います。 現状、input type="file"をドラッグアンドドロップで拾えるようにするエリア(#exclude)を設けているのですが、ユーザが誤って他の箇所にドロップした際に、ページの遷移を避けるコードを考えております。 1)以下のコードくらいしか、思いつかなかったのですが、動作しません。ページ遷移がchangeイベントではないからなのでしょうか? 2)そもそも広域な要素に対してpreventDefault()をすると本来起きてほしい、イベントをも起きなくしてしまう懸念があるとも考えているのですが、もしそうであれば、他に誤ドロップを防止するために取りうる良い方法はございますでしょうか? よろしくお願い申し上げます。 ``` $('body:not(#exclude)').on('change',function(){ preventDefault(); //修正コード $('body:not(#exclude)').on('drop',function(e){ e.preventDefault(); }) ```
回答: 1)ページ遷移に関わるイベントは`change`イベントではなく, `window`オブジェクトが発する`beforeunload`イベントです. 本イベントに関数を紐付けることで実際にページ遷移する前にユーザーに確認をとることができます. 例えばドロップ処理においては誤ったノードに対してドロップ操作をした際の誤ページ遷移を防ぐことが可能となります. ``` window.addEventListener("beforeunload", function (e) { var confirmationMessage = "\o/"; e.returnValue = confirmationMessage; // Gecko and Trident return confirmationMessage; // Gecko and WebKit }); ``` 引用元 2)いいえ, そのようなことはありません. `preventDefault`メソッドはブラウザ規定の動作をキャンセルするだけでイベントの発生を妨げるものではありません. 一般にJavaScriptではイベントをDOMツリー内でイベントを発生させた要素から親要素の方に向かって順に通知していき, 最終的に全てのルートである`window`オブジェクトに通知します(これを**イベントのバブリング**と呼びます). `drop`イベントについても同様です. ここで`drop`イベントが`window`オブジェクトに通知されるとブラウザ規定の動作として「ページ遷移」が発生するので, ``` window.ondrop = function(e){ e.preventDefault(); }; ``` として動作をキャンセルするわけです. こうした上でドロップ操作を要する要素に対し`drop`イベントにリスナ関数を登録すればよいのです.