clearTimeout() Doesnt work - javascript

When I double click, it seems that the clearTimeout(timer) doesnt work, and the code calls the function activated(currentactiveid);
But also the function inside the setTimeout("activated2('" + currentactiveid + "')", 2000); references timer. So at the end I think that the problem is that the clearTimeout cannot find the variable timer.
HTML:
<td class='td2' id='currentid1' ondblclick='activatedd(this);' onclick='dclickornot(this);'>Some Text</td>
Javascript:
// Single Click
function dclickornot(e)
{
var currentactiveid = e.id;
var timer = setTimeout("activated2('" + currentactiveid + "')", 2000);
}
// Double Click
function activatedd(e)
{
clearTimeout(timer);
var currentactiveid = e.id;
activated(currentactiveid);
}

In JavaScript, variables are defined in the scope of the function. So you must use a global variable instead. This still doesn't prevent multiple single clicks, though.
(function () {
'use strict';
var timer, currentactiveid;
// Single Click
function dclickornot(e) {
currentactiveid = e.id;
timer = window.setTimeout(function () {activated2(currentactiveid); }, 2000);
}
// Double Click
function activatedd(e) {
window.clearTimeout(timer);
timer = undefined;
currentactiveid = e.id;
activated(currentactiveid);
}
}());

You need to remove 'var' from in front of your timer. It's scope is locked to the dclickornot() function.

Your timer variable is declared inside a function, and is out of scope in the activatedd function. To resolve it, declare timer in global scope, outside the two functions.

In javascript, the "var" keyword used inside a function creates a local variable that can only be seen from inside this function or from the scope chain created underneath this function.
In your case, "clearTimeout(timer);" is using a timer variable that is always undefined.

Related

How to deal with nested functions in javascript?

It might be a beginner question but I'm facing with the next situation:
$(function f() {
function test2() {
//.....
}
function GetData() {
//.....
}
function update() {
test2();
GetData();
//...
}//end update
update();
});//end f()
function stop() {
clearInterval(multipleCalls);
}
function start() {
multipleCalls=null; //this is a global variable
setTimeout(update, 1000);
}
The stop function stops a graphic when a button is pressed and everything works fine. The start function should restart a graphic when a button is pressed. My guess is that the update function is not well invoked in start function. How could I do so everything to work fine?
You have currently commented out the } that closes the update function, so the line that says end f doesn't in fact end f(). In its present state, your code would not execute. (I note that someone else edited your code after which this remark is no longer valid; I don't know if the edit is closer to your actual code, or if it did in fact obscure a real error)
You're referring to both multiplecalls and multipleCalls. Note that javascript is case sensitive.
You're clearing multipleCalls but never setting it to anything but null. Did you intend to write multipleCalls = setTimeout(update, 1000) ?
start, being placed outside of f, won't have access to update. Either define update and the functions it is dependent upon outside of f(), or make it globally accessible, i.e.
window.update = function() { ... }
Which you'd then be able to access as setTimeout(window.update, 1000);
You have a scoping issue. The update is only known within the f.
You are trying to call it from outside f in start. The only way to achieve this is to either expose function update to the same scope as where start is, or bring start to the same scope as update.
The first option is easiest (and ugliest):
function update() {
//...
}
// assign it to the global scope (window is the global scope for browsers)
window.update = update;
Now update is available from `starts.
The more appropriate approach would be to define your handlers (which call start and stop within the scope of f, for example
$(function f() {
//.. everything there now
$('.start').on('click', function(e) {
setTimeout(update, 1000);
});
});
Working example
$(function f() {
var timer; // no need to be 'global'
function update() {
$('.result').text(new Date() + ' GetData();');
}
$('.start').on('click', function() {
// always clear a timer before setting it
clearTimeout(timer);
// and always set a timer variable, so it can be cancelled
timer = setTimeout(update, 1000);
});
$('.stop').on('click', function() {
// cancel the timer
clearTimeout(timer);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class=start>start</button>
<button class=stop>stop</button>
<div class=result>..</div>
You could try this:
window.update = function update() {...}
and then:
setTimeout(window.update, 1000);

Why doesn't setTimeout recognize function name?

(function( $ ){
$.fn.hash = function(){
function activate()
{
setTimeout('checkHash()', 100);
}
activate();
var previousHashTag = location.hash;
var previousHashProperty = '';
function checkHash()
{
if( previousHashTag !== location.hash )
{
$('body').trigger("hashchange", [ getHashObj() ]);
previousHashTag = location.hash;
setTimeout( "checkHash()", 200);
}
setTimeout( "checkHash()", 100);
}
This is my hash plugin I'm trying to make.
I would like to call the activate() function when user loads the plugin.
The activate function would set a timeout to check for a hash every 100 miliseconds.
How can I pull this off since checkHash is outside of the function in this object?
You are using string argument in setTimeout, which means that the code will be run in global object. As your called function is defined inside a closure of another function, you have to pass a reference
setTimeout(checkHash, 100);
or use anonymous function
setTimeout(function(){
checkHash();
});
You have to use the second approach when you want to pass any arguments to function called from setTimeout.
setTimeout(function(){
checkHash(arg);
});
You are passing strings to setTimeout and evaluating them. This breaks the normal scope. Don't do that, pass functions instead.
setTimeout(checkHash, 100);
Now scope will be preserved, and you can access activate from checkHash and vice versa as they are declared in the same scope.

How to clear timeout in javascript?

Why is this not working?
$('#plugbot-likebox').hover(function () {
$('#plugbot-ui').slideDown();
$('#ZobrazNastavenia').fadeOut("fast");
}, function () {
toUi = setTimeout(function(){
$('#plugbot-ui').slideUp();
}, 1500);
toNastavenia = setTimeout(function(){
$('#ZobrazNastavenia').fadeIn("fast");
}, 2000);
});
I need clear timeout but this not working. Please tell me why. Thanks.
timeoutUI and timeoutNastavenia are variables that are locally scoped to the anonymous functions you define them in.
If you want them available in a wider scope, then you have to declare them in a wider scope.
Don't use var inside the anonymous functions. Do use var variableName outside of those functions. (e.g. just before the first line of the code in the question).
this is an example to clear timeout:
var myVar;
function myFunction()
{
myVar = setTimeout(function(){alert("Hello")},3000);
}
function myStopFunction()
{
clearTimeout(myVar);
}
as you can see myVar is defined in global scope, so in your code it will not work because timeoutUI and timeoutNastavenia are private variables, you should use timeoutUI=... instead of var timeoutUI=..
If I'm using jQuery and timeouts, then I always set them on the element itself:
$('#plugbot-ui').data(
'timeout-toUi',
setTimeout(function(){
$('#plugbot-ui').slideUp();
}, 1500)
);
This way you can clear the timeout by getting the ID off of the element itself:
clearTimeout($('#plugbot-ui').data('timeout-toUi'));
By the way, when using jQuery you can just use .delay():
$('#plugbot-ui').delay(1500).slideUp();
And you can use .stop() to stop the animation and clear and finish all animations:
$('#plugbot-ui').stop(true, true);

jQuery closure: How to get a value from a function click

I don't quite understand JS closures and I think it can solve my problem. here it is:
I have something like that :
$(document).ready(function () {
$("#buttonConfirm").click(function () {
popup_confirme();
});
});
function popup_confirme() {
var r = popup_modal();
}
function popup_modal() {
var int_val = 0;
$(".button").click(function () {
int_val = ($(this).val() == 'yes' ? '1' : '0');
});
return int_val;
}
I would like to get my int_val returned by the button click event. I need to get the 'r' value as 0 or 1. I know I should use closures, but I dont know how to do it. Thank you for your expertise !
You can't do this, it's impossible, for reasons unrelated to closures.
Your not calling the code that sets int_val, you're only defining the code, and saying "when .buttons are clicked, invoke this code". The code will not have been executed at the point you run return int_val, it will be executed at some point in the future when the button is clicked.
This block of code cannot logically work:
// First line run
var int_val = 0;
// Second line run
$(".button").click(function () {
// This line runs in the future, or maybe never, if the button isn't clicked
int_val = ($(this).val() == 'yes' ? '1' : '0');
});
// Third line run
return int_val;
If you want to communicate values back out of asynchronous functions, you should use promises:
function popup_modal() {
var dfd = $.Deferred();
$(".button").click(function () {
int_val = ($(this).val() == 'yes' ? '1' : '0');
// Allow int_val to find its way back to the calling code's `done` handler
dfd.resolve(int_val);
});
return dfd.promise()
}
The calling code will receive a promise object, which it can add callbacks to:
function popup_confirme() {
var r;
popup_modal().done(function (int_val) {
r = int_val;
}
}
I can't intuit beyond this point what you meant int_val to do up in your calling code.
A closure occurs when an inner function references something defined outside it. To illustrate:
function outer() {
var foo = 1;
element.click(function () {
// this function creates a closure on foo.
alert(foo);
});
};
What you seem to want done is that your int_val variable be accessible where both popup_modal and popup_confirme can get to it.
Many ways to do it based off your example, but something as simple as this can work:
(function () {
var int_val = 0;
var popup_modal = function () {
int_val = $(this).val() === 'yes' ? 1 : 0;
};
var popup_confirme = function () {
// your original code here doesn't really do anything
alert(int_val);
};
$('.button').click(popup_modal);
$('#buttonConfirm').click(popup_confirme);
}());
Technically all JavaScript functions are closures as they are objects with a scope chain attached to them. A closure is simply the combination of a function object and a scope (a set of variable bindings).
Scope is actually pretty simple really. Javascript uses lexical scoping which means that function are executed in the variable scope that was in effect when they were defined. Simply put, An outer function cannot read a value from an inner function unless is is specifically returned. An inner function can read all values declared in an outer function.
When most people talking about closures they are actually referring to the act of returning an item from an inner nested function to the outer function in which it has been defined.
e.g
// I am the outer function.
function outer (){
var outerVariable = "I am available to inner functions.";
// I am an inner function. I was declared in the scope of the outer
// function and as such all the variables declared in that scope are
// available to me.
function inner (){
// This will return => "I am available to inner functions." as we can
// read the outer declaration.
var innerReadValue = outerVariable;
// This will be available only to the inner function as it is
// not returned.
var privateVariable = "I am private";
// This will be available to the outer function as we are returning it
// on the next line.
var publicVariable = "I am available to outer functions";
// Make publicVariable public. This is what most people refer to
// when talking about closures.
return publicVariable;
}
// Read the inner functions publicVariable declaration.
// Returns => "I am available to outer functions"
var outerReadValue = inner();
}
In your example you are trying to get a value that was declared and not returned on the inner scope. As you should understand by now, this is invisible to the outer function so cannot work.
This can be rewritten as such:
// This is called an Immediately Invoked Function Expression. IIFE, It
// basically wraps your code in a function hiding all internal declarations
// from the global scope and then invokes it. You don't want to pollute the
// global scope.
(function(){
// Declare this outside so all functions can read it.
var int_val = 0;
// Declare this outside so all functions can read it.
var popup_confirm = function(){
// "int_val" is available here.
return int_val;
};
// Although your function runs automatically, we delay binding until
// the DOM is ready.
$(document).ready(function(){
$("#buttonConfirm").click(function(){
// Provide feedback. "popup_confirm" is available here
// since is declared in the outer scope.
return popup_confirm();
});
$(".button").click(function(){
// Set the value of int_val that has been declared in the outer
// scope.
int_val = $(this).val() === "yes" ? 1 : 0;
});
});
}());
Hopefully this makes it all a little bit more clear to you.

Javascript setTimeout function with 'this' [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
setTimeout and “this” in JavaScript
I am trying to put a timeout on an Object. With some test code (see below) I want to decrease the timerPos until it reaches 0. When I use the code below the first time timerInc() is called by startTimer(), it will reach 3 (as expected). When TimerInc() is called by the timeout i will receive 'undefined' for the timerPos variable. What am I doing wrong?
function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
this.timerMinutes = timer;
this.timerPos = 0;
this.startTimer = function() {
this.timerPos = this.timerMinutes+1;
this.timerInc();
};
this.timerInc = function() {
if (this.timerPos > 0){
this.timerPos--;
// first time this function gets called timerPos is 3
// the second time when its called by the timeout it
// will be 'undefined'
setTimeout(this.timerInc,1000);
}
};
}
(using this.timerInc() in the timeout instead of this.timerInc does not work for me, neither does using quotes)
You need to bind the "this" variable to another one that you use explicitly since the value of "this" changes based on who is calling the function!
function Alert(timer) {
var that = this; // Store this Alert instance as "that".
this.timerMinutes = timer;
this.timerPos = 0;
// ...
this.timerInc = function() {
// Use the Alert instance "that", not whatever is bound to "this" at runtime.
if (that.timerPos > 0){
that.timerPos--;
setTimeout(that.timerInc, 1000);
}
};
}
The issue is that the setTimeout() function will call its function argument from global scope, not the scope of the enclosing object at the time it is registered. So in global scope the "this" variable is bound to the "global" object (likely the browser window).
You can verify like so:
setTimeout(function(){alert(this);}, 500); // => alerts "[object DOMWindow]"
First of all you should use prototype to declare the methods of your class Alert. And changing the scope of the function you're calling is gonna do the job:
function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
this.timerMinutes = timer;
this.timerPos = 0;
}
Alert.prototype.startTimer = function() {
this.timerPos = this.timerMinutes+1;
this.timerInc();
};
Alert.prototype.timerInc = function() {
if (this.timerPos > 0){
this.timerPos--;
console.log(this.timerPos);
setTimeout(function(_this){_this.timerInc()},1000,this);
}
};
DEMO: http://jsfiddle.net/kmendes/HNYKa/1/

Categories

Resources