今回はJavaScriptの話です
意外と知らない(騙されている人)が多い気がします

イベント

JavaScriptではHTMLのエレメントがクリックされた時など 「ユーザが何か操作した」時(イベントが起きた時)に関数を実行させることができます

//(1) <a id="atag" href="#" onclick="fn();return false;">りんく</a> //(2) document.getElementById("atag").onclick = fn; //(3) document.getElementById("atag").addEventListener("click",fn,false);

イベントに関数を設定する方法はたぶん全部で3つ

一番上は HTMLに直接書くやつ
HTMLにあんまり書きたくないしChrome拡張機能作ってると分けないと怒られるので試しにやってみるときくらいしか書かないです

次が個人的に良く使う書き方
エレメントのプロパティonclickに関数を入れておくとイベント発生時に実行してくれます
最後のより書きやすいです

最後のは長いですがいいところもあります
1つめが関数を複数セットできること
(2)のやり方だと2つめの関数をセットしようとすると上書きしてしまいます
登録済みの関数と登録しようとしてる関数の2つを実行する関数を作ってそれを登録するということもできますがすごく複雑なつくりになります

例↓
document.getElementById("atag").onclick = fn; function fn(){ fnA(); fnB(); } function fA(){ fnAA(); fnAB(); } function fAA(){ fnAAA(); fnAAB(); } // .......
addEventListenerメソッドを使うといくつでも登録できるのでこんなことをしなくて済みます
ただ イベントを消したい時に キーとして設定した関数が必要です
無名関数を直接設定すると消せなくなります

そして もう1つのいいところ
今falseになっている3つめの引数でイベントをキャプチャするタイミングを選べます

JavaScriptではこんな感じでイベントが起きた所を探します
js-event-bubbling


矢印のようにDOMツリーの一番親からそれぞれの一番下の子まで見て また一番親まで戻ってきます
この流れのどのタイミングでキャプチャするかをaddEventListenerの3つめの引数で選びます
上から下に行くタイミングでキャプチャするにはtrue 下から上に行くタイミングでキャプチャするにはfalseを選びます
基本はfalseだそうです
なぜかは知りません
IEにでもあわせてるじゃないでしょうか

流れは上から下で下から上なので
divelem = document.getElementsByTagName("div").item(0); divelem.addEventListener("click", function(){console.log(false)}, false); divelem.addEventListener("click", function(){console.log(true)}, true);
を設定して divエレメントをクリックすると
true
false
と表示されます
※Chromeだとたまにfalseが先に来るので謎です

ところでこの絵は省略してるので縦一本ですが divやbodyはいっぱい子があると思ってください

バブリング


イベントが下から上に上がっていくと書きましたが実際のWebページだとこんなイメージです

js-event-bubbling2

pのところをクリックしてもdivやbodyもクリックされた扱いになるわけです
この下(内)側から上(外)側に伝播して(つたわって)いくことをバブリングというそうです
名前の由来は泡が上にいくから?

名前はなんでもいいんですが JavaScriptではこの伝播を止めることができます
こんなイメージです
「STOP!」のところまでしかイベントが伝播しません
js-event-bubbling-stop

図のようにpで止めるとdivやbodyのクリックイベントは起きません
伝播のストップは下から上に向かってのみ起きるのでaddEventListenerでfalseを指定したときのみ関係します
イベントを自分だけで処理して親に伝えたくない時に止めましょう

反対に trueにしてると誰かに遮られることなくイベントをキャプチャできます
3つ目の引数について何も教えずにとりあえずfalseにしとけばいいって 書いてるところが多いですがそれでfalseにしてると 「画面全体で右クリックイベントをキャプチャして処理したいのに ライブラリで設定したエレメント上だけイベントが起きない」ってことになって困ります
こういうときにtrueを使います
GoogleMapsとかたしかそうだったような気がします
jQueryのデザイン部分もありそうです

伝播の止め方

JavaScriptでイベントの伝播を止めれると書きましたがその方法はevent.stopPropagation()を実行するだけ 簡単です
var pelem = document.getElementsByTagName("p").item(0); pelem.onclick = function(eve){ eve.stopPropagation(); };

デフォルト動作のキャンセル

もう1つイベント関連で ブラウザのデフォルトの動作をキャンセルするということができます
submitボタンでフォームの内容を送るのをキャンセル aタグでページ遷移するのをキャンセル 右クリックしてメニューが出てくるのをキャンセル Ctrl-Fで検索ウィンドウが出るのをキャンセルという感じです

そういえば昔 Ctrl-Fを無効化してブラウザごとに ブラウザの検索ウィンドウに似せたものを表示して検索するとそのキーワードがサイト管理者のサーバに送られるサイトが話題になりましたよね
あれって 結局何がしたかったんでしょうか
ページ内検索のキーワード収集とか何の得があるのかよくわかりません

※ChromeではF1のヘルプだけキャンセルできなかったような

方法です
var pelem = document.getElementsByTagName("p").item(0); pelem.onclick = function(eve){ eve.preventDefault(); };

イベントのpreventDefaultメソッドを実行するとそのイベントのデフォルト挙動が行われなくなります

やっと本題

return falseです

ぐぐってみると イベントに登録した関数で返り値にfalseを返すと preventDefaultとstopPropagationの両方の意味があると書いてるところが多いです

これは間違いです!

これはjQueryのイベントを設定するときの仕様でただのJavaScriptにそんな機能はありません

jQueryの解説として書いてるところは問題ないのですがJavaScriptの説明として書いていたり 何も注意書きなしに書いてるところもあるので注意です

JavaScriptの説明のように書いておいて サンプルソースではjQueryなんてのもあります


普通のJavaScriptではpreventDefaultとstopPropagationの両方はしてくれませんが preventDefaultだけは行います
混ざってきて複雑になるので自分で両方書いたほうが安全だしわかりやすいと思います