※スマホ対応はしてません。

タグ: event

jQueryのtrigger()みたいに、イベントを作ったり発火させたりしてみよう。(DOMおれおれAdvent Calendar 2015 – 22日目)

カテゴリー: JavaScript

DOMおれおれAdvent Calendar 2015 – 22日目

2015-12-22

jQueryなら $el.trigger('foo') とするだけで簡単なんだけど、DOMでやるとちょっと面倒くさいです。

独自イベントを作る

CustomEventというコンストラクターを使います。第一引数にイベント名を与えます。

var type = 'foo';
var myEvent = new CustomEvent(type);

console.log(myEvent, myEvent.type);

基本的にこれで良いのだけど、IEはエラーになります。しかもCustomEventコンストラクターはあるのに使っちゃ駄目っていう仕様です。(だから有無だけじゃ判断できない。) IEてそういうところあるよね……。

というわけで

仕方ないからIEでも動くやり方にします。

var type = 'foo';
var myEvent = document.createEvent('CustomEvent');
myEvent.initCustomEvent(type, false, false, null);

console.log(myEvent, myEvent.type);

IEでも動くんならこれでいいんじゃ?

と思う方もおられるかと思いますが、なんでもこっちのやり方は廃止の予定だそうで。 new CustomEvent() の方を使ってね、だそうです。

イベントに情報を持たせる

CustomEventの場合、 event.detail で参照できる情報を設定する事ができます。

var type = 'foo';
var detail = { sushi:'tuna' };

var event1 = document.createEvent('CustomEvent');
event1.initCustomEvent(type, false, false, detail);
console.log(event1.detail.sushi);  // => "tuna"

var event2 = new CustomEvent(type, { detail:detail });
console.log(event2.detail.sushi);  // => "tuna"

本物?のイベントの見分け方

ユーザー操作からウェブブラウザーが生成した本物のイベントは、 isTrusted プロパティが true になります。JavaScriptから生成した場合はこれが false になるので、ここを見ると「あ、こいつ騙りだ!」と分かります。

クリックイベントを作る

引数が多くて割と面倒くさい。

var event = document.createEvent('MouseEvents');
event.initMouseEvent('click',
  true,    // bubbles
  true,    // cancelable
  window,  // view
  null,    // detail
  0,       // screenX
  0,       // screenY
  0,       // clientX
  0,       // clientY
  false,   // ctrlKey
  false,   // altKey
  false,   // shiftKey
  false,   // metaKey
  0,       // button
  null     // relatedTarget
);

IEを捨てられるなら new MouseEvent('click') だけで事足ります。情報を与える必要がある場合は第二引数にオブジェクトを指定します。

var event = new MouseEvent('click', {
  bubbles: true,
  button: 1
});

イベントを発火させる

dispatchEvent() でイベントを発火させる事ができます。

// eventは作成済みとします

var el = document.querySelector('#el');

el.addEventListener('click', function(event) {
  console.log(event.type);
});

el.dispatchEvent(event);

上記の例の通り、イベントは普通に addEventListener() で監視できます。ちなみに監視はあくまでイベント名を対象に行うので、MouseEventでもCustomEventでも、 type が "click" であれば反応します。

ちなみにjQuery

jQueryはjQuery.Eventという独自のコンストラクターを用意して、DOMのイベントとは無関係にやってるみたいです。なので本来の event にあるはずのプロパティがなかったりする。

元のイベントは event.originalEvent に格納されるので、適宜そちらを利用します。携帯端末のタップ関係とかこっち使うね。

参考

イベント監視で教えてもらえる情報いろいろ。(DOMおれおれAdvent Calendar 2015 – 21日目)

カテゴリー: JavaScript

DOMおれおれAdvent Calendar 2015 – 21日目

2015-12-21

イベント監視のコールバックでもらえるeventオブジェクト、色々使えます。

target でイベント発生要素

あと currentTarget で監視対象要素、 relatedTarget で関連要素。

過去記事をどうぞ。

type でイベントの種類

例えば click イベントを監視していたら event.type は "click" になります。複数のイベント監視を同じコールバック関数で行う場合に利用できます。

var listener = function(event) {
  console.log(event.type);
};
el.addEventListener('focus', listener);
el.addEventListener('click', listener);

マウス操作とタッチ操作をある程度同一視しつつ一部違う処理、なんてときに便利かもしれません。あとは諸々のイベントを監視してログ取ってるときとか。

timeStamp

イベント発生日時の数字です。

だいたい Date.now() と同じくらいになるかと思います。 new Date(event.timeStamp) してやるとDateオブジェクトになります。

Firefoxでバグってる

なんか変な数字が返ってきます。

『11年くらいバグってる』そうです。まじかよ。

内容が変わるっぽい

Dateと同じミリ秒単位の数字が設定されてたんですが、最近この値をページ読み込み時を起点としたマイクロ秒単位の値になりそうな流れです。

defaultPrevented でキャンセル済みか確認

preventDefault() されると true になります。

el.addEventListener('click', function(event) {
  console.log(event.defaultPrevented);  // => false
  event.preventDefault();
  console.log(event.defaultPrevented);  // => true
});

eventPhase でイベント発火の段階を知る

状態 定数
未発火 Event.NONE
キャプチャ中 Event.CAPTURING_PHASE
対象要素 Event.AT_TARGET
浮上中 Event.BUBBLING_PHASE

「キャプチャ中」てのはあれです、 addEventListener() の第三引数で true を指定した時のあれです。

あとIEは Event.NONE を持ってないみたい。

その他

だいたいよくわかってない。

  • bubbles … 浮上し得るかどうか。コールバック関数に与えられるものは全部 true ? 新規作成したオブジェクトだと false
  • cancelable … preventDefault() でキャンセルできるか。したか、じゃない。
  • isTrusted … 利用者操作からのイベントであるか。JavaScriptが作成したEventオブジェクト等だと false

参考

イベントに関係する要素は教えてもらえるよ。(DOMおれおれAdvent Calendar 2015 – 19日目)

カテゴリー: JavaScript

DOMおれおれAdvent Calendar 2015 – 19日目分

2015-12-19

イベントのコールバック実行時、 this が監視対象の要素になるんですが、引数で与えられるEventオブジェクトからも得る事ができます。

<div id="wrapper">
  <button id="button"></button>
</div>
var el = document.querySelector('#wrapper');
el.addEventListener('click', function(event) {
  console.log(this.id, event.target.id, event.currentTarget.id);
});

event.currentTarget

event.currentTarget が this と同じになります。(なので、よく bind() で this は違うものにしたりします。)

event.target

event.target は最初にイベントが起こった要素です。上記の例だと監視しているのは <div> です。その要素内の <button> をクリックした場合、 event.target はクリックした <button> 、 event.currentTarget は監視している <div> になります。

event.relatedTarget

他に関連する要素を格納しています。マウス操作のイベントにのみ設定されます。 focus や mouseenter のイベントで、「どこから移動してきたか」「どこへ移動したか」を示したります。

<input id="text-1" type="text" />
<input id="text-2" type="text" />
var el = document.querySelector('#text-1');
el.addEventListener('focus', function(event) {
    console.log('from:', event.relatedTarget);
});
el.addEventListener('focusout', function(event) {
    console.log('to:', event.relatedTarget);
});

使った事ないです。古いIEでも使えますが、Firefoxが頑なに実装してません。(?)

参考

スクロールで何かするための処理まとめ。(JavaScriptおれおれAdvent Calendar 2014 – 21日目)

カテゴリー: JavaScript

JavaScriptおれおれAdvent Calendar 2014 – 21日目

よくある処理についてまとめました。

スクロールの監視

windowを対象にscrollイベントを監視するだけです。documentでも動くけど、古いIEは駄目。いちいち変える理由もないので、windowだけ使えばよろし。

$(window  ).on('scroll', function(event){ console.log('window'); });
$(document).on('scroll', function(event){ console.log('document'); });  // IE 8では呼ばれない

スクロール位置の取得

document.documentElement.scrollTopに現在のスクロール位置が格納されています。ちなみにdocument.documentElementはHTML要素の事。ただし、WebKitだけBODY要素から、document.body.scrollTopで得る必要があります。

一度だけ取得するならこんなコードで。

var scrollTop = document.documentElement.scrollTop || documentElement.body.scrollTop;

何度も取得するなら、要素を事前にキャッシュしておくと良いかと。

var elScrollable;
if (navigator.userAgent.indexOf('WebKit') < 0) {
    elScrollable = document.documentElement;
}
else {
    elScrollable = document.body;
}

var scrollTop = elScrollable.scrollTop;

ページ最下部へのスクロール到達判定

「スクロール位置 + 画面高さ」が「ページ高さ」と等しくなれば、最下部へ到達したものと考えます。

画面高さの取得

(さらに…)