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/
Related
I know how to execute a function once, this is not the question
First, this is my code
var executed1 = false;
var executed2 = false;
var executed3 = false;
function myFunction()
{
if(-------------------)
{
//Verification - If the others conditions have ever been called
if (executed2)
{
executed2 = false;
}
else if(executed3)
{
executed3 = false;
}
//Verification - If the condition have ever been called during this condition = true;
if (!execution1)
{
execution1 = true;
//My code here ...
}
}
else if (-------------------)
{
if (executed1)
{
executed1 = false;
}
else if(executed3)
{
executed3 = false;
}
if (!execution2)
{
execution2 = true;
//My code here ...
}
}
else if (-------------------)
{
//Same thing with execution3
}
}
setInterval("myFunction()", 10000);
I'll take the first condition, for example
(1) If the condition is true, I want to execute my code but only the first time : as you can see, my function is executed every 10s. As long as the first condition is true, nothing should append more.
If the first condition becomes false and the second condition true, it’s the same process.
But now, If the first condition ever been true and false, I would like that if the condition becomes true again, it will be the same thing that (1)
Is there any way to read a cleaner code to do that ?
Because, now there are only 3 conditions, but there may be 100.
use clearInterval to stop execution your function and one if to check conditions
var fid = setInterval(myFunction, 1000);
var cond = [false,false,false];
function myFunction()
{
console.log(cond.join());
// check conditions in some way here (e.g. every is true)
if(cond.every(x=>x)) {
clearInterval(fid);
console.log('Execute your code and stop');
}
// change conditions (example)
cond[2]=cond[1];
cond[1]=cond[0];
cond[0]=true;
}
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.
This is what I'd like to do:
User clicks on button, Run Function A
If button hasn't been clicked again within 1 second, Run Function B too
If button has been clicked, repeat (run function A again and check for function B)
This is what I've tried
var clicked = false;
$('#button').click(function(){
A();
});
function A(){
clicked = true;
setTimeout(function(){
clicked == false;
)}, 1000);
setTimeout(function(){
if ( clicked == false ) {
B();
}
)}, 1000);
}
I think the code will for scenario 1 and 2, but how can I get it working for 3 too?
EDIT: Just saw a related SO question upon posting which I didn't find through search. Please wait while I check if it's a duplicate
I think you are looking to throttle (buffer) the clicks, that is, you want to wait a specified amount of time before you act, if the same event happens again within your throttling period, you restart your wait. http://jsfiddle.net/8QdLV/
function B() {
console.log('Clicked')
}
var timeoutId;
$('#button').click(function() {
clearTimeout(timeoutId);
timeOutId = setTimeout(B, 1000);
});
This can be generalized http://jsfiddle.net/8QdLV/
function throttle(handler, buffer) {
var timeoutId;
buffer = buffer || 1000;
return function(e) {
clearTimeout(timeoutId);
var me = this;
timeoutId = setTimeout(function() {
handler.call(me, e);
}, buffer);
}
}
$('button').click(throttle(function() {
console.log('Throttled click');
});
By the way, you may want to use https://code.google.com/p/jquery-debounce/ which also provides a $.throttle function
use the setInterval function.
note that it doesn't suffice to record the click with a boolean, otherwise two clicks at t=0, t=0.99 will both be cleared by the reset operation at t=1.
var clicked = false
, hnd_reset = null
, hnd_check = null;
$('#button').click(function() {
A();
});
function A(){
clicked = true;
hnd_reset = setTimeout(function(){
clicked = false;
hnd_reset = null;
)}, 1000);
if (hnd_check === null) {
hnd_check = setInterval(function(){
if ( !clicked && (hnd_reset === null)) {
clearInterval( hnd_check );
hnd_check = null;
B();
}
)}, 1000);
}
}
alternatively you could track the number of clicks in an int starting at 0, allowing for execution of B iff the tracker is 0.
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
}
}
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.