2017-05-05 11 views
-1

私が記述していることは、より標準的なアプローチではあまりアドバイスされていない可能性があります。そうであれば、有効な答えになります。カスタム.on()および.off()操作をjqueryのカスタムイベントに追加する標準的な方法は何ですか?

独自のカスタムイベントを作成しているとしますが、on()およびoff()の各ステップでは、その要素に対してアクションを実行する必要があります。

私の例のシナリオでは、要素が500 msタイムパス内で1回、2回、または3回クリックされたときに発生する「multiclick」というカスタムjqueryイベントを作成します。

私の最初のアイデアはオフ、上の機能を拡張し、トリガーなどのように私の独自のイベントを追加することです:

(function($) 
{ 
    var oldOn = $.fn.on; 
    var oldOff = $.fn.off; 
    var oldTrigger = $.fn.trigger; 

    // events [, selector ] [, data ], handler 
    // events [, selector ] [, data ] 
    // Note: this does not implement selector or data for multiclick 
    $.fn.on = function(events, handler) 
    { 
     if (events.split(/\s+/).some(function(event) { return event == 'multiclick'; })) 
     { 
      $(this).each(function() 
      { 
       if (!Array.isArray($(this).data('multiclick-state'))) 
       { 
        $(this).data('multiclick-state', []); 
       } 
       var clicks = 0; 
       var clicksTimer = null; 
       var clickHandler = function(e) 
       { 
        clicks++; 
        if (clicks == 1) 
        { 
         clicksTimer = setTimeout(function() 
         { 
          handler(e, clicks); 
          clicks = 0; 
         }, 500); 
        } 
        else if (clicks == 3) 
        { 
         clearTimeout(clicksTimer); 
         handler(e, clicks); 
         clicks = 0; 
        } 
       }; 
       $(this).data('multiclick-state').push(
       { 
        handler: handler, 
        clickHandler: clickHandler 
       }); 
       $(this).click(clickHandler); 
      }); 
      arguments[0] = arguments[0].replace('multiclick', ''); 
     } 
     return oldOn.apply(this, arguments); 
    }; 

    // events [, selector ] [, handler ] 
    // events [, selector ] 
    // events 
    // Note: this does not implement selector 
    $.fn.off = function(events, handler) 
    { 
     if (events.split(/\s+/).some(function(event) { return event == 'multiclick'; })) 
     { 
      $(this).each(function() 
      { 
       if (!Array.isArray($(this).data('multiclick-state'))) 
       { 
        $(this).data('multiclick-state', []); 
       } 
       $(this).data('multiclick-state', $(this).data('multiclick-state').filter(function(state) 
       { 
        if (handler == undefined || state.handler === handler) 
        { 
         $(this).off('click', state.clickHandler); 
         return false; 
        } 
        return true; 
       }.bind(this))); 
      }); 
      arguments[0] = arguments[0].replace('multiclick', ''); 
     } 
     return oldOff.apply(this, arguments); 
    }; 

    // eventType [, extraParameters ] 
    // event, [, extraParameters ] 
    // Note: I wrote this in case trigger is changed to handle multiple events. Currently it does not. Also I don't support the second overloaded signature 
    $.fn.trigger = function(events) 
    { 
     if (typeof events == 'string' && events.split(/\s+/).some(function(event) { return event == 'multiclick'; })) 
     { 
      $(this).each(function() 
      { 
       if (!Array.isArray($(this).data('multiclick-state'))) 
       { 
        $(this).data('multiclick-state', []); 
       } 
       // This doesn't support disabling bubbling or stopPropogation, would have to think about it. Very ad-hoc. 
       $(this).data('multiclick-state').forEach(function(data) 
       { 
        data.clickHandler(); 
       }); 
      }); 
      arguments[0] = arguments[0].replace('multiclick', ''); 
     } 
     return oldTrigger.apply(this, arguments); 
    }; 

    $.fn.multiclick = function(callback) 
    { 
     if (arguments.length == 1) 
     { 
      return $(this).on('multiclick', callback); 
     } 
     else 
     { 
      return $(this).trigger('multiclick'); 
     } 
     return this; 
    }; 
}(jQuery)); 

私は本当にこれが最も完全なソリューションである保証が、それはありませんよ基本的なアプローチを示しています。そして、それは通常のjqueryのイベントのように使用することになります。

function multiclick(e, clicks) 
{ 
    console.log(clicks); 
} 

// $(document).on('multiclick', multiclick); 
$(document).multiclick(multiclick); 
//$(document).off('multiclick'); 
//$(document).off('multiclick', multiclick); 

jsfiddle例:https://jsfiddle.net/rhsswfho/1/

これは、すべてのちょうどヘルパー関数とかなり直接的あるいはjqueryのに組み込まれるべきもののために多くのコードのように思えますしかし、私は誰も見つけません。言い換えれば、やや壊れやすく、すべてのオン、オフ、トリガコールにパフォーマンス上のペナルティが加わります。

これを行うための標準的なアプローチ、またはそのような問題を処理するためのより標準的なアプローチは何ですか?

+1

あなたが解決しようとしているより高いレベルの問題を本当に明らかにしません。これはちょうど[XY問題]のように聞こえます(https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – charlietfl

+0

@charlietflローカライズされたソリューションを作成しようとしていました。本質的に、はるかに簡単であることが判明した文書にバインドする代わりに:http://jsfiddle.net/f35u0fw2 – Sirisian

+0

まだ適切な問題の説明がありません。あなたは、どこかに散らばっている文章やコードがたくさんあり、期待どおりに動いているかどうかは具体的に言及していません。 [ask] – charlietfl

答えて

0

のjQueryを経由してそのイベントをトリガします。 (つまり、イベントタイプごとに実行されるコードがないという意味です)。むしろ、このようなので、文書又は身体リスナーを作成することによって簡単に達成することができる要素の局所的なソリューションを作成するよりも:

var clicks = 0; 
var lastTarget = null; 
var clicksTimer = null; 
$('body').click(function(e) 
{ 
    if (e.target !== lastTarget) 
    { 
    clearTimeout(clicksTimer); 
    lastTarget = e.target; 
    clicks = 0; 
    } 
    clicks++; 
    if (clicks == 1) 
    { 
    clicksTimer = setTimeout(function() 
    { 
     $(e.target).trigger('multiclick', clicks); 
     clicks = 0; 
     lastTarget = null; 
    }, 500); 
    } 
    else if (clicks == 3) 
    { 
    $(e.target).trigger('multiclick', clicks); 
    clearTimeout(clicksTimer); 
    clicks = 0; 
    lastTarget = null; 
    } 
}); 

、通常のように用いる:jsfiddleに

$('div').on('multiclick', function(e, clicks) 
{ 
    console.log(clicks); 
}); 

$('span').on('multiclick', function(e, clicks) 
{ 
    console.log(clicks); 
}); 

例:http://jsfiddle.net/f35u0fw2/

この特定のケースでは、ユーザがどこでもクリックして、リスニングしている要素に対して1,2回または3回クリックした後に 'multiclick'イベントが発生することが予想されます。

0

あなたが言ったように、それはかなり簡単です。任意の種類のイベントをリッスンするために.on()を使用できます。だからあなたのような何かを行うことができます:

$('body').on('takeMeToDinner', function() { 
    alert('who will pay the bills?'); 
}); 

をし、それが唯一のDOMイベントを実施していますので、オン/オフイベントカスタム操作を追加することを中心に設計されていません

$('body').trigger('takeMeToDinner'); 
+0

これは私が要求したようなカスタムのオン/オフ操作を実行しません。 – Sirisian

+0

@シリシアンなぜカスタムオン/オフイベントが必要だと思いますか?単純なイベントハンドラを使用して、クロージャなどの状態を追跡してください。 – Pointy

+1

@シリシアンでは、任意の要素に対して任意のアクションを実行できます。必要な要素に対してイベントをトリガーし、必要に応じて$(this)を介して特定の要素にアクセスできます。したがって、明らかに、上のコードは、特定のユースケースに対して記述しなければならない関数全体ではありませんが、カスタムイベントを処理する方法については説明しています。 –

関連する問題