8

i have a loop function that in first 5 seconds it runs social1() and in second 5 seconds it runs social2() then loop ...

i have 2 hover functions too

i need clear all active timeouts because when i hover on images (.social1 & .social2), i can see that multiple timeouts are running

how to fix this?

function social1() {
    $('.social1').fadeTo(500, 1);
    $('.social2').fadeTo(500, 0.5);
    timeout = setTimeout(function() {
          social2();
    }, 5000);
}
function social2() {
    $('.social1').fadeTo(500, 0.5);
    $('.social2').fadeTo(500, 1);
    timeout = setTimeout(function() {
          social1();
    }, 5000);
} 


$(document).ready(function ()
{
    social1();

    $('.social1').hover(
        function () {
            window.clearTimeout(timeout);
            social1();
        },
        function () {
            timeout = setTimeout(function() {
                  social2();
            }, 5000);
        }
    );
    $('.social2').hover(
        function () {
            window.clearTimeout(timeout);
            social2();
        },
        function () {
            timeout = setTimeout(function() {
                  social1();
            }, 5000);
        }
    );
A. Wolff
  • 74,033
  • 9
  • 94
  • 155
Mohammad Masoudian
  • 3,483
  • 7
  • 27
  • 45

2 Answers2

29

__EDIT__

To manage a collection of timeouts (and intervals), you could use following snippet. This will allow to clear any timeouts or intervals set anywhere in code, although, you have to set this snippet before setting any timeout or interval. Basically, before processing any javascript code or external script which uses timeout/interval.

JS:

;(function () {
    window.timeouts = {},
    window.intervals = {},
    window.osetTimeout = window.setTimeout,
    window.osetInterval = window.setInterval,
    window.oclearTimeout = window.clearTimeout,
    window.oclearInterval = window.clearInterval,
    window.setTimeout = function () {
        var args = _parseArgs('timeouts', arguments),
            timeout = window.osetTimeout.apply(this, args.args);
        window.timeouts[args.ns].push(timeout);
        return timeout;
    },
    window.setInterval = function () {
        var args = _parseArgs('intervals', arguments),
            interval = window.osetInterval.apply(this, args.args);
        window.intervals[args.ns].push(interval);
        return interval;
    },
    window.clearTimeout = function () {
        _removeTimer('timeouts', arguments);
    },
    window.clearInterval = function () {
        _removeTimer('intervals', arguments);
    },
    window.clearAllTimeout = function () {
        _clearAllTimer('timeouts', arguments[0]);
    },
    window.clearAllInterval = function () {
        _clearAllTimer('intervals', arguments[0]);
    };

    function _parseArgs(type, args) {
        var ns = typeof args[0] === "function" ? "no_ns" : args[0];
        if (ns !== "no_ns")[].splice.call(args, 0, 1);
        if (!window[type][ns]) window[type][ns] = [];
        return {
            ns: ns,
            args: args
        };
    }

    function _removeTimer(type, args) {
        var fnToCall = type === "timeouts" ? "oclearTimeout" : "oclearInterval",
            timerId = args[0];
        window[fnToCall].apply(this, args);
        for (var k in window[type]) {
            for (var i = 0, z = window[type][k].length; i < z; i++) {
                if (window[type][k][i] === timerId) {
                    window[type][k].splice(i, 1);
                    if (!window[type][k].length) delete window[type][k];
                    return;                        
                }
            }
        }
    }

    function _clearAllTimer(type, ns) {
        var timersToClear = ns ? window[type][ns] : (function () {
            var timers = [];
            for (var k in window[type]) {
                timers = timers.concat(window[type][k]);
            }
            return timers;
        }());
        for (var i = 0, z = timersToClear.length; i < z; i++) {
            _removeTimer(type, [timersToClear[i]]);
        }
    }
}());

How to use it:

Set timeout(s)/interval(s) as usual:

var test1 = setTimeout(function(){/**/, 1000);
var test2 = setTimeout(function(){/**/, 1000);

Then you could use to clear both:

clearAllTimeout(); // clearAllInterval(); for intervals

This will clear both timeouts (test1 & test2)

You can use some namespaces to clear only specific timers, e.g:

// first (optional) parameter for setTimeout/setInterval is namespace
var test1 = setTimeout('myNamespace', function(){/**/, 1000); // 'myNamespace' is current namespace used for test1 timeout
var test2 = setTimeout(function(){/**/, 1000); // no namespace used for test2 timeout

Again, clearAllTimeout(); will clear both timeouts. To clear only namespaced one, you can use:

clearAllTimeout('myNamespace'); // clearAllInterval('myNamespace'); for namespaced intervals

This will clear only test1 timeout

You could for some reason wish to delete non namespaced timeouts only. You could then use:

clearAllTimeout('no_ns'); // clearAllInterval('no_ns'); for non namespaced intervals only

This will clear only test2 timeout in this example

See jsFiddle DEMO

__END of EDIT__

Old post specific to opening question here:

You could try that:

var timeouts = [];

timeouts.push(setTimeout(function() {
          social2();
    }, 5000));

timeouts.push(setTimeout(function() {
          social1();
    }, 5000));

//etc...

function clearAllTimeouts(){
   for(var i = 0, z = timeouts.length; i < z; i++)
       clearTimeout(timeouts[i]);

   timeouts = [];
}

UPDATED following David Thomas comment

var timeouts = {'social' : [], 'antisocial' : []};

//a social timeout
timeouts.social.push(setTimeout(function() {
              social1();
        }, 5000));

//an anti-social timeout
timeouts.antisocial.push(setTimeout(function() {
              antisocial1();
        }, 5000));

function clearTimeouts(namespace){
       for(var i = 0, z = timeouts[namespace].length; i < z; i++)
           clearTimeout(timeouts[namespace][i]);

       timeouts[namespace] = [];
    }

//usage e.g
clearTimeouts("social");
A. Wolff
  • 74,033
  • 9
  • 94
  • 155
  • 2
    You could maybe show a pseudo name-spaced means `timeouts = {'social' : [], 'antisocial' : []'}` and within the `clearAllTimeouts()` function accept a particular key? (you've already got 6 (deserved) up-votes, so it's not necessarily worth it, but since you've started...) =) – David Thomas Jun 12 '13 at 15:49
  • 1
    That seems like way overkill when this looks like some kind of toggle, not something that needs to generalize to lots of elements. – Barmar Jun 12 '13 at 15:52
  • If it's really just the two, then I'd agree with @Barmar. Plus this answer doesn't even bother to clear the Array, which means it's just going to get longer and longer. People should really be more careful about voting. –  Jun 12 '13 at 15:53
  • @Barmar: it could be, but I was anticipating future questions that will (probably) be closed as duplicates of this one that are asking about that type of issue. Might as well make it canonical while we can (and by 'we' I mean 'roasted', of course...) =) – David Thomas Jun 12 '13 at 15:55
  • @CrazyTrain: there is that omission too, but still: it answers the question that was asked, even if it could (and should) be improved to account for problems created by an ever-growing array of non-existent timeouts. – David Thomas Jun 12 '13 at 15:57
  • @DavidThomas: Sure. I didn't say it doesn't answer the question. But it's a pretty glaring omission to have received so many votes so quickly. –  Jun 12 '13 at 15:58
  • @CrazyTrain: but it answered the question (so 'this answer is useful'), and managing the solution wasn't a part of the question. So, while it's an improvement needing to be made, I still up-voted. Mind you, the *number* of up-votes surprised me a little. But I think they're deserved. – David Thomas Jun 12 '13 at 16:01
  • 1
    BTW, i only win 2 points from this answer actually :) Anyway, thx David and Crazy Train for good inputs – A. Wolff Jun 12 '13 at 16:03
  • 1
    @DavidThomas, roasted: To be clear, I've no problem with gaining rep off an answer. IMO, it's a pretty serious omission, especially for a hover event, but it's fixed now, so not an issue any more. That's all I really wanted from my first comment. :-) –  Jun 12 '13 at 16:07
  • @CrazyTrain ya, this was a serious omission thx for the correction – A. Wolff Jun 12 '13 at 16:09
0
//Incase if you are looking for full fledged code
    var dict = {};
    function checkForIntervals(id){
        var index = index; 
        var result = findOrAddProperty(id);
        if(result.length != 0){
             clearTimeoutsFor(id);
         }
         dict[id].push(setTimeout(function(){alertFunc(id,index);}, 60000)); 
    };

    // to clear specific area timeout
    function clearTimeoutsFor(namespace){
        for(var i = 0, z = dict[namespace].length; i < z; i++)
            clearTimeout(dict[namespace][i]);

        dict[namespace] = [];
    }

    to clear all timeouts
    function clearAllTimeOuts(){
        for (key in dict) {
            for(var i = 0, z = dict[key].length; i < z; i++)
                clearTimeout(dict[key][i]);
            dict[key] =[];
         }
    };

    function findOrAddProperty(str){
        var temp  = [];
        for (key in dict) {
              if(key == str){
                  if (dict.hasOwnProperty(key)) {
                        temp = dict[key];
                        break;
                      }
              }
         }
        if(temp.length == 0){
            dict[str] = [];
        }
        return temp;
    };


    function alertFunc(id,index) {
        jQuery(document).ready(function($) {
            do the ajax call here after 1 min
        });
    };