How to disable a click event handler for particular time? - javascript

Only JavaScript, No jquery.
Code goes like:
window.onload = addListeners;
function addListeners(){
for(var i = 0 ; i < document.getElementsByClassName('arrow').length; i++){
if(window.addEventListener){
document.getElementsByClassName('arrow') [i].addEventListener( 'click', func , false);
}else{
document.getElementById('arrow') [i].attachEvent('onclick' , func);
}
}
}
function func(){
//Takes exactly 5 seconds to execute
}
Now, I want to disable the 'click' for 5 seconds when the function 'func()' is running. And, then after the 'func()' is completely executed, the click should again be enabled automatically.
How to do this only using JavaScript?

Rather than disable the click event, check a variable to see if its currently running.
var funcRunning = false;
function func(){
if (funcRunning) return;
funcRunning = true;
//Function logic here
funcRunning = false;
return //whatever
}
This way your not guessing the function will take 5 seconds to run, the function will simply not execute its logic until its completed its current run.
EDIT: As #NULL has suggested, a better method would be to store the boolean variable on the function itself to prevent global pollution:
function func(){
if (func.IsRunning) return;
func.IsRunning = true;
//Function logic here
func.IsRunning = false;
return //whatever
}

To elaborate my comments on Curts answer:
When declaring the function func you can do two things:
function func() {
if ( !func.isRunning ) {
func.isRunning = true;
/* logic goes here */
func.isRunning = false;
}
}
Or you can make a closure and store isRunning inside it:
var func = (function() {
var isRunning = false;
return function() {
if ( !isRunning ) {
isRunning = true;
/* logic goes here */
isRunning = false;
}
};
})();
The second example can makes a private variable only accessible inside the closure.
Its mostly about a design pattern some developers doesn't like to store variables directly on functions like in example one. The only difference is that if someone chooses to set func.isRunning = true the function cannot run again and therefore not reset itself.

If your function is asynchronous (it sends ajax request, as far as I understood), you'd better create a "success" callback for that request and handle funcRunning flag there.
Here is an example:
var funcRunning = false;
function func() {
if (funcRunning) {
return;
}
funcRunning = true;
var xmlhttp = new XmlHttpRequest();
xmlhttp.open('GET', '/xhr/test.html', true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
// do something.
funcRunning = false;
}
}
};
}
P.S. Current example is not the most correct in creating XmlHttpRequest instance (not crossbrowser). It is shown only as an example.

Related

Reducing function name usage within function

When I search for a function name - it gets clumsy when I see plenty of function names as in the example. In large code base I waste my time when searching for how and from where a function has been called :
function do_something()
{
if (typeof do_something.flag == "undefined")
{
do_something.flag = true;
}
if (do_something.flag == null)
{
do_something.flag = true;
}
}
Here when I search for do_something so that I can look from where it is called instead I find plenty of lines consisting of do_something.flag1,do_something.flag2 and so on which isn't of any use in most of such searches. In large function I get plenty of such lines occupying search output.
I've another scenario. In (Netbeans) IDE I want to do Ctrl-F do_something function looking for where it is called in the file. Now I find pressing F3 within the function itself iterating over it's own lines containing something like do_something.var1=5 etc.
In short is there any way to reduce the function name usage within the function when creating object-global variables?
I've much longer functions but I'll give real example of medium level function causing this problem:
function slow_down_clicks(label, userfunc, timeinmsec)
{
console.log("slow_down_clicks=" + label);
if (typeof slow_down_clicks.myobj == UNDEFINED)
{
slow_down_clicks.myobj = {};
}
if (typeof slow_down_clicks.myobj[label] == UNDEFINED)
{
slow_down_clicks.myobj[label] = {
inqueue: false,
lastclickedtime: 0,
login_post_error_count: 0
};
}
var myfunc = function ()
{
console.log("Executing the user func");
slow_down_clicks.myobj[label].inqueue = false;
slow_down_clicks.myobj[label].lastclickedtime = new Date().getTime();
userfunc();
}
console.log("Due to error in home.aspx reloading it", ++slow_down_clicks.myobj[label].login_post_error_count);
if (slow_down_clicks.myobj[label].inqueue == false)
{
var diff = new Date().getTime() - slow_down_clicks.myobj[label].lastclickedtime;
console.log("diff=", diff, timeinmsec);
if (diff > timeinmsec)
{
myfunc(); //click login
}
else
{
console.log("queuing the request after:", timeinmsec - diff);
slow_down_clicks.myobj[label].inqueue = true;
setTimeout(function ()
{
console.log("called myfunc babalatec");
myfunc();
}, timeinmsec - diff);
}
}
else
{
console.log("Discarding this request...");
}
}
I think you can just define the fields as normal variables and put your code in its own file. Then you can just refer to the variables by its name inside your function because they are within the function's closure. The variables will not be accessible outside because you limit them in its own file.
like:
let flag = false
function doSomething () {
if (!flag) {
flag = true
}
....
}
Put the above code snippet in a separate file and import the function when you want to use it.

alert once within loop setInterval or requestAnimationFrame, javascript

This is an small snipped of a game developed in javascript.
It has a main function that loops infinitely.
PROBLEM
I want a single alert to show up when the character dies, otherwise it appears thousands of alerts due to the loop
characterDead = false;
function colision(){
//if colision > true
charactedDead = true;
alert("the character died")
}
function main(){
//...other functions
colision();
requestAnimationFrame(main);
}
window.onload = function() {main();};
You need a characterDead check in colision().
Also, you have a typo - "charactedDead" should be "characterDead" in the same function :)
var characterDead = false;
function colision() {
if (!characterDead) { // check if the character is dead already
characterDead = true; // kill it
console.log("the character died"); // alert or log this
}
}
function main() {
//...other functions
colision();
requestAnimationFrame(main);
}
window.onload = function() {
main();
};

How can I get my anonymous JavaScript function to execute withing the calling scope?

I'm trying to make a generic error message function that I can use within any JavaScript function. This function would test for certain validity and stop the calling function dead-cold if it fails.
For example:
var fun = function() {
var a = {};
a.blah = 'Hello';
checkIfExistErrorIfNot(a); // fine, continue on...
checkIfExistErrorIfNot(a.blah); // fine, continue on...
checkIfExistErrorIfNot(a.notDefined); // error. stop calling method ("fun") from continuing
console.log('Yeah! You made it here!');
}
This was my first stab at it:
var checkIfExistErrorIfNot(obj) {
var msg = 'Object does not exist.';
if(!obj) {
return (function() {
console.log(msg);
return false;
})();
}
return true;
}
The returning anonymous function executes just fine. But the calling function still continues. I'm guessing it's because the anon function does not execute in the scope of the calling function.
Thanks.
EDIT
I may not have made my intentions clear. Here is what I normally do in my methods:
saveData: function() {
var store = this.getStore();
var someObj = this.getOtherObject();
if(!store || !someObj) {
showError('There was an error');
return false; // now, 'saveData' will not continue
}
// continue on with save....
}
This is what I'd like to do:
saveData: function() {
var store = this.getStore();
var someObj = this.getOtherObject();
checkIfExistErrorIfNot(store);
checkIfExistErrorIfNot(someObj);
// continue on with save....
}
Now, what would be even cooler would be:
...
checkIfExistErrorIfNot( [store, someObj] );
...
And iterate through the array...cancelling on the first item that isn't defined. But I could add the array piece if I can find out how to get the first part to work.
Thanks
You can use exceptions for that:
var checkIfExistErrorIfNot = function (obj) {
var msg = 'Object does not exist.';
if(!obj) {
throw new Error(msg);
}
}
var fun = function() {
var a = {};
a.blah = 'Hello';
try {
console.log('a:');
checkIfExistErrorIfNot(a); // fine, continue on...
console.log('a.blah:');
checkIfExistErrorIfNot(a.blah); // fine, continue on...
console.log('a.notDefined:');
checkIfExistErrorIfNot(a.notDefined); // error. stop calling method ("fun") from continuing
} catch (e) {
return false;
}
console.log('Yeah! You made it here!');
return true;
}
console.log(fun());

best way to toggle between functions in javascript?

I see different topics about the toggle function in jquery, but what is now really the best way to toggle between functions?
Is there maybe some way to do it so i don't have to garbage collect all my toggle scripts?
Some of the examples are:
var first=true;
function toggle() {
if(first) {
first= false;
// function 1
}
else {
first=true;
// function 2
}
}
And
var first=true;
function toggle() {
if(first) {
// function 1
}
else {
// function 2
}
first = !first;
}
And
var first=true;
function toggle() {
(first) ? function_1() : function_2();
first != first;
}
function function_1(){}
function function_2(){}
return an new function
var foo = (function(){
var condition
, body
body = function () {
if(condition){
//thing here
} else {
//other things here
}
}
return body
}())`
Best really depends on the criteria your application demands. This might not be the best way to this is certainly a cute way to do it:
function toggler(a, b) {
var current;
return function() {
current = current === a ? b : a;
current();
}
}
var myToggle = toggler(function_1, function_2);
myToggle(); // executes function_1
myToggle(); // executes function_2
myToggle(); // executes function_1
It's an old question but i'd like to contribute too..
Sometimes in large project i have allot of toggle scripts and use global variables to determine if it is toggled or not. So those variables needs to garbage collect for organizing variables, like if i maybe use the same variable name somehow or things like that
You could try something like this..: (using your first example)
function toggle() {
var self = arguments.callee;
if (self.first === true) {
self.first = false;
// function 1
}
else {
self.first = true;
// function 2
}
}
Without a global variable. I just added the property first to the function scope.
This way can be used the same property name for other toggle functions too.
Warning: arguments.callee is forbidden in 'strict mode'
Otherwise you may directly assign the first property to the function using directly the function name
function toggle() {
if (toggle.first === true) {
toggle.first = false;
// function 1
}
else {
toggle.first = true;
// function 2
}
}

calling the same function multiple times while clicking

I have a function which accepts a string and outputs it one character at a time with a delay. The event occurs when the user clicks a link or button. The problem is that if the user clicks a link and then another before the first one is done, they both run at the same time and output to the screen. It becomes jumbled up.
ex:
string1 : "i like pie very much"
string1 : "so does the next guy"
output : i sloi kdeo epse .... and so on.
Anyone know a method to fix this?
I think I need a way to check if the function is being processed already, then wait till it is done before starting the next.
Place both functions inside an object (because globals are bad), add a variable to the object which knows if a function is executing, and check the variable, like this:
var ns = {
isExecuting:false,
func1: function(){
if (this.isExecuting) { return; }
this.isExecuting = true;
//do stuff 1
this.isExecuting = false;
},
func2: function(){
if (this.isExecuting) { return; }
this.isExecuting = true;
//do stuff 2
this.isExecuting = false;
}
}
and for extra elegance:
var ns = {
isExecuting:false,
executeConditionally:function(action){
if (this.isExecuting) { return; }
this.isExecuting = true;
action();
this.isExecuting = false;
}
func1: function(){
this.executeConditionally(function(){
//stuff
})
},
func2: function(){
this.executeConditionally(function(){
//stuff
})
}
}
add a variable globally or in scope outside the method called IsProcessing and set it to true the first time the method is called, on the method you can then just check if (IsProcessing) return false;
All you need to do is set a variable that indicates whether the function is running:
var isRunning = false;
$('a').click(function({
if(isRunning == false){
isRunning = true;
///Do stuff
isRunning = false;
}
else{
return false;
}
});
Don't you want all the clicks to be taken into account, but in order ?
If so, I suggest you separate streams between adding a click to process, and consuming clicks
:
the html :
<a class="example" href="javascript:void(0)" onclick="delayPushLine();">i like pie very much</a><br/>
<a class="example" href="javascript:void(0)" onclick="delayPushLine();">so does the next guy</a>
<div class="writeThere"></div>
and the javascript (using jQuery a bit)
var charDisplayDelay = 50; // the time between each char display
var displayDelay = 2000; // the time before a click is handled
var lines = [];
var lineIdx = 0, pos = 0;
function delayPushLine(e) {
if (!e) {
e = window.event
}
setTimeout(function() { lines.push(e.srcElement.innerText); }, displayDelay);
}
function showLines () {
if (lines.length > lineIdx) {
if (pos < lines[lineIdx].length) {
$(".writeThere").append(lines[lineIdx].substr(pos,1));
pos++;
} else {
pos = 0;
lineIdx++;
$(".writeThere").append("<br/>");
}
}
}
setInterval("showLines()", charDisplayDelay);
http://jsfiddle.net/kD4JL/1/

Categories