3

JQuery の .show および .hide メソッドをオーバーライドして、次のコードで呼び出される前後にトリガー イベントを起動しようとしています。

$(document).ready(function () {
    $('#dataBox').bind('afterShow', function () {
        alert('afterShow');
    });
    $('#dataBox').bind('afterHide', function () {
        alert('afterHide');
    });
    $('#dataBox').bind('beforeShow', function () {
        alert('beforeShow');
    });
    $('#dataBox').bind('beforeHide', function () {
        alert('beforeHide');
    });
    $('#toggleButton').click(function(){
        if($('#dataBox').is(':visible')) {
            $('#dataBox').hide ();
        } else {
            $('#dataBox').show();
        }
    });
});

jQuery(function ($) {
    var _oldShow = $.fn.show;
    //Override jquery's 'show()' method to include two triggered events before and after
    $.fn.show = function (speed, oldCallback) {
        return $(this).each(function () {
            var obj = $(this),
                newCallback = function () {
                    if ($.isFunction(oldCallback)) {
                        oldCallback.apply(obj);
                }
                obj.trigger('afterShow');
            };
        obj.trigger('beforeShow');
            _oldShow.apply(obj, [speed, newCallback]);
        });
    }
});

jQuery(function ($) {
    var _oldHide = $.fn.hide;
    //Override jquery's 'hide()' method to include two triggered events before and after
    $.fn.hide = function (speed, oldCallback) {
        return $(this).each(function () {
            var obj = $(this),
                newCallback = function () {
                    if ($.isFunction(oldCallback)) {
                        oldCallback.apply(obj);
                }
                obj.trigger('afterHide');
            };
        obj.trigger('beforeHide');
            _oldHide.apply(obj, [speed, newCallback]);
        });
    }
});

次のマークアップがあります。

<input type='text' id='dataBox'/>
<input type='button' value='toggle' id='toggleButton' />

トグル ボタンをクリックすると、'beforeHide' および 'beforeShow' イベントがトリガーされますが、'afterShow' および 'afterHide' はトリガーされません。私が間違っていることについて誰かが私に手がかりを与えることができますか?

4

3 に答える 3

7

デモフィドルをチェックしてください。それがうまくいくことを願っています

$.show / $.hide - オーバーライド機能:

(function($){
$.override ={'show': $.fn.show, 'hide': $.fn.hide};

$.each($.override,function(M,F){

        var m=M.replace( /^\w/, function(r){ return r.toUpperCase(); });

        $.fn[M] = function(speed, easing, callback) {

            var args=[speed||0,easing||'',callback||function(){}];

            if( $.isFunction(speed)){
                args[2]=speed;
                args[0]=0;
            }                   
            else if( $.isFunction(easing)){
                args[2]=easing;
                args[1]='';
            }                   

            if(!this.selector){
                F.apply(this, arguments);
                return this;
            }

            return this.each(function () {
                var obj = $(this),
                    oldCallback = args[args.length-1],
                    newCallback = function () {
                        if ($.isFunction(oldCallback)){
                            oldCallback.apply(obj);
                        }
                        obj.trigger('after'+m);
                };

                obj.trigger('before'+m);
                args[args.length-1]=newCallback;

                //alert(args);
                F.apply(obj,args);

            });
        }
});
})(jQuery);

利用方法

jQuery(function($){
var $dataBox=$('#dataBox').bind('beforeHide afterHide beforeShow afterShow', function(e) {
    alert(e.type);
});

$('#toggleButton').bind('click',function(){
    $dataBox[$dataBox.is(':visible')?'hide':'show'](100,'swing',function(){ alert('end of animation');});
    return false;
});
});
于 2012-05-29T15:44:46.687 に答える
3

afterShowおよびafterHideイベントがトリガーされない理由

newCallbackjQueryは、表示/非表示がアニメーション化されている場合にのみ、(コード内の)コールバック関数を呼び出します。.show()/にパラメータが渡されない場合.hide()(またはが渡される場合speedundefined、jQueryは要素を直接表示/非表示にし、コールバック関数は実行されません。

なぜオーバーライドするのが最善のアイデアではないの.show().hide()

  • jQueryは.show()/.hide()を内部的に(たとえばの一部として.fadeTo())呼び出し、再帰的に(アニメーションの表示/非表示を実行する場合)呼び出すため、カスタムイベントは予期しないときにトリガーされます。

  • 私見では、「ストック」jQueryとカスタマイズを(プラグインとして)別々に、メソッド名/名前空間を別々に保つのが最善です。

    • 開発者がhttp://api.jquery.comでストックメソッドを検索すると、ドキュメントにメソッドの動作が完全に記述されていることがわかります。
    • 開発者が他の場所のコードで作業している場合、ストックメソッドを呼び出さず、会社のコードベースに固有の動作を期待します。

.eventedShow()/.eventedHide()

.eventedShow()これにより、and ( /.eventedHide()と同じ引数を取ります)が追加され、必要な処理が実行されます。.show().hide()

(function( $ ) {

$.each( [ 'Show', 'Hide' ], function( i, method ) {
    $.fn[ 'evented' + method ] = function( speed ) {
        var originalMethod = method.toLowerCase(),
            hasCallback = false,
            args;

        // animate
        if ( speed || speed === 0 ) {
            args = $.makeArray( arguments );
            $.each( args, function( i, arg ) {
                if ( $.isFunction( arg ) ) {
                    args[ i ] = function() {
                        arg.apply( this, arguments );
                        $( this ).trigger( 'after' + method );
                    };
                    hasCallback = true;
                    return false;
                }
            } );
            if ( !hasCallback ) {
                args.push( function() {
                    $( this ).trigger( 'after' + method );
                } );
            }

            this.each( function() {
                var el = $( this );
                el.queue( function() {
                    $( this )
                        .trigger( 'before' + method )
                        .dequeue();
                } );
                $.fn[ originalMethod ].apply( el, args );
            } );

        // straight show/hide
        } else {
            this.trigger( 'before' + method );
            $.fn[ originalMethod ].apply( this, arguments );
            this.trigger( 'after' + method );
        }

        return this;
    };
} );

})( jQuery );

ここでコードを試すことができます:http://jsfiddle.net/jefferyto/bv8D2/

show既存のコードで/hideeventedShow/に変更する必要がありeventedHideますが、これはグローバルな検索と置換を使用して行うことができます。

于 2012-05-31T11:22:05.907 に答える
3

コードにいくつかのブレークポイントを設定したところ、newCallback関数が呼び出されていないことがわかりました。その関数を呼び出すときに速度パラメーターを使用していないためだと思います。jQuery の元の関数のドキュメント$.showからわかるよう$.showno、 、onetwoまたは `3 つのパラメーターで呼び出すことができます。

.show(期間[、コールバック])

durationアニメーションの実行時間を決定する文字列または数値。

コールバックアニメーションが完了したら呼び出す関数。

追加されたバージョン: 1.4.3

.show( [デュレーション] [,イージング] [, コールバック] )

durationアニメーションの実行時間を決定する文字列または数値。

easing遷移に使用するイージング関数を示す文字列。

コールバックアニメーションが完了したら呼び出す関数。

したがって、一連のさまざまなパラメーターを渡す場合と渡さない場合があります。したがって、問題はこの行にあると思います

 _oldHide.apply(obj, [speed, newCallback]);

この特定のケースでの場所speedは未定義です。

$.fn.showそして、次のような関数を呼び出すことができます

$(..).show(undefined,callBack)
//or
$(..).show(undefined,undefined, callBack)

他の引数が指定されていない場合、コールバックは常に最初の引数である必要があり、その場合、jQuery は400msアニメーションにデフォルトの速度/期間を使用します。そして、fadeIn/fadeOut タイプのエフェクトが表示されます。このコールバックで表示/非表示のように動作させるには

_oldShow/_oldHide次のように呼び出す必要があります

_oldShow.apply(obj, [0,newCallback]);

//or

_oldHide.apply(obj, [0,newCallback]);

簡単な検索で、インターネットでコードを見つけました。これは正常に動作し、$.showandに渡すことができるすべての引数を特別に処理しているようです$.hide。次のフィドルをチェックして、それを確認してください

働くフィドル

于 2012-05-22T13:17:21.887 に答える