3

Is it possible to avoid twice firing events by browsers, but not based on timing (in case your resize event execution lasts long that solution is bad)

DarkAjax
  • 15,955
  • 11
  • 53
  • 65
OPOPO
  • 473
  • 2
  • 5
  • 15
  • 1
    Could you be more specific? Are you thinking of [.one()](http://api.jquery.com/one/)? – Belladonna Mar 01 '13 at 22:09
  • Chrome for example firest some events (resize) twice. Timeout based solution works, but when my resize funtion execution lasts for 10sec's and then it begins to execute again its terrible... So, I cant set short timeout, and when I set long timeout it would block real resize event when user would indeed resize window after 5s for example. I need to force one event function firing per event. In Mozilla its ok, in Chrome it's twice. – OPOPO Mar 01 '13 at 22:12
  • 2
    Can't really be done! You could have hacked it by detecting mouse button down etc. but those events don't register on the browser chrome, only the window, so no banana. Timers are the only viable option. – adeneo Mar 01 '13 at 22:13
  • Right, you can't control the events, but you can control how YOU handle them. Timers are the answer. – Diodeus - James MacFarlane Mar 01 '13 at 22:14
  • So at least - why is that? Why Chrome fires it twice? Times are the answer only when you control how long events execution lasts. When you dont know it, becouse you got for example some complicated drawing - it gets tricky. And its terrible when all the drawing is done twice - and you need to redraw it every resize, but once only. – OPOPO Mar 01 '13 at 22:15
  • The resize event fires continuosly ? – adeneo Mar 01 '13 at 22:15
  • 1
    It really would be nice to have an event like `onafterresize`, but this is not implemented by any browser (yet). Unfortenately our only change for the moment is to use a delay to achieve this. – Teemu Mar 01 '13 at 22:16
  • 1
    @Teemu You could just write it yourself. [http://jsfiddle.net/NSmsE/](http://jsfiddle.net/NSmsE/). All credit where credit is due to [BGerrissen](http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing) – Ohgodwhy Mar 01 '13 at 22:19
  • @OPOPO Timers are pretty much the best option. I mean, you could detect for Chrome and have a toggle lock, so it runs every other time, but this seems like a bad idea. – Belladonna Mar 01 '13 at 22:19
  • @Ohgodwhy I can't see anything in the console when running your fiddle : (. Just a moment, I'll try it locally... – Teemu Mar 01 '13 at 22:23
  • I will try to add some timeout 'blocker' on the end of resize function. Will let you know. – OPOPO Mar 01 '13 at 22:29
  • @Ohgodwhy I've just tested your fiddle code locally, it really seems to work. This is a nice catch, and upvoted Zevan's answer... thought it still uses delays I've mentioned in my previous comment ; ). – Teemu Mar 01 '13 at 22:34
  • A fix to previous, upvoted BGerrissen ofcourse... – Teemu Mar 01 '13 at 22:46
  • You can modify James Padolsey's approach to fit your needs: http://james.padolsey.com/javascript/special-scroll-events-for-jquery/ – yckart Mar 02 '13 at 00:45

2 Answers2

0
window.blockResize = false;
$(window).resize(function() {

    if (window.blockResize) return;

        //do stuff


    window.blockResize = true;
    setTimeout(function(){window.blockResize = false},200);


});

Ok, it's still based on timers, but It works in my case now.

OPOPO
  • 473
  • 2
  • 5
  • 15
0

You can use setTimeout() and clearTimeout() in conjunction with jQuery.data:

$(window).resize(function() {
    clearTimeout($.data(this, 'resizeTimer'));
    $.data(this, 'resizeTimer', setTimeout(function() {
        //do something
        alert("Haven't resized in 200ms!");
    }, 200));
});

Update

I wrote an extension to enhance jQuery's default on (& bind)-event-handler. It attaches an event handler function for one or more events to the selected elements if the event was not triggered for a given interval. This is useful if you want to fire a callback only after a delay, like the resize event, or else. https://github.com/yckart/jquery.unevent.js

;(function ($) {
    var methods = { on: $.fn.on, bind: $.fn.bind };
    $.each(methods, function(k){
        $.fn[k] = function () {
            var args = [].slice.call(arguments),
                delay = args.pop(),
                fn = args.pop(),
                timer;

            args.push(function () {
                var self = this,
                    arg = arguments;
                clearTimeout(timer);
                timer = setTimeout(function(){
                    fn.apply(self, [].slice.call(arg));
                }, delay);
            });

            return methods[k].apply(this, isNaN(delay) ? arguments : args);
        };
    });
}(jQuery));

Use it like any other on or bind-event handler, except that you can pass an extra parameter as a last:

$(window).on('resize', function(e) {
    console.log(e.type + '-event was 200ms not triggered');
}, 200);

http://jsfiddle.net/ARTsinn/EqqHx/

yckart
  • 32,460
  • 9
  • 122
  • 129