I couldn't find a solution to this, but the second this after mousedown will not work. I've seen different things about binding it but I haven't had any luck. (It works everywhere else in the code).
$(".rightArrow").click(function () {
var stop_slide = parseInt($(this).prev().css("marginLeft"));
scroll_size = $(this).prev().children().size() * 177 * -1;
if(stop_slide > scroll_size){
var int00; // declared here to make it visible to clearInterval.
$(this).mousedown(function(){
int00 = setInterval(function() {
$(this).prev().css( { marginLeft : "-=1px" } );
}, 1);
}).mouseup(function() {
clearInterval(int00);
});
}
});
The this from the setInterval is different than the this from mousedown. Simply use a self variable, this way:
$(".rightArrow").click(function() {
var stop_slide = parseInt($(this).prev().css("marginLeft"));
scroll_size = $(this).prev().children().size() * 177 * -1;
if (stop_slide > scroll_size) {
var int00; // declared here to make it visible to clearInterval.
$(this).mousedown(function() {
var self = this;
int00 = setInterval(function() {
$(self).prev().css({
marginLeft: "-=1px"
});
}, 1);
}).mouseup(function() {
clearInterval(int00);
});
}
});
Each function declared via the function statement has its own context (this), hence, you need to store the previous context into a variable to access it in another function.
Another way is to use bind:
int00 = setInterval(function () {
$(this).prev().css(...);
}.bind(this));
This will bind the current context (the current this) to the setInterval callback.
And if you use es2015, you can use arrow functions:
// the `this` from here
int00 = setInterval(() => {
// will be the `this` from here
});
The arrow functions have no context––they inherit the current context.
Related
I'm trying to cancel a requestAnimationFrame loop, but I can't do it because each time requestAnimationFrame is called, a new timer ID is returned, but I only have access to the return value of the first call to requestAnimationFrame.
Specifically, my code is like this, which I don't think is entirely uncommon:
function animate(elem) {
var step = function (timestamp) {
//Do some stuff here.
if (progressedTime < totalTime) {
return requestAnimationFrame(step); //This return value seems useless.
}
};
return requestAnimationFrame(step);
}
//Elsewhere in the code, not in the global namespace.
var timerId = animate(elem);
//A second or two later, before the animation is over.
cancelAnimationFrame(timerId); //Doesn't work!
Because all subsequent calls to requestAnimationFrame are within the step function, I don't have access to the returned timer ID in the event that I want to call cancelAnimationFrame.
Looking at the way Mozilla (and apparently others do it), it looks like they declare a global variable in their code (myReq in the Mozilla code), and then assign the return value of each call to requestAnimationFrame to that variable so that it can be used any time for cancelAnimationFrame.
Is there any way to do this without declaring a global variable?
Thank you.
It doesn't need to be a global variable; it just needs to have scope such that both animate and cancel can access it. I.e. you can encapsulate it. For example, something like this:
var Animation = function(elem) {
var timerID;
var step = function() {
// ...
timerID = requestAnimationFrame(step);
};
return {
start: function() {
timerID = requestAnimationFrame(step);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation = new Animation(elem);
animation.start();
animation.cancel();
timerID; // error, not global.
EDIT: You don't need to code it every time - that's why we are doing programming, after all, to abstract stuff that repeats so we don't need to do it ourselves. :)
var Animation = function(step) {
var timerID;
var innerStep = function(timestamp) {
step(timestamp);
timerID = requestAnimationFrame(innerStep);
};
return {
start: function() {
timerID = requestAnimationFrame(innerStep);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation1 = new Animation(function(timestamp) {
// do something with elem1
});
var animation2 = new Animation(function(timestamp) {
// do something with elem2
});
i have a problem accessing variable inside method in OOP.
this is my code :
var slideshow = {
elSet : $(".slideshow"),
next : function() {
},
swipe : function() {
var clear = this.autorun().loop;
onSwipe(function() {
clearInterval(clear); // not working
});
},
autorun : function() {
var self = this;
var loop = setInterval(function() {
self.next();
}, 5000);
},
initial : function() {
this.swipe();
this.autorun();
}
}
slideshow.initial();
i want to clearInterval from variable loop,
on browser console return error TypeError: this.loop(...) is undefined
what's wrong with my code?
Just assign the interval id returned by setInterval to a variable you can access, or like Barmar's answer return it.
var slideshow = {
elSet: $(".slideshow"),
next: function() {
},
swipe: function() {
var self = this;
onSwipe(function() {
//use the interval id to cancel
clearInterval(self.intervalRef);
});
},
// variable to store the interval id
intervalRef: null,
autorun: function() {
var self = this;
//assign the interval id generated by setInterval to a variable you can access
this.intervalRef = setInterval(function() {
self.next();
}, 5000);
},
initial: function() {
this.swipe();
this.autorun();
}
}
slideshow.initial();
Issues:
var clear = this.autorun().loop; Here this will have scope swipe and not object.
var loop = setInterval(function() {}) Here loop will have scope of autorun and will expire after function execution is over.
You can try something like this:
JSFiddle
function SlideShow() {
// self will hold current object reference for all functions
var self = this;
var interval = null;
function next() {
console.log('next');
}
function swipe() {
onSwipe(function() {
console.log("Clearint Interval")
clearInterval(interval);
});
}
// Private function
function onSwipe(callback) {
console.log("On Swipe");
// Check if value is passed and its a function
if (callback && typeof(callback) === 'function')
callback();
}
function loop() {
interval = setInterval(function() {
next();
}, 5000);
}
function init() {
swipe();
loop();
}
// Public properties
return {
elSet: $(".slideshow"),
next: next,
swipe: swipe,
loop: loop,
initial: init,
interval: interval
}
}
// Create a new instance of SlideShow
var slideshow = new SlideShow();
slideshow.initial();
In the swipe function, you have:
var clear = this.autorun().loop;
This expects this.autorun() to return an object, and tries to access the loop property of that object, which should contain the ID of an interval function. But autorun doesn't return anything, let alone an object with a loop property.
Change autorun to:
autorun : function() {
var self = this;
var loop = setInterval(function() {
self.next();
}, 5000);
return loop;
}
Then you can do:
var clear = this.autorun();
You also shouldn't call this.autorun() in the initial function. It's already called by this.swipe(). Running it again will cause two interval functions to run, and the ID of the second one isn't saved anywhere so that you can clear it.
I'm trying to cancel a requestAnimationFrame loop, but I can't do it because each time requestAnimationFrame is called, a new timer ID is returned, but I only have access to the return value of the first call to requestAnimationFrame.
Specifically, my code is like this, which I don't think is entirely uncommon:
function animate(elem) {
var step = function (timestamp) {
//Do some stuff here.
if (progressedTime < totalTime) {
return requestAnimationFrame(step); //This return value seems useless.
}
};
return requestAnimationFrame(step);
}
//Elsewhere in the code, not in the global namespace.
var timerId = animate(elem);
//A second or two later, before the animation is over.
cancelAnimationFrame(timerId); //Doesn't work!
Because all subsequent calls to requestAnimationFrame are within the step function, I don't have access to the returned timer ID in the event that I want to call cancelAnimationFrame.
Looking at the way Mozilla (and apparently others do it), it looks like they declare a global variable in their code (myReq in the Mozilla code), and then assign the return value of each call to requestAnimationFrame to that variable so that it can be used any time for cancelAnimationFrame.
Is there any way to do this without declaring a global variable?
Thank you.
It doesn't need to be a global variable; it just needs to have scope such that both animate and cancel can access it. I.e. you can encapsulate it. For example, something like this:
var Animation = function(elem) {
var timerID;
var step = function() {
// ...
timerID = requestAnimationFrame(step);
};
return {
start: function() {
timerID = requestAnimationFrame(step);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation = new Animation(elem);
animation.start();
animation.cancel();
timerID; // error, not global.
EDIT: You don't need to code it every time - that's why we are doing programming, after all, to abstract stuff that repeats so we don't need to do it ourselves. :)
var Animation = function(step) {
var timerID;
var innerStep = function(timestamp) {
step(timestamp);
timerID = requestAnimationFrame(innerStep);
};
return {
start: function() {
timerID = requestAnimationFrame(innerStep);
}
cancel: function() {
cancelAnimationFrame(timerID);
}
};
})();
var animation1 = new Animation(function(timestamp) {
// do something with elem1
});
var animation2 = new Animation(function(timestamp) {
// do something with elem2
});
I am having a hard time getting a countdown timer working as I don't know what I am doing wrong. I am trying to setup a countdown timer using jQuery in a prototype.
The main problem I see so far is at the setInterval:
_self.counter = setInterval(_self.runTimer(_self),1000);
When I don't pass in the "this" I get NaN but when I do the countdown only happens once and then stops.
Here is my JSFiddle work so far:
http://jsfiddle.net/f9GN7/
Thank you in advance.
I've modified a little of your code, I changed setInterval to setTimeout.
var timer_code = function(){
this.counter;
this.timeCountDown = 30;
}
timer_code.prototype = {
init : function(){
var _self = this;
$('#start').on('click',function(e){
_self.setTimer();
});
},
setTimer : function(){
var _self = this;
// _self.counter = setInterval(_self.runTimer(_self),1000);
var timerLoop = function(){
if(_self.timeCountDown > 0){
_self.runTimer();
setTimeout(timerLoop, 1000);
}
};
timerLoop();
},
runTimer : function(){
var _self = this;
_self.timeCountDown--;
if(_self.timeCountDown <= 0){
// clearInterval(_self.counter);
$('#timer').html("DONE");
return;
}
$('#timer').html(_self.timeCountDown);
console.log(_self.timeCountDown);
}
}
var timer = new timer_code();
timer.init();
http://jsfiddle.net/f9GN7/1/
setInterval gets a function reference as its first parameter ..
This function may not return a function object, the function call you just passed needs to be called in the scoope of a closure
Keeping your code with just a few modifications :
setTimer: function(){
if(this.counter)
clearInterval(this.counter); // timer may have already been launched, it may need to be cleared if its value is an integer and is != 0
this.counter = setInterval(
(function (ref) {
return function () {
ref.runTimer();
}
})(this),
1000);
}
See Fiddle Here
I am working on a modification of tamper data that will allow me to send the HTTP request/responses it observes to a server. So far, that functionality has been implemented correctly. The next step is to automate this process, and I wish to use a toolbarmenu button of type 'checkbox' to toggle this functionality on and off.
So far I have this bit of code in the .XUL:
<toolbarbutton id="tamper.autosend" label="&tamper.toolbar.autosend;" type="checkbox" oncommand="oTamper.toggleTimer();"/>
And this function in the main driver of my extension:
toggleTimer : function() {
var checked = document.getElementById('tamper.autosend').checked;
var consoleService = Components.classes["#mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
consoleService.logStringMessage(checked);
if (checked) {
var interval = window.setInterval(function(thisObj) { thisObj.sendResults(true); }, 1000, this);
}
else {
window.clearInterval(interval);
}
}
Using the consoleService I see that the value of 'checked' is indeed correct. I believe the problem lies with how I am calling clearInterval, but I'm not exactly sure how to remedy it.
Any help is greatly appreciated!
You have defined interval inside if try to declare your variable on the start
var interval = 0;
toggleTimer : function() {
var checked = document.getElementById('tamper.autosend').checked;
var consoleService = Components.classes["#mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
consoleService.logStringMessage(checked);
if (checked) {
interval = window.setInterval(function(thisObj) { thisObj.sendResults(true); }, 1000, this);
}
else {
window.clearInterval(interval);
}
}
Your doing it wrong, each time you want to set the new interval you should clear it first
clearInterval(intervalID);
console.log('reset timer');
intervalID = setInterval(function () {
console.log('tick');
}, refreshInterval);
You're storing the interval in a local variable; the value is lost after the function returns, next time you attempt to clearInterval an undefined variable. Store the interval in i.e. a global variable instead:
if (checked) {
window.interval = window.setInterval(function(thisObj) { thisObj.sendResults(true); }, 1000, this);
}
else {
window.clearInterval(interval);
}
Ofcourse, because interval is defined as a private variable. It is defined in the toggleTimer function and is destroyed when the function ends.
Use interval = window.setInterval() instead of var interval = window.setInterval() to define a global variable that is accessible later for clearInterval.
Below are some examples of the JavaScript variable scope. var is used to define a variable in the current scope. Leaving var always creates or changes a local variable.
function func1() {
i = 1; // global
}
func1();
alert(i); // 1
var j = 2;
function func2() {
var j = 3; // private
}
func2();
alert(j); // 2
k = 4;
function func3() {
k = 5; // global
}
func3();
alert(k); // 5
var l = 6;
function func4() {
l = 7; // global
}
func4();
alert(l); // 7
function func5() {
var m = 6; // private
}
func5();
alert(m); // undefined