4

特定のDOMイベントにイベントハンドラーがバインドされているかどうかを検出することは可能ですか(ブラウザーのデフォルトのイベント処理を含む) -FirefoxのGreasemonkeyコードEcmaScript 5.1 strictモード内で?

これまでのところ、テキストが選択されたときにクリックイベントの処理をキャンセルすることができましたが、クリックイベントがデフォルトのアクションをトリガーする次のすべての状況でイベント処理をキャンセルしたいと思います。

  • ページ上のテキストの選択
  • コンテキストメニューが表示されます(つまり、右クリック)
  • リンクをたどる(左クリック<a>
  • フォーム要素が操作されます(テキストボックスにフォーカスが移り、カーソルが点滅し始め、ラジオボタンが選択されます...)
  • イベントを処理するその他のJavaScriptコード(ポップアップヘルプダイアログが表示されるなど)

このためのキャッチオールメカニズムはありますか、それともコード内のすべての状況を明示的に綴る必要がありますか?

次のコードは、選択が行われたことを検出する方法です。

var toggleHighlight = function(){
    var oldTargt;
    return function(e){
        targt = e.target;
        sel = window.getSelection();
        if (!sel.isCollapsed && sel.containsNode(targt, true)) {
            return;
        }
        ...
        oldTargt = targt;
}()
document.addEventListener('click', toggleHighlight);

注:
-スクリプトで伝播を停止したくありません。イベントが他のハンドラーに伝播される場合は、スクリプトを停止したいと思います。 -デフォルトのブラウザイベントハンドラーをキャッチしない場合 、 JQueryイベントハンドラーのみの
ソリューションには興味がありません。-この機能が実際に存在しない場合は、自分の意見だけでなく、いくつかの記事やブログを引用してください。 -特定の提案を歓迎しますが、私は主に一般的な解決策の存在に興味があります。

更新:受け入れ可能なソリューションは次のとおりです。

  • if私がチェックする必要がある条件の網羅的な(っぽい)リスト
  • FirefoxプラグインからアクセスできるJavaScript以外の方法
  • 有効な要素をクリックすると新しいURLのリロードがトリガーされることをFirefoxが<a>認識する方法と、このロジックにjavascript/pluginsからアクセスできない方法の説明
4

1 に答える 1

3

この質問は、 「Javascript /jQueryにデフォルトがない場合にのみアクションを実行する方法」とほぼ同じです。、ただし、Greasemonkeyスクリプターとして、もう1つの(複雑な)オプションを使用できます。

あなたの質問から、ノードを持たないノードにデフォルトのアクションを設定し、特定のイベントに対して他のイベントハンドラーが起動した場合は、そのデフォルトのアクションを中止したいようです。このための「キャッチオールメカニズム」はありません。また、試行するほとんどすべての手法で、ページが破壊される可能性があります。理由は次のとおりです。

  1. javascriptもGreasemonkeyAPIも、特定のノードのイベントを一覧表示するメカニズムを提供していません。古い提案がありましたが、それは実行されていません。

    ただし、 FirefoxアドオンはnsIEventListenerServiceを介してイベントを一覧表示できるため、Greasemonkeyとインターフェイスするその部分のヘルパーアドオンを作成できる可能性があります。詳細は(方法で)この質問の範囲を超えています。

  2. 同様に、が設定されていない限り、イベントオブジェクトevent.defaultPreventedからイベントチェーン内の以前のイベントを検出するメカニズムはありません。(通常はそうではありません。)

  3. ノードXのイベントリスナーを一覧表示できたとしても、親ノードのフォールバックリスナーには役立ちません。最新のJSライブラリは、古いノードをクリック可能にすることができます。または、たとえば、すべてのクリックイベントdocument取得するリスナーをオンに設定することもできますが、元のターゲットが特定のノードである場合を除いて、実際には何も実行されません


良い妥協戦略は、他の質問の先導に従い、デフォルトのアクションを持つノードに対しては何もしないことです。
右クリックまたは中央クリックを処理するには、をオンにしますevent.which

したがって、次のスニペットを小切手に追加できます。

return function(e){
    targt   = e.target;
    sel     = window.getSelection();

    if (e.which != 1) {
        return; //-- Abort on anything that is not a left-click.
    }
    if (e.defaultPrevented) {
        return; //-- The one time we know that some other handler fired.
    }
    if (isInteractiveElement (targt) ) {
        // Do nothing for elements that trigger browser actions
        return; 
    }
    ...

どこ:

function isInteractiveElement (node) {
    var intElems = [
        //-- Must be uppercase
        "A", "BUTTON", "INPUT", "TEXTAREA", "VIDEO", "MAP", "OBJECT"
    ];
    if (intElems.indexOf (node.nodeName) >= 0) {
        return true;
    }
    else if (node.nodeName === "BODY") {
        return false;
    }

    return isInteractiveElement (node.parentNode);
}
于 2013-04-29T11:12:42.630 に答える