JavaScript/JQuery: $(window).resize how to fire AFTER the resize is completed?

前端 未结 12 686
终归单人心
终归单人心 2020-11-22 08:54

I\'m using JQuery as such:

$(window).resize(function() { ... });

However, it appears that if the person manually resizes their browser wind

相关标签:
12条回答
  • 2020-11-22 09:40

    Actually, as I know, you can't do some actions exactly when resize is off, simply because you don't know future user's actions. But you can assume the time passed between two resize events, so if you wait a little more than this time and no resize is made, you can call your function.
    Idea is that we use setTimeout and it's id in order to save or delete it. For example we know that time between two resize events is 500ms, therefore we will wait 750ms.

    var a;
    $(window).resize(function(){
      clearTimeout(a);
      a = setTimeout(function(){
        // call your function
      },750);
    });

    0 讨论(0)
  • 2020-11-22 09:43

    Here's a modification of CMS's solution that can be called in multiple places in your code:

    var waitForFinalEvent = (function () {
      var timers = {};
      return function (callback, ms, uniqueId) {
        if (!uniqueId) {
          uniqueId = "Don't call this twice without a uniqueId";
        }
        if (timers[uniqueId]) {
          clearTimeout (timers[uniqueId]);
        }
        timers[uniqueId] = setTimeout(callback, ms);
      };
    })();
    

    Usage:

    $(window).resize(function () {
        waitForFinalEvent(function(){
          alert('Resize...');
          //...
        }, 500, "some unique string");
    });
    

    CMS's solution is fine if you only call it once, but if you call it multiple times, e.g. if different parts of your code set up separate callbacks to window resizing, then it will fail b/c they share the timer variable.

    With this modification, you supply a unique id for each callback, and those unique IDs are used to keep all the timeout events separate.

    0 讨论(0)
  • 2020-11-22 09:45

    Declare globally delayed listener:

    var resize_timeout;
    
    $(window).on('resize orientationchange', function(){
        clearTimeout(resize_timeout);
    
        resize_timeout = setTimeout(function(){
            $(window).trigger('resized');
        }, 250);
    });
    

    And below use listeners to resized event as you want:

    $(window).on('resized', function(){
        console.log('resized');
    });
    
    0 讨论(0)
  • 2020-11-22 09:45

    Simple jQuery plugin for delayed window resize event.

    SYNTAX:

    Add new function to resize event

    jQuery(window).resizeDelayed( func, delay, id ); // delay and id are optional
    

    Remove the function(by declaring its ID) added earlier

    jQuery(window).resizeDelayed( false, id );
    

    Remove all functions

    jQuery(window).resizeDelayed( false );
    

    USAGE:

    // ADD SOME FUNCTIONS TO RESIZE EVENT
    jQuery(window).resizeDelayed( function(){ console.log( 'first event - should run after 0.4 seconds'); }, 400,  'id-first-event' );
    jQuery(window).resizeDelayed( function(){ console.log('second event - should run after 1.5 seconds'); }, 1500, 'id-second-event' );
    jQuery(window).resizeDelayed( function(){ console.log( 'third event - should run after 3.0 seconds'); }, 3000, 'id-third-event' );
    
    // LETS DELETE THE SECOND ONE
    jQuery(window).resizeDelayed( false, 'id-second-event' );
    
    // LETS ADD ONE WITH AUTOGENERATED ID(THIS COULDNT BE DELETED LATER) AND DEFAULT TIMEOUT (500ms)
    jQuery(window).resizeDelayed( function(){ console.log('newest event - should run after 0.5 second'); } );
    
    // LETS CALL RESIZE EVENT MANUALLY MULTIPLE TIMES (OR YOU CAN RESIZE YOUR BROWSER WINDOW) TO SEE WHAT WILL HAPPEN
    jQuery(window).resize().resize().resize().resize().resize().resize().resize();
    

    USAGE OUTPUT:

    first event - should run after 0.4 seconds
    newest event - should run after 0.5 second
    third event - should run after 3.0 seconds
    

    PLUGIN:

    jQuery.fn.resizeDelayed = (function(){
    
        // >>> THIS PART RUNS ONLY ONCE - RIGHT NOW
    
        var rd_funcs = [], rd_counter = 1, foreachResizeFunction = function( func ){ for( var index in rd_funcs ) { func(index); } };
    
        // REGISTER JQUERY RESIZE EVENT HANDLER
        jQuery(window).resize(function() {
    
            // SET/RESET TIMEOUT ON EACH REGISTERED FUNCTION
            foreachResizeFunction(function(index){
    
                // IF THIS FUNCTION IS MANUALLY DISABLED ( by calling jQuery(window).resizeDelayed(false, 'id') ),
                // THEN JUST CONTINUE TO NEXT ONE
                if( rd_funcs[index] === false )
                    return; // CONTINUE;
    
                // IF setTimeout IS ALREADY SET, THAT MEANS THAT WE SHOULD RESET IT BECAUSE ITS CALLED BEFORE DURATION TIME EXPIRES
                if( rd_funcs[index].timeout !== false )
                    clearTimeout( rd_funcs[index].timeout );
    
                // SET NEW TIMEOUT BY RESPECTING DURATION TIME
                rd_funcs[index].timeout = setTimeout( rd_funcs[index].func, rd_funcs[index].delay );
    
            });
    
        });
    
        // <<< THIS PART RUNS ONLY ONCE - RIGHT NOW
    
        // RETURN THE FUNCTION WHICH JQUERY SHOULD USE WHEN jQuery(window).resizeDelayed(...) IS CALLED
        return function( func_or_false, delay_or_id, id ){
    
            // FIRST PARAM SHOULD BE SET!
            if( typeof func_or_false == "undefined" ){
    
                console.log( 'jQuery(window).resizeDelayed(...) REQUIRES AT LEAST 1 PARAMETER!' );
                return this; // RETURN JQUERY OBJECT
    
            }
    
            // SHOULD WE DELETE THE EXISTING FUNCTION(S) INSTEAD OF CREATING A NEW ONE?
            if( func_or_false == false ){
    
                // DELETE ALL REGISTERED FUNCTIONS?
                if( typeof delay_or_id == "undefined" ){
    
                    // CLEAR ALL setTimeout's FIRST
                    foreachResizeFunction(function(index){
    
                        if( typeof rd_funcs[index] != "undefined" && rd_funcs[index].timeout !== false )
                            clearTimeout( rd_funcs[index].timeout );
    
                    });
    
                    rd_funcs = [];
    
                    return this; // RETURN JQUERY OBJECT
    
                }
                // DELETE ONLY THE FUNCTION WITH SPECIFIC ID?
                else if( typeof rd_funcs[delay_or_id] != "undefined" ){
    
                    // CLEAR setTimeout FIRST
                    if( rd_funcs[delay_or_id].timeout !== false )
                        clearTimeout( rd_funcs[delay_or_id].timeout );
    
                    rd_funcs[delay_or_id] = false;
    
                    return this; // RETURN JQUERY OBJECT
    
                }
    
            }
    
            // NOW, FIRST PARAM MUST BE THE FUNCTION
            if( typeof func_or_false != "function" )
                return this; // RETURN JQUERY OBJECT
    
            // SET THE DEFAULT DELAY TIME IF ITS NOT ALREADY SET
            if( typeof delay_or_id == "undefined" || isNaN(delay_or_id) )
                delay_or_id = 500;
    
            // SET THE DEFAULT ID IF ITS NOT ALREADY SET
            if( typeof id == "undefined" )
                id = rd_counter;
    
            // ADD NEW FUNCTION TO RESIZE EVENT
            rd_funcs[id] = {
                func : func_or_false,
                delay: delay_or_id,
                timeout : false
            };
    
            rd_counter++;
    
            return this; // RETURN JQUERY OBJECT
    
        }
    
    })();
    
    0 讨论(0)
  • 2020-11-22 09:47

    I use the following function for delaying repeated actions, it will work for your case:

    var delay = (function(){
      var timer = 0;
      return function(callback, ms){
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
      };
    })();
    

    Usage:

    $(window).resize(function() {
        delay(function(){
          alert('Resize...');
          //...
        }, 500);
    });
    

    The callback function passed to it, will execute only when the last call to delay has been made after the specified amount of time, otherwise a timer will be reset, I find this useful for other purposes like detecting when the user stopped typing, etc...

    0 讨论(0)
  • 2020-11-22 09:48

    I prefer to create an event:

    $(window).bind('resizeEnd', function() {
        //do something, window hasn't changed size in 500ms
    });
    

    Here is how you create it:

     $(window).resize(function() {
            if(this.resizeTO) clearTimeout(this.resizeTO);
            this.resizeTO = setTimeout(function() {
                $(this).trigger('resizeEnd');
            }, 500);
        });
    

    You could have this in a global javascript file somewhere.

    0 讨论(0)
提交回复
热议问题