web-dev-qa-db-ja.com

ブラウザでページ上のすべてのイベントをプログラムでキャッチすることは可能ですか?

まず、W3C標準で定義されているイベントタイプのリストを次に示します。 (このリストは、HTML5標準で定義されているonevent属性に基づいています。他にも数十のイベントタイプがあると想定していますが、このリストは十分に長いものです。)

  • アボート
  • 残像
  • 印刷前
  • アンロード前
  • ぼかす
  • 遊べる
  • canplaythrough
  • 変化する
  • クリック
  • コンテキストメニュー
  • コピー
  • キューチェンジ
  • 切る
  • dblclick
  • DOMContentLoaded
  • 引っ張る
  • ドラッグエンド
  • ドラッグエンター
  • ドラッグリーブ
  • ドラッグオーバー
  • ドラッグスタート
  • drop
  • durationchange
  • 空になった
  • 終了しました
  • エラー
  • フォーカス
  • 集中する
  • フォーカスアウト
  • フォームチェンジ
  • フォーム入力
  • ハッシュチェンジ
  • 入力
  • 無効
  • キーダウン
  • キープレス
  • キーアップ
  • 負荷
  • loadeddata
  • 読み込まれた
  • ロードスタート
  • メッセージ
  • マウスダウン
  • mouseenter
  • ネズミ
  • マウスムーブ
  • マウスアウト
  • マウスオーバー
  • マウスアップ
  • マウスホイール
  • オフライン
  • オンライン
  • ページハイド
  • ページショー
  • ペースト
  • 一時停止
  • 演奏する
  • 遊ぶ
  • ポップステート
  • 進捗
  • レート変更
  • readystatechange
  • やり直す
  • リセットする
  • リサイズ
  • scroll
  • 求めた
  • 探している
  • 選択する
  • 公演
  • 失速
  • ストレージ
  • 参加する
  • サスペンド
  • timeupdate
  • undo
  • 降ろす
  • 体積変化
  • 待っている

今、anyイベントがページ上のany要素で最初に発生したときに呼び出されるグローバルイベントハンドラーを定義することは可能ですか? (この場合、要素で発生したイベントは子孫要素からバブルアップしたためカウントしません-だから「元々発生する」と書きました。)

それが不可能な場合、少なくともanyイベントがDOMツリーのルート(documentオブジェクトまたはwindowオブジェクト-両方とも機能するはずです)? (プログラムでバブリングを停止できることは知っていますが、他の要素に他のハンドラが定義されていないページでこのイベントハンドラを使用します。)この議論のためのケース。)

私はこれを行うことができることを知っています(jQueryを使用して):

$(document).bind('abort afterprint beforeprint beforeunload etc.', function() {
    // handle event
});

しかし、それは私にとってかなり望ましくない解決策でしょう。

ところで、クロスブラウザソリューションは必要ありません。 1つのブラウザでのみ動作する場合は、問題ありません。

また、 Firebugはイベントをログに記録できます ですが、単にコンソールにログを記録するのではなく、プログラムで(JavaScriptを介して)イベントをキャッチできるようにしたいと思います。

48
Šime Vidas
/*

function getAllEventTypes(){

  if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;

  var types = {};
  $('.standard-table:eq(0) tr').find('td:eq(1)').map(function(){
    var type = $.trim(this.innerText) || 'OtherEvent';
    types[type] = types[type] || [];     
    var event = $.trim(this.previousElementSibling.innerText);
    if(event) types[type].Push(event);
  });
  for(var t in types) types[t] = types[t].join(' ');
  return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
}

*/

var DOMEvents = {
UIEvent: "abort DOMActivate error load resize scroll select unload",
ProgressEvent: "abort error load loadend loadstart progress progress timeout",
Event: "abort afterprint beforeprint cached canplay canplaythrough change chargingchange chargingtimechange checking close dischargingtimechange DOMContentLoaded downloading durationchange emptied ended ended error error error error fullscreenchange fullscreenerror input invalid languagechange levelchange loadeddata loadedmetadata noupdate obsolete offline online open open orientationchange pause pointerlockchange pointerlockerror play playing ratechange readystatechange reset seeked seeking stalled submit success suspend timeupdate updateready visibilitychange volumechange waiting",
AnimationEvent: "animationend animationiteration animationstart",
AudioProcessingEvent: "audioprocess",
BeforeUnloadEvent: "beforeunload",
TimeEvent: "beginEvent endEvent repeatEvent",
OtherEvent: "blocked complete upgradeneeded versionchange",
FocusEvent: "blur DOMFocusIn  Unimplemented DOMFocusOut  Unimplemented focus focusin focusout",
MouseEvent: "click contextmenu dblclick mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup show",
SensorEvent: "compassneedscalibration Unimplemented userproximity",
OfflineAudioCompletionEvent: "complete",
CompositionEvent: "compositionend compositionstart compositionupdate",
ClipboardEvent: "copy cut paste",
DeviceLightEvent: "devicelight",
DeviceMotionEvent: "devicemotion",
DeviceOrientationEvent: "deviceorientation",
DeviceProximityEvent: "deviceproximity",
MutationNameEvent: "DOMAttributeNameChanged DOMElementNameChanged",
MutationEvent: "DOMAttrModified DOMCharacterDataModified DOMNodeInserted DOMNodeInsertedIntoDocument DOMNodeRemoved DOMNodeRemovedFromDocument DOMSubtreeModified",
DragEvent: "drag dragend dragenter dragleave dragover dragstart drop",
GamepadEvent: "gamepadconnected gamepaddisconnected",
HashChangeEvent: "hashchange",
KeyboardEvent: "keydown keypress keyup",
MessageEvent: "message message message message",
PageTransitionEvent: "pagehide pageshow",
PopStateEvent: "popstate",
StorageEvent: "storage",
SVGEvent: "SVGAbort SVGError SVGLoad SVGResize SVGScroll SVGUnload",
SVGZoomEvent: "SVGZoom",
TouchEvent: "touchcancel touchend touchenter touchleave touchmove touchstart",
TransitionEvent: "transitionend",
WheelEvent: "wheel"
}

var RecentlyLoggedDOMEventTypes = {};

for(DOMEvent in DOMEvents){

  var DOMEventTypes = DOMEvents[DOMEvent].split(' ');

  DOMEventTypes.filter(function(DOMEventType){
    var DOMEventCategory = DOMEvent + ' '+DOMEventType;  
    document.addEventListener(DOMEventType, function(e){
      if(RecentlyLoggedDOMEventTypes[DOMEventCategory]) return;
      RecentlyLoggedDOMEventTypes[DOMEventCategory] = true;
      setTimeout(function(){ RecentlyLoggedDOMEventTypes[DOMEventCategory] = false }, 5000);
      var isActive = e.target==document.activeElement;
      if(isActive) {
        console.info(DOMEventCategory, 
          ' target=', e.target, 
          ' active=', document.activeElement, 
          ' isActive=', true );
      } else {
        console.log(DOMEventCategory, 
          ' target=', e.target,
          ' active=', document.activeElement, 
          ' isActive=', false );
      }

    }, true);
  });

}
21
Vlad Mysla

Dom要素のすべてのプロパティを反復処理し、/ on(。*)/パターンに一致するものを選択できます(たとえば、onclickまたはonmousemove)。

var events = [];
for (var property in element) {
    var match = property.match(/^on(.*)/)
    if (match) { 
        events.Push(match[1]);
    }
}
console.log(events.join(' '))
9
YankovskyAndrey

Firefoxでこれを行う方法があることを非常に疑います。 Firebugのソースコード (特にattachAllListenersメソッド)を見ると、イベント名のリストを反復処理することが明らかに道であることがわかりますが、これはバブルの問題を解決しません。

5

それを行うための「簡単な方法」はないようです。

私の考え:どのイベントがすべてであるかはわかっているので、すべてのDOM要素のすべてのイベントを処理できます。

var events =
[   
    "onabort",
    "onafterprint",
    "onbeforeprint",
    "onbeforeunload",
    ...

];

var root = document.body;
var elms = root.childNodes;

for(var i = 0; i < elms.length; i++)
{
    for(var j = 0; j < events.length; j++)
    {
        elms[i][events[j]] = globalHandler;
    }
}

function globalHandler()
{
    alert("Global handler called");
}

これは「直感的なアイデア」ですが、あまり効率的ではないようです。ただし、動作するはずです。

幸運を。

2
josec89

パーティーに少し遅れましたが、私はここで他の人に役立つかもしれない何かを作りました。

https://codepen.io/phreaknation/pen/QmJjEa

これは、その要素に認識されている要素からすべてのイベントをキャプチャするES6クラスです。このデモでは、ページ内の要素の時間を変更したり、MDNページへのクリック可能なリンクでイベントを読み出したり、要素と対話したり、タイムスタンプでイベントがトリガーされる方法を確認したりできます。

これが役立つことを願っています

クラスコード

class EventSystem {
  constructor(element) {
    this._ = {
      element: null
    }

    return this;
  }

  getAllEventTypes({blacklist = [], whitelist = []} = {}) {
    const events = [];
    for (let property in this._.element) {
      const match = property.match(/^on(.*)/);
      if (match) {
        if ((whitelist.length > 0 ? whitelist.indexOf(match) !== -1 : true) &&
            (blacklist.length > 0 ? blacklist.indexOf(match) === -1 : true)) {
          events.Push(match[1]);
        }          
      }
    }
    return events;
  }

  getElementType() {
    return this._.element.tagName.toLowerCase();
  }

  setElement(element) {
    this._.element = element;
    return this;
  }

  applyEvents(events, callback) {
    events.forEach((event) => {
      this._.element.addEventListener(event, (ev) => {
        if (typeof callback === 'function') {
          callback(event, ev);
        }
      })
    })
  }
}
0
Phreak Nation

MDN Webサイトの最新バージョンの場合:

(function getAllEventTypes(){
  if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;

  var types = {};
  $('.standard-table').map(function(){
    if($(this).find('caption').length > 0){
        var type = $(this).find('caption')[0].innerHTML || 'OtherEvent';
    types[type] = types[type] || [];     
    $(this).find('tbody tr td code a').each(function(el){
        if(this.innerText) types[type].Push(this.innerText);
    });
    }
  });
  for(var t in types) types[t] = types[t].join(' ');
  return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
})();
0
Martino Lessio