How to properly scope function to run on delay in Polymer? - javascript

I am trying to add the input data into an array delayed for 2 seconds after the last keystroke. However, when I run this I get the following error: Uncaught TypeError: this._validateInput is not a function
How can I properly scope this._validateInput() to run on delay?
I tried let func = this._validateInput();, but that seems to run the function every time that func is set.
Also, the on-change input handler only fires when the input loses focus.
Looking for away to solve this...
<paper-input id="itemId" on-input="_autoAddToArray"></paper-input>
...
_validateInput () {
console.log('validate input');
}
_autoAddToArray () {
let timeout = null;
clearTimeout(timeout);
timeout = setTimeout(function () {
this._validateInput();
}, 2000);
}

Either use a lambda:
setTimeout(
() => this._validateInput(),
2000
);
or bind the function
setTimeout(this._validateInput.bind(this), 2000);
Either solution should work
The lambda works because it doesn't have its own scope.
The binding works because it applies the scope "before" running it so to speak

The this keyword always refers to the this of the current scope, which changes any time you wrap something in function() { ... }
You need to assign your this in the outer scope to a variable.
var self = this;
timeout = setTimeout(function () {
self._validateInput();
}, 2000);
Reference: setTimeout scope issue

<paper-input id="itemId" on-input="_autoAddToArray"></paper-input>
...
_autoAddToArray () {
let timeout = null;
clearTimeout(timeout);
let that = this;
timeout = setTimeout(function () {
that._validateInput();
}, 2000);
}
_validateInput () {
if(this.$.itemId.value) {
// do something
}
}

Related

Delay eventListener

In JavaScript, I have an element (which is an input tag).
This code :
element.addEventListener("focus", function () {
this.parentNode.parentNode.style.outline = this.parentNode.parentNode.dataset.ans_outline;
});
When the input is focused, outline is changed immediately.
My question is : how could I delay this event ?
I've tried :
element.addEventListener("focus", function () {
setTimeout(function(node) {
node.parentNode.parentNode.style.outline = node.parentNode.parentNode.dataset.ans_outline;
}(this), 1000)
});
.. But it doesn't work :(
try this:
element.addEventListener("focus", function () {
var node = this;
setTimeout(function() {
node.parentNode.parentNode.style.outline = node.parentNode.parentNode.dataset.ans_outline;
}, 1000)
});
First argument of setTimeout function is function you want to execute (do not call this function directly).
You can store reference to this in node variable and then use it inside your timed out function (see closures)
Remove the reference to the this and give it this way:
element.addEventListener("focus", function () {
$this = this;
setTimeout(function() {
$this.parentNode.parentNode.style.outline = $this.parentNode.parentNode.dataset.ans_outline;
}, 1000)
});

Why does setInterval initiate when I'm only assigning it?

I'm assigning to a variable, a function that uses setInterval, but I don't want the function to run until I call it. However, the function is running from just the assignment statement.
sessionClock = setInterval(function() {
console.log("Hi")
}, 1000)
I have also tried like this:
sayHi = function() {
console.log("Hi");
}
var sayHiStarter = setInterval(sayHi, 1000);
Both of these initiate the function and will log "Hi" to the console.
Why is it running on assignment? And what can do I do fix this?
If you only want to bind a function to setInterval, but call it later, you can use bind:
var sessionClock = setInterval.bind(null, function() {
console.log("Hi")
}, 1000);
//... later
var myInterval = sessionClock(); // start the timer
// ... later if you need to clear it
clearInterval(myInterval);
In principle, bind returns a new function that calls your original function (in this case, setInterval) with predefined arguments. So when you call sessionClock, that returned function is called. There a other aspects to bind, but they don't seem to apply in this context.
The call to setInterval does not return a function, but an identification for the created interval. This id is used to remove the interval when you don't want it to execute anymore:
sessionClock = setInterval(function() {
console.log("Hi")
}, 1000)
...
clearInterval(sessionclock);
What you want is something like this:
sessionClock = function () {
return setInterval(function() {
console.log("Hi")
},
1000);
}
//When needed
var intervalId=sessionClock();

How to clear setTimeout inside Javascript Object?

I have an object that I have a few functions inside that I am using setTimout inside. I'm trying to clear the timeout using clearTimeout.. but I'm not hitting it right.
var ExpireSession = {
killSession: function () {
var TESTVAR2 = setTimeout(function () {
window.location.href = "error/expired.aspx";
}, 15000);
},
stopTimers: function (){
clearTimeout(ExpireSession.killSession.TESTVAR2)
}
}
Before 15 seconds I am triggering: ExpireSession.stopTimers(); but it does not stop it. Any ideaas what I am doing wrong here?
var TESTVAR2 is a variable that is local to the function it is declared within. It is not a property of an object.
If you want to access it as a property of an object, then you must define it as such:
ExpireSession.killSession.TESTVAR2 = setTimeout(function () {
(You might be able to make use of this depending on how you call the function).
Because JavaScript has functional scope, TESTVAR2 will only be defined within killSession. To reference it, you can set it as a property of ExpireSession:
killSession: function () {
this._TESTVAR2 = setTimeout(function () {
window.location.href = "error/expired.aspx";
}, 15000);
},
stopTimers: function () {
clearTimout(this._TESTVAR2);
}

Referencing Non-Global Variable for Timer JS

I have this function.
function changeFrame(){
var time = setInterval(start, 250);
}
and I want to stop it from firing in another function, but haven't been able to figure out how to do it.
Do you mean this?
function changeFrame(){
var time = setInterval(function() {
// Do stuff
}, 250);
}
Think it's in the comments.
Ok amended the fiddle to do what you want. I made time a global var. Call clearInterval in stop with the global var http://jsfiddle.net/QNWF4/3/
In order to call clearInterval you need to have the handle returned by setInterval. That means something will either be global to the page or global to a containing function in which your script resides.
function Timer()
{
var handle = null;
this.start = function (fn,interval) {
handle = setInterval(fn,interval);
};
this.stop = function ()
{
if (handle) { clearInterval(handle); handle = null; }
};
return this;
}

setTimeout() problems on IE 9

I have a simple js structure like this :
var Waiting = (function () {
function Waiting() {
this.timer;
}
Waiting.prototype.show = function () {
var self = this;
clearTimeout( self.timer );
self.timer = setTimeout( function(){ self.hideLogo(); },3000);
}
Waiting.prototype.hideLogo = function () {
console.log("ok i passed timeout");
};
return Waiting;
})();
As expected, I get the "ok i passed timeout" log on every browser the first time I execute the show function (which called the hideLogo one). The problem appears in IE9 when I called for the second time the show function. This time, the hideLogo function is never called (log never appears in IE console). I tried a lot of things without any success.
If anyone as an idea...
When you're using setTimeout, the function that is being called looses the context: in other words this doesn't post to the instance on which the method is called anymore. You're using self to cancel this issue out, but self is, itself, an iffy word (as in reserved keyword). Perhaps use that, and use an IIFE in the setTimeout call:
this.timer = setTimeout((function (that)
{
return function()
{
clearTimeout(that.timer);//perhaps clear timeout here?
that.hideLogo.apply(that,[]);//double dutch, the apply _shouldn't_ be required
};
}(this)), 3000);
At first glance, that's the only thing I can see that might be the issue with your code: the clearTimeout call shouldn't be an issue, but I like to call it at the end of the timeout itself, and the self ambiguity thing. Let me know if this changes anything for you!
I am not really sure how you'd call show the second time with the code provided, maybe you create a new Waiting()?
Here is what worked for IE8
var Waiting=(function () {
function Waiting() {
this.timer;
}
Waiting.prototype.show = function () {
var self = this;
console.log("will clear pref timeout");
clearTimeout( self.timer );
self.timer = setTimeout(
function(){
self.hideLogo();
},30);
}
Waiting.prototype.hideLogo = function () {
console.log("ok i passed timeout");
};
return new Waiting();
})();
// shows only one time
Waiting.show();
Waiting.show();
// next one will show because it lets the prefious one
// finish without clearing the pref timeout.
setTimeout(function(){
Waiting.show();
},1000);
Try:
setTimeout( function(){
clearTimeout( that.timer );
that.hideLogo();
},3000);
Worked for me on IE and Chrome. IE is very behind on everything.

Categories