Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient way of using window.resize (or other method) to fire jquery functions, and making gridster.js repsonsive

I have been tinkering with some thoughts on a round-about way of making gridster.js responsive. I found a code snippit in the github issues in gridster and realized if I ran it under certain window sizing and destroyed and re-ran gridster I can get the effect of gridster responding responsivley. Let me show you what I mean -

$(window).resize(function(){
            var width = $(window).width();
            var columns = "";

            if(Modernizr.mq('screen and (max-width:640px)')){
                columns = 1;
                gridster.destroy();
                var tooFar = $('.gridster .gs-w').filter(function () {
                  return $(this).data('col') > columns;
                });
                $(tooFar).each(function () {
                  $(this).attr('data-col', '1');    
                });

                var tooBig = $('.gridster li').filter(function () {
                  return $(this).data('sizex') > columns;
                });
                $(tooBig).each(function () {
                  $(this).attr('data-sizex', columns);

                });
                $(".gridster ul").gridster({
                    widget_base_dimensions: [300, 300],
                    widget_margins: [5, 5],  
                    max_cols: 1,
                      resize: {
                          enabled: true
                        },
                        draggable: {
                          handle: '.dragDiv'
                        },
                    serialize_params: function ($w, wgd) {              
                        return {
                            /* add element ID to data*/
                            id: $w.attr('id'),
                            /* defaults */
                            col: wgd.col,
                            row: wgd.row,
                            size_x: wgd.size_x,
                            size_y: wgd.size_y,
                           /* htmlContent: $($w).html() */
                        }
                    }
        }).data('gridster');
            }

        });

So when gridster should break into 1 column (it has a base of 4), it destroys and re runs with 1 column. This works surprisingly well, the issue is this is not a pretty way of achieving this. I am also not showing all the break points ( it breaks into, 3 -2 -1 columns based on window size). It runs very poorly because its firing on every window resize, and I'm wondering if there is a cleaner way to do this where the functions would only fire once when they hit the window size.

Also - this is only to size gridster down, so if you size out it will not expand, I have not tried building those functions yet.

Any pointers or suggestions in using something that maybe isn't listening to every single instance of a window re-size would be super helpful.

Thanks!!

like image 299
ajmajmajma Avatar asked Jun 27 '14 21:06

ajmajmajma


1 Answers

I gather from your question that gridster is being re-run continuously as the user resizes the window; that is, if you resize the window by dragging the window slowly, pixel by pixel, there is a gridster re-run for every pixel change.

Try throttling the resize event with setTimeout. When resize fires, you set a timer to do the re-run of gridster -- say the timer duration is 200ms. If within that 200ms, another resize fires, you reset the timer. With this approach, the re-run only occurs when the user is done resizing (at least for the moment). You can tweak the timer duration for a better experience.

Try:

var resizeTimeout;
$(window).resize(function(){
  if(!!resizeTimeout){ clearTimeout(resizeTimeout); }
  resizeTimeout = setTimeout(function(){
    //do gridster re-run here
  },200);
});

example fiddle (look at the console as you slowly resize the window)


EDIT: For anyone interested in this pattern, I've extracted the throttling logic from the above code and put it into a jQuery plugin:

(function($){
    $.fn.onDelayed = function(eventName,delayInMs,callback){
        var _timeout;
        this.on(eventName,function(e){
          if(!!_timeout){ 
              clearTimeout(_timeout); 
              console.log('timer being re-set: ' + eventName);
          } else {
              console.log('timer being set for the first time: ' + eventName);
          }
          _timeout = setTimeout(function(){
              callback(e);
          },delayInMs);
        });
    };
})(jQuery);

which would be used like

$(function(){
    $(document).onDelayed('click',500,function(){
        alert('clicking is done');
    });
    $(window).onDelayed('resize',1000,function(){
        alert('resize is finished');
    });
});

Fiddle with two example uses of onDelayed

like image 65
Jonathan Wilson Avatar answered Oct 13 '22 16:10

Jonathan Wilson