Class button timeout - javascript

So i have a class that has some functions that are making a carousel work. But pressing the next button fast deletes the previous animation and starts the next so i want to make the button wait for the animation to end. The animation inside css is 0.6 seconds but the timeous i set inside goNext functions is completely ignored when i fast click the button. What am I doing wrong here?
index.js
let carousel = document.getElementById("carousel");
let seats = document.querySelectorAll("ul > li");
if (seats.length === 1)
carousel.style.left = 0;
class SLID {
constructor() {
this.nextDisable = true;
this.changeNextDisable = this.changeNextDisable.bind(this);
}
changeNextDisable() {
this.nextDisable = false;
}
goToNext() {
if(this.nextDisable===false){
this.nextDisable = true;
var el, i, j, new_seat, ref;
el = document.querySelector("ul > li.is-ref");
el.classList.remove('is-ref');
new_seat = el.nextElementSibling || seats[0];
new_seat.classList.add('is-ref');
new_seat.style.order = 1;
for (i = j = 2, ref = seats.length; (2 <= ref ? j <= ref : j >= ref); i = 2 <= ref ? ++j : --j) {
new_seat = new_seat.nextElementSibling || seats[0];
new_seat.style.order = i;
}
carousel.classList.remove('toPrev');
carousel.classList.add('toNext');
carousel.classList.remove('is-set');
return setTimeout(()=> {
this.changeNextDisable();
carousel.classList.add('is-set');
}, 60);
}
goToPrev() {
var el, i, j, new_seat, ref;
el = document.querySelector("ul > li.is-ref");
el.classList.remove('is-ref');
new_seat = el.previousElementSibling || seats[seats.length - 1];
new_seat.classList.add('is-ref');
new_seat.style.order = 1;
for (i = j = 2, ref = seats.length; (2 <= ref ? j <= ref : j >= ref); i = 2 <= ref ? ++j : --j) {
new_seat = new_seat.nextElementSibling || seats[0];
new_seat.style.order = i;
}
carousel.classList.remove('toNext');
carousel.classList.add('toPrev');
carousel.classList.remove('is-set');
return setTimeout((function () {
return carousel.classList.add('is-set');
}), 50);
}
}
}
let s = new SLID();
document.getElementById("nextButton").addEventListener("click", () => {
s.goToNext();
});
document.getElementById("prevButton").addEventListener("click", () => {
s.goToPrev();
});

According to your animation type (transition or animation) you can replace
return setTimeout(()=> {
this.changeNextDisable();
carousel.classList.add('is-set');
}, 60);
(and trying avoid it) to:
carousel.addEventListener("animationend", () => {
this.changeNextDisable();
carousel.classList.add('is-set');
}, {
once: true,
});
or
carousel.addEventListener("transitionend", () => {
this.changeNextDisable();
carousel.classList.add('is-set');
}, {
once: true,
});
same thing for goToPrev method.

You tell us that the CSS animation has a duration of 0.6 seconds, which is 600 milliseconds, not 60 or 50 milliseconds, which is what you set your setTimeout delay to.
So:
return setTimeout(()=> {
this.changeNextDisable();
carousel.classList.add('is-set');
}, 600);
// ^^^^
Having said that, you should look into listening to the transactionend event, as then you don't need to know how long the CSS transition takes.
That would look like this:
const done = () => {
carousel.removeEventListener("transactionend", done);
this.changeNextDisable();
carousel.classList.add('is-set');
}
return carousel.addEventListener("transactionend", done);

Related

React useEffect and useState returns a number instead of an object

I've been battle with this problem for 2 days now, I'm trying to implement a continuous vertical text scrolling, but for some reasons unknown to me react returns a number instead of my array object (after I logged the output to see what was going wrong with my code) at the second iteration (as the array is constantly updated at interval). For the record, this was initially implemented in an Angular JS application, but I'm trying to convert it to react with useEffect() and useState() to update the changes in the array.
Below is what I've done so far:
const Skills = () => {
let skillWrap = useRef();
let [activeSkills, setActiveSkills] = useState([]);
console.log(activeSkills);
console.log(typeof activeSkills);
let sMax = totalSkills.length - 1; // 0 -> 19
let activeStart = Math.floor(Math.random() * (sMax + 1));
let activeEnd = activeStart === 0 ? sMax : activeStart - 1;
for (let e = activeStart; e <= sMax; e++) {
setActiveSkills(activeSkills.push(totalSkills[e]));
}
if (activeStart !== 0) {
for (let s = 0; s <= activeEnd; s++) {
setActiveSkills(activeSkills.push(totalSkills[s]));
}
}
let scrollDis = 0,
scrollingDown = false,
scrollingUp = false,
scrollingDownSelf = false,
scrollingUpSelf = false,
scrollCatchInterval = 40,
scrollDirection = "up",
hasScrolledRecently = false;
const wheelEventHandler = e => {
let skillFocused = skillWrap.current.childNodes[19];
skillFocused.classList.remove("active");
function animateScroll(scrollDis, callback) {
let curLeftTop = scrollDis * 8,
curLeftFinal = scrollDis * 4;
tween(skillWrap.current, -curLeftFinal, curLeftTop, 1, callback);
}
function scrollUp() {
setTimeout(() => {
for (let su = 0; su < scrollDis; su++) {
activeEnd--;
activeStart--;
if (activeEnd < 0) activeEnd = 19;
if (activeStart < 0) activeStart = 19;
/*setActiveSkills(activeSkills.unshift(totalSkills[activeStart]));
setActiveSkills(activeSkills.pop());*/
activeSkills.unshift(totalSkills[activeStart]);
activeSkills.pop();
}
skillFocused.classList.add("active");
skillWrap.current.style.transform = "none";
scrollDis = 0;
scrollingUp = false;
scrollingUpSelf = false;
if (e.deltaZ === 0) {
setTimeout(() => {
hasScrolledRecently = false;
}, 3000);
}
}, 0);
}
function scrollDown() {
setTimeout(() => {
for (let sd = 0; sd < Math.abs(scrollDis); sd++) {
activeEnd++;
activeStart++;
if (activeEnd > 19) activeEnd = 0;
if (activeStart > 19) activeStart = 0;
/*setActiveSkills(activeSkills.push(totalSkills[activeEnd]));
setActiveSkills(activeSkills.shift());*/
activeSkills.push(totalSkills[activeEnd]);
activeSkills.shift();
}
skillFocused.classList.add("active");
skillWrap.style.transform = "none";
scrollDis = 0;
scrollingDown = false;
scrollingDownSelf = false;
if (e.deltaZ === 0) {
setTimeout(() => {
hasScrolledRecently = false;
}, 3000);
}
}, 0);
}
if (
(e.deltaY === 100 || e.deltaY === 3) &&
!scrollingUp &&
!scrollingDownSelf
) {
// (scroll down) add skill to bottom & remove skill from top
scrollDirection = "down";
scrollDis--;
scrollingDown = true;
if (e.deltaZ === 0) hasScrolledRecently = true;
let scd = scrollDis;
setTimeout(() => {
if (scrollDis === scd) {
if (scrollDis < -6) scrollDis = -6;
scrollingDownSelf = true;
animateScroll(scrollDis, scrollDown);
}
}, scrollCatchInterval);
} else if (
(e.deltaY === -100 || e.deltaY === -3) &&
!scrollingDown &&
!scrollingUpSelf
) {
// (scroll up) add skill to top & remove skill from bottom
scrollDirection = "up";
scrollDis++;
scrollingUp = true;
if (e.deltaZ === 0) hasScrolledRecently = true;
let scu = scrollDis;
setTimeout(() => {
if (scrollDis === scu) {
if (scrollDis > 5) scrollDis = 5;
scrollingUpSelf = true;
animateScroll(scrollDis, scrollUp);
}
}, scrollCatchInterval);
}
};
function tween(o, x, y, durationSecs, onComplete) {
let fps = 30,
count = 0,
stopAt = fps * durationSecs,
easef = Quad_easeInOut;
let f = function() {
count++;
if (count >= stopAt) {
tween_stop(o);
if (onComplete) onComplete();
} else {
tween_setProperty(
o,
easef(count, 0, x, stopAt),
easef(count, 0, y, stopAt)
);
}
};
clearInterval(o._tween_int);
o._tween_int = setInterval(f, (durationSecs * 1000) / fps);
}
function tween_stop(o) {
clearInterval(o._tween_int);
}
function tween_setProperty(o, x, y) {
o.style.cssText += ";transform:translate3d(" + x + "vw," + y + "vh,0);";
}
function Quad_easeInOut(t, b, c, d) {
if ((t /= d / 2) < 1) return (c / 2) * t * t * t * t + b;
return (-c / 2) * ((t -= 2) * t * t * t - 2) + b;
}
useEffect(() => {
/*console.log(activeSkills);*/
setTimeout(() => {
skillWrap.current.childNodes[19].classList.add("active");
}, 2000);
window.addEventListener("wheel", wheelEventHandler);
function constantScroll() {
// prevents scrolling while changing views
setTimeout(function() {
// emulate scrolling of the skill list
let scrollEvent = new WheelEvent("wheel", {
deltaY: scrollDirection === "up" ? -100 : 100,
deltaZ: 1 // used to differentiate between user scroll / programmatic scroll
});
if (!hasScrolledRecently) {
// 3 scroll events are dispatched to mirror scrolling of 3 skills
for (let r = 0; r < 3; r++) {
window.dispatchEvent(scrollEvent);
}
}
constantScroll();
}, 3000);
}
// wait 3 seconds before issuing first scroll
setTimeout(function() {
constantScroll();
}, 2000);
return () => {
window.removeEventListener("wheel", wheelEventHandler);
console.log("Skills Component will unmount");
};
}, [activeSkills]);
return (
<div>
<div className="view skills active active-f">
<div className="header-container skills">
<div className="header-title-wrap">
<div className="cover" />
<h1 className="header big first">My</h1>
<h1 className="header big last">Skillsset</h1>
</div>
<div className="header-info-wrap">
<div className="header-content-body skill-one">
<div className="line-left" />
<p className="header body about-one">
The core of my skill set largely surrounds the MERN{" "}
<strong>stack</strong>, to achieve both a clear and dynamic user
experience. I also have some experience with mobile integration
(Android and iOS). Strengthening my grasp of the mobile app
development space is one of my primary goals for the near
future.
</p>
</div>
</div>
</div>
<div className="skill-container active active-f">
<div className="skill-wrap">hey</div>
</div>
</div>
<div className="skill-container active-f active">
<div ref={skillWrap} className="skill-wrap">
{console.log(activeSkills)}
{activeSkills.map((skill, i) => (
<div key={i} className="skill">
{skill}
</div>
))}
</div>
</div>
</div>
);
};
Below is the https://codesandbox.io/ page to see what I've done so far, and the link to the Angular JS implementation which I'm trying to achieve with React.
My React implementation (from the skills route): https://codesandbox.io/s/shy-http-jlrle
Original Angular implementation (skills route): https://codesandbox.io/s/github/eazylaykzy/portfolio-ex
I really would appreciate any effort at helping me get this to work.
Just to abstract the first part as mentioned in my comment, you could write your own hook and use it as so
import React, { useMemo } from 'react';
// How to shuffle an array
// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
const newArray = [...array];
for (let i = newArray.length - 1; i > 0; i -= 1) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
}
return newArray;
}
function useActiveSkills(skills) {
return useMemo(() => shuffle(skills), [skills]);
}
function Component() {
const activeSkills = useActiveSkills();
return (
<>
{activeSkills.map((skill) => (
<p>{skill.name}</p>
))}
</>
);
}

Run function only once until onmouseout

I have an anchor tag that plays a sound everytime the link is hovered:
<a onmouseenter="playAudio();">LINK</a>
However, when hovered, the link creates some characters that, if I keep moving the mouse inside the element, it keeps playing the sound over and over again.
Is there a way to play the onmouseenter function only once until it has detected the event onmouseout?
I've tried adding:
<a onmouseenter="playAudio();this.onmouseenter = null;">LINK</a>
but then it only plays the sound once.
Here goes the TextScramble animation function:
// ——————————————————————————————————————————————————
// TextScramble
// ——————————————————————————————————————————————————
class TextScramble {
constructor(el) {
this.el = el
this.chars = '!<>-_\\/[]{}—=+*^?#________'
this.update = this.update.bind(this)
}
setText(newText) {
const oldText = this.el.innerText
const length = Math.max(oldText.length, newText.length)
const promise = new Promise((resolve) => this.resolve = resolve)
this.queue = []
for (let i = 0; i < length; i++) {
const from = oldText[i] || ''
const to = newText[i] || ''
const start = Math.floor(Math.random() * 40)
const end = start + Math.floor(Math.random() * 40)
this.queue.push({
from,
to,
start,
end
})
}
cancelAnimationFrame(this.frameRequest)
this.frame = 0
this.update()
return promise
}
update() {
let output = ''
let complete = 0
for (let i = 0, n = this.queue.length; i < n; i++) {
let {
from,
to,
start,
end,
char
} = this.queue[i]
if (this.frame >= end) {
complete++
output += to
} else if (this.frame >= start) {
if (!char || Math.random() < 0.28) {
char = this.randomChar()
this.queue[i].char = char
}
output += `<span class="dud">${char}</span>`
} else {
output += from
}
}
this.el.innerHTML = output
if (complete === this.queue.length) {
this.resolve()
} else {
this.frameRequest = requestAnimationFrame(this.update)
this.frame++
}
}
randomChar() {
return this.chars[Math.floor(Math.random() * this.chars.length)]
}
}
// ——————————————————————————————————————————————————
// Configuration
// ——————————————————————————————————————————————————
const phrases = [
'MAIN_HUB'
]
const el = document.querySelector('.link_mainhub')
const fx = new TextScramble(el)
let counter = 0
const next = () => {
fx.setText(phrases[counter]).then(() => {});
}
el.addEventListener('mouseenter', next);
<a class="link_mainhub" onmouseenter="playAudio();">LINK</a>
Thanks.
Set a variable when you start playing the audio, and check for this before playing it again. Have the animation unset the variable when it's done.
function audioPlaying = false;
function playAudio() {
if (!audioPlaying) {
audioPlaying = true;
audioEl.play();
}
}
const next = () => {
fx.setText(phrases[counter]).then(() => {
audioPlaying = false;
});
}

Starting Javascript intervals nonsynchronously and stop each after three runs

I have a function for letting blink a OpenLayer marker three times. The simplified version which only shows console messages:
function blink_three_times(layername){
var x = 0;
setTimeout(function() {
blink_in = setInterval(function() {
x = x+1;
if ( x === 3) {clearInterval(blink_in)};
console.log(layername + ' is visible');
}, 500);
}, 250);
blink_out = setInterval(function() {
if (x === 2) {clearInterval(blink_out)};
console.log(layername + ' is invisible');
}, 500);
};
It works fine, but if it is started multiple times before one has finished, the counter (x) exceeds 3 and the interval does not stop. How can I avoid that?
That is because you have funcions blink_in & blink_out in global scope. When you are calling it second time it overwrites the definitions of functions.
Define them using var to make them local.
var blink_in = setInterval(function() {..})
and
var blink_out = setInterval(function() {..})
DEMO
Your variables blink_in and blink_out are global ones so if you call the function multiple times they will override it and therefore cannot stop the interval properly.
Use them in your function scope by definining them with "var" in order to avoid the problem (see http://jsfiddle.net/cb0h8tst/)
function blink_three_times(layername){
var x = 0;
var blink_in, blink_out;
setTimeout(function() {
blink_in = setInterval(function() {
x = x+1;
if ( x === 3) {clearInterval(blink_in)};
console.log(layername + ' is visible');
}, 500);
}, 250);
blink_out = setInterval(function() {
if (x === 2) {clearInterval(blink_out)};
console.log(layername + ' is invisible');
}, 500);
};
Based on your last update question,
you could also make a more dynamic to keep track of the layers that are actually being blinked, a possible example
function Blinker(opt) {
var ts = {};
this.elementId = opt ? opt.elementId : undefined;
this.runs = (opt ? opt.runs : 3) || 3;
this.completed = (opt ? opt.completed : function() { }) || function() { };
this.start = function(arg) {
var timestamp = arg || this.elementId, that = this;
if (typeof ts[timestamp] !== 'undefined') {
console.log('Cannot run multiple times on same layer');
return;
}
ts[timestamp] = {
timestamp: timestamp,
count: 0,
element: document.getElementById(arg || this.elementId),
controller: this
};
setTimeout(function() {
ts[timestamp].showInterval = setInterval(that.setVisibility.bind(ts[timestamp], true), 500);
}, 250);
ts[timestamp].hideInterval = setInterval(this.setVisibility.bind(ts[timestamp], false), 500);
};
this.setVisibility = function(visible) {
this.element.style.visibility = visible ? 'visible' : 'hidden';
this.element.style.display = visible ? 'inherit' : 'none';
if (visible) {
this.count++;
}
if (!visible && this.count === 2)
{
clearInterval(this.hideInterval);
}
if (visible && this.count === 3)
{
clearInterval(this.showInterval);
this.controller.completed.apply(this.controller, [this.element.id]);
delete ts[this.timestamp];
}
};
}
var blinker = new Blinker({
elementId: 'blinker',
runs: 3,
completed: function(elementId) {
var log = document.getElementById('log');
log.innerHTML += '<p><strong>' + elementId + '</strong> has finished blinking</p>';
}
});
you could find the fiddle here: http://jsfiddle.net/q70w0kpx/

Javascript Incrementing Numbers

What I'm after:
There are 5 counters on my page, they should all start from 0 and count upwards (increment) at the same time to different values that are set at different speeds. So for example I set 10, 25, 1500, 400, 500 in my variables I would like them all to reach these values.
• start at the same time
• all increment at different speeds
• stop at value set for each
My Problem
I can't figure out a good way to write some simple very efficient javascript to do this (going to be used on a mobile), currently I'm using setinterval which seems to start all the counters at different times and jerks/not smooth..
how far I've got so far
http://jsfiddle.net/95smH/
setInterval(f1,500);
setInterval(f2,1500);
setInterval(f3,500);
setInterval(f4,50);
var v1 = 0
, v2 = 0
, v3 = 0
, v4 = 0;
function f1() {
$('.count.v1').text(v1);
if ( v1 < 450 )
{
v1 ++;
}
}
function f2() {
$('.count.v2').text(v2);
if ( v2 < 50 )
{
v2 ++;
}
}
function f3() {
$('.count.v3').text(v3);
if ( v3 < 23 )
{
v3 ++;
}
}
function f4() {
$('.count.v4').text(v4);
if ( v4 < 4 )
{
v4 ++;
}
}
This would be my shot at a slightly more general way. It will also kill the setInterval once every counter has finished. Of course this will still have the typical inaccuracy of Javascript intervals.
var counter = new (function () {
'use strict';
var counters = [],
handler = null,
precision = 50;
this.addCounter = function (maxValue, interval, selector) {
counters.push({
maxValue: maxValue,
currentValue: 0,
interval: interval / precision,
intervalCounter: 0,
$output: $(selector)
});
return this;
};
this.start = function () {
handler = setInterval(function () {
var stillRunning = false;
for (var i = 0; i < counters.length; i++) {
var counter = counters[i];
counter.intervalCounter++;
if (counter.intervalCounter === counter.interval) {
counter.intervalCounter = 0;
counter.currentValue++;
if (counter.currentValue <= counter.maxValue) {
stillRunning = true;
counter.$output.val(counter.currentValue);
}
} else {
stillRunning = true;
}
}
if (!stillRunning) {
clearInterval(handler);
}
}, precision);
};
return this;
})();
counter
.addCounter(50, 250, '.v1')
.addCounter(25, 500, '.v2')
.start();
Demo fiddle: http://jsfiddle.net/s9AYz/1/
Note that precision must be set such that the interval of each counter is a multiple of it (Boris solution has the same requirement).
This is based on your own code style:
setInterval(tick,50);
var cusers = 0
, cawardshows = 0
, ccountries = 0
, cregions = 0;
var susers = 500
, sawardshows = 1500
, scountries = 500
, sregions = 50;
var i = 0;
function tick() {
$('.count.users').text(cusers);
if ( cusers < 450 && i % susers == 0)
{
cusers ++;
}
$('.count.awardshows').text(cawardshows);
if ( cawardshows < 50 && i % sawardshows == 0 )
{
cawardshows ++;
}
$('.count.countries').text(ccountries);
if ( ccountries < 23 && i % scountries == 0 )
{
ccountries ++;
}
$('.count.regions').text(cregions);
if ( cregions < 4 && i % sregions == 0)
{
cregions ++;
}
i += 50;
}
The idea is to have only one timer, so all updates will be synchronized to the same clock. Since values have different "speeds", you update some of them only every nth step.
Here is a solution quite cpu-friendly :
- you only have one setInterval using a base period that you decide.
- On each interval you iterate through your all counters doing very little work each time.
(i even avoided to use % ).
- The elements are cached.
jsbin is here :
http://jsbin.com/urUxojo/2/edit?html,js,console,output
window.onload=function() {
// this is the period of the base Interval in ms.
// The counters will be aligned on this base period
Counter.basePeriod = 50 ;
// constructor of a Counter
// ! initializes the counter display.
function Counter(id, period_ms, max, initialValue) {
this.element = document.getElementById(id);
this.period = Math.ceil(period_ms / Counter.basePeriod) || 1;
this.max = max ;
this.value = initialValue || 0 ;
this.last = 0;
this.element.value = (this.value);
return this;
};
// called on each basePeriod tick
// updates the element every period until it reaches its max value.
Counter.prototype.tick = function() {
this.last++;
if (this.last == this.period &&
this.value != this.max ) {
this.value++;
this.element.value = (this.value);
this.last=0;
}
};
Counter.counters = [];
Counter.start= function () {
function handleCounters() {
for (var i=0; i< Counter.counters.length; i++) { Counter.counters[i].tick(); }
}
Counter._interval = setInterval(handleCounters, Counter.basePeriod);
};
Counter.add = function() {
var newCounter = Object.create(Counter.prototype);
Counter.counters.push( Counter.apply(newCounter, arguments) );
}
// -------------------------------
Counter.add('cnt1' , 500 , 450 );
Counter.add('cnt2' , 400 , 40 );
Counter.add('topCounter', 1000 , 5 );
Counter.start();
}
Well, you always want to get rid of duplicity, so you can do:
function IntervalClass(selector, sleepTime, maxValue, startValue) {
var curValue = startValue;
this.tick = function () {
if (curValue < maxValue) {
curValue++;
}
$(selector).html(curValue);
};
this.start = function () {
setInterval(this.tick, sleepTime);
};
}
new IntervalClass(".count.users", 1000, 35, 0).start();
new IntervalClass(".count.awardshows", 500, 20, 0).start();
new IntervalClass(".count.countries", 1500, 15, 0).start();
new IntervalClass(".count.regions", 200, 100, 0).start();
JSFIDDLE

how to clear all javascript Timeouts?

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);
}
);
__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");
//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
});
};

Categories

Resources