how to execute second method only after first method is executed - javascript

I want to print a heading tag only after a paragraph tag is loaded. Below is my Javascript code. See the plunker for more clarification: http://embed.plnkr.co/aheHkSQUBft5A4Z3wkie/preview
function changeText(cont1, cont2, speed){
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30);
clearInterval(Otimer);
});
$(document).ready(function() {
changeText($("h2"), $(".h2"), 30);
clearInterval(Otimer);
});

I would do something like this (please not that ES6 Promises aren't supported by Internet Explorer, but there are shims to use Promises with old browsers too).
You'll have to fill out the parts commented to get it to work though:
var Otimer;
/*#TODO: refactor show() function to use ES6 Promises (eventually with shims) */
function show(Ocontent) {
var i = 0;
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
if (Otimer === undefined) {
Otimer = setInterval(show, speed); // Remember to fulfill the promise and remove the interval once it's finished
}
// return the promise
};
function changeText(p1, p2, speed) {
var Otext = p1.text();
var Ocontent = Otext.split("");
return show(Ocontent);
};
$(function () {
changeText($("p"), $(".p2"), 30).then(function() { // We call changeText the second time after the promise return by changeText() is fulfilled and the show() function has finished
Otimer = undefined;
changeText($("h2"), $(".h2"), 30);
});
});

first of all, variable declaring inside of function is scoped variable, which You cannot access from outside of the function.
so the line clearInterval(Otimer); never works.
the code below is fixed code of the scope issue and using callback to implement what you want.
function changeText(cont1, cont2, speed, cb) {
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i++;
}else{
clearInterval(Otimer)
if(cb) cb()
}
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30, function(){
changeText($("h2"), $(".h2"), 30);
});
});
http://plnkr.co/edit/xowItFUWqI79obi4ZVNV?p=preview

Related

Change a function's properties each time it's executed in Javascript

I'm willing to create a function that changes payhighx() into paylowx() and paylowx() into payhighx() each time one of the two is executed. I thought of an if statement going into the roll() function that'd check whether payhighx()/paylowx() was executed and change their properties if the returned value is True. I tried researching something related to my problem, but couldn't find anything useful in terms of JQuery and Javascript.
var start = 0.01
var $input = $("#oddsInput")
var $odds = $("#oddsOverUnder")
var $button = $("#roll")
var $bet = $("#bet")
var $pay = $("#oddsPayout.btn.btn-primary.btn-xlg.btn-block")
function paylowx() {
$pay.click()
document.getElementById("oddsInput").value = "1.2";
$odds.click()
}
function payhighx() {
$pay.click()
document.getElementById("oddsInput").value = "5.2";
$odds.click()
}
function roll() {
$bet.val(start)
$button.click()
setTimeout(function() {
var tr = document.querySelector("#myBetsTable tr:nth-child(2)")
var cls = tr.getAttribute('class')
if (cls === 'success'){
}
else{
payhighx()
}
$button.click();
setTimeout(function()
{
$button.click();
},1000);
},1000);
}
setInterval(roll, 2000)

Javascript element.style.opacity is undefined. Why?

I am trying to make a JS function that flickers an element. I use a setInterval() for timing, but it gives the error message Uncaught TypeError: Cannot read property 'opacity' of undefined.
When I try to modify the opacity not with a timer, but "by hand", that works...
What am I doing wrong?
Usage:
document.getElementById('idOfTheElement').startFlicker();
The function:
Element.prototype.startFlicker = function() {
var blinkInterval = setInterval(function() {
if (parseInt(this.style.opacity) === 0) {
this.style.opacity = 1;
} else {
this.style.opacity = 0;
}
}, 50);
};
Try this
Element.prototype.startFlicker = function() {
var self = this;
var blinkInterval = setInterval(function() {
if (parseInt(self.style.opacity) === 0) {
self.style.opacity = 1;
} else {
self.style.opacity = 0;
}
}, 50);
};
In setInterval this refers to window, you need store context (this - current element) in variable and use in setInterval
Because of the context. this.style inside the setInterval refers to the global window object.
You could always make a reference to the element itself, because inside the setInterval function, the window object is passed as this.
Instead, you should give .bind() a try. So this will be a reference to the argument of the method.
Element.prototype.startFlicker = function() {
var blinkInterval = setInterval(function() {
if (parseInt(this.style.opacity) === 0) {
this.style.opacity = 1;
} else {
this.style.opacity = 0;
}
}.bind(this), 50);
};

setInterval() with a count

If possible I'd like to use to remove count and use an argument in self.addOrbitTrap(). At the moment for testing my code does something like this:
Bbrot.prototype.findMSet = function() {
//...code
var self = this;
canvasInterval = setInterval(function() {
self.addOrbitTrap();
}, 0);
}
var count = 0;
Bbrot.prototype.addOrbitTrap = function() {
//...code
if (count === 100) {
// Call a different function. That's why I use count
}
count++;
}
Edit: To be more specific, count is used in my code to count how many times addOrbitTrap() successfully runs (it does not add an orbit trap if a randomly selected pixel is a part of the Mandelbrot Set). After it runs some number of times, I call a different function (from within addOrbitTrap()). I would rather not use a global variable because count is not used anywhere else.
You could introduce count as a local variable inside findMSet that you pass to addOrbitTrap(); at each interval the value will be increased:
Bbrot.prototype.findMSet = function() {
//...code
var self = this,
count = 0;
canvasInterval = setInterval(function() {
self.addOrbitTrap(++count);
}, 0);
}
Handling the value is simple:
Bbrot.prototype.addOrbitTrap = function(count) {
//...code
if (count === 100) {
// Call a different function. That's why I use count
}
}
just make the variable on the object and use it.
Bbrot.prototype.count = 0;
Bbrot.prototype.findMSet = function() {
//...code
var self = this;
canvasInterval = setInterval(function() {
self.addOrbitTrap();
}, 0);
}
Bbrot.prototype.addOrbitTrap = function() {
if(ranSuccessful)
this.count++;
}
Bbrot.prototype.someOtherFunc = function() {
return this.count;
}

countdown timer stops at zero i want it to reset

I am trying to figure out a way to make my countdown timer restart at 25 all over again when it reaches 0. I dont know what I am getting wrong but it wont work.
Javascript
window.onload = function() {
startCountDown(25, 1000, myFunction);
}
function startCountDown(i, p, f) {
var pause = p;
var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
//write out count
countDownObj.innerHTML = i;
if (i == 0) {
//execute function
fn();
//stop
return;
}
setTimeout(function() {
// repeat
countDownObj.count(i - 1);
},
pause
);
}
//set it going
countDownObj.count(i);
}
function myFunction(){};
</script>
HTML
<div id="countDown"></div>
try this, timer restarts after 0
http://jsfiddle.net/GdkAH/1/
Full code:
window.onload = function() {
startCountDown(25, 1000, myFunction);
}
function startCountDown(i, p, f) {
var pause = p;
var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
// write out count
countDownObj.innerHTML = i;
if (i == 0) {
// execute function
fn();
startCountDown(25, 1000, myFunction);
// stop
return;
}
setTimeout(function() {
// repeat
countDownObj.count(i - 1);
}, pause);
}
// set it going
countDownObj.count(i);
}
function myFunction(){};
​
I don't see you resetting the counter. When your counter goes down to 0, it executes the function and return. Instead, you want to execute the function -> reset the counter -> return
You can do this by simply adding i = 25 under fn() :
function startCountDown(i, p, f) {
var pause = p;
var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
// write out count
countDownObj.innerHTML = i;
if (i == 0) {
// execute function
fn();
i = 25;
// stop
return;
}
setTimeout(function() {
// repeat
countDownObj.count(i - 1);
},
pause
);
}
// set it going
in #Muthu Kumaran code is not showing zero after countdown 1 . you can update to this:
if (i < 0) {
// execute function
fn();
startCountDown(10, 1000, myFunction);
// stop
return;
}
The main reason for using setInterval for a timer that runs continuously is to adjust the interval so that it updates as closely as possible to increments of the system clock, usually 1 second but maybe longer. In this case, that doesn't seem to be necessary, so just use setInterval.
Below is a function that doesn't add non–standard properties to the element, it could be called using a function expression from window.onload, so avoid global variables altogether (not that there is much point in that, but some like to minimise them).
var runTimer = (function() {
var element, count = 0;
return function(i, p, f) {
element = document.getElementById('countDown');
setInterval(function() {
element.innerHTML = i - (count % i);
if (count && !(count % i)) {
f();
}
count++;
}, p);
}
}());
function foo() {
console.log('foo');
}
window.onload = function() {
runTimer(25, 1000, foo);
}

Looping functions with timeout

I want to have two functions (an animation downwards and animation upwards) executing one after the other in a loop having a timeout of a few seconds between both animations. But I don't know how to say it in JS …
Here what I have so far:
Function 1
// Play the Peek animation - downwards
function peekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-150px";
tile2.style.top = "-150px";
peekAnimation.execute();
}
Function 2
// Play the Peek animation - upwards
function unpeekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "0px";
tile2.style.top = "0px";
peekAnimation.execute();
}
And here's a sketch how both functions should be executed:
var page = WinJS.UI.Pages.define("/html/updateTile.html", {
ready: function (element, options) {
peekTile();
[timeOut]
unpeekTile();
[timeOut]
peekTile();
[timeOut]
unpeekTile();
[timeOut]
and so on …
}
});
You can do this using setTimeout or setInterval, so a simple function to do what you want is:
function cycleWithDelay() {
var delay = arguments[arguments.length - 1],
functions = Array.prototype.slice.call(arguments, 0, arguments.length - 1),
pos = 0;
return setInterval(function () {
functions[pos++]();
pos = pos % functions.length;
}, delay);
}
Usage would be like this for you:
var si = cycleWithDelay(peekTile, unpeekTile, 300);
and to stop it:
clearInterval(si);
This will just cycle through the functions calling the next one in the list every delay msec, repeating back at the beginning when the last one is called. This will result in your peekTile, wait, unpeekTile, wait, peekTile, etc.
If you prefer to start/stop at will, perhaps a more generic solution would suit you:
function Cycler(f) {
if (!(this instanceof Cycler)) {
// Force new
return new Cycler(arguments);
}
// Unbox args
if (f instanceof Function) {
this.fns = Array.prototype.slice.call(arguments);
} else if (f && f.length) {
this.fns = Array.prototype.slice.call(f);
} else {
throw new Error('Invalid arguments supplied to Cycler constructor.');
}
this.pos = 0;
}
Cycler.prototype.start = function (interval) {
var that = this;
interval = interval || 1000;
this.intervalId = setInterval(function () {
that.fns[that.pos++]();
that.pos %= that.fns.length;
}, interval);
}
Cycler.prototype.stop = function () {
if (null !== this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
Example usage:
var c = Cycler(peekTile, unpeekTile);
c.start();
// Future
c.stop();
You use setInterval() to call unpeekTile() every 1000 milliseconds and then you call setTimeOut() to run peekTile() after 1000 milliseconds at the end of the unpeekTile() function:
function peekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-150px";
tile2.style.top = "-150px";
peekAnimation.execute();
}
function unpeekTile() {
/* your code here */
setTimeout(peekTile, 1000);
}
setInterval(unpeekTile, 1000);
Check out the fiddle
var animation = (function () {
var peekInterval, unpeekInterval, delay;
return {
start: function (ip) {
delay = ip;
peekInterval = setTimeout(animation.peekTile, delay);
},
peekTile: function () {
//Your Code goes here
console.log('peek');
unpeekInterval = setTimeout(animation.unpeekTile, delay);
},
unpeekTile: function () {
//Your Code goes here
console.log('unpeek');
peekInterval = setTimeout(animation.peekTile, delay);
},
stop: function () {
clearTimeout(peekInterval);
clearTimeout(unpeekInterval);
}
}
})();
animation.start(1000);
// To stop
setTimeout(animation.stop, 3000);
​
I can't use this instead of animation.peekTile as setTimeout executes in global scope

Categories

Resources