I am trying to loop through and execute the functions in my array however i am having trouble doing so, here is the code:
<p id="demo" >I will change colour automatically.</p>
<script>
var i = 0;
var array_of_functions = [
function first_function(){
document.getElementById("demo").style.color = "red";
},
function second_function(){
document.getElementById("demo").style.color = "blue";
},
function third_function(){
document.getElementById("demo").style.color = "green";
},
function forth_function(){
document.getElementById("demo").style.color = "white";
}
];
var time = 1000;
function change(){
for(var i=0, len=array_of_functions.length; i < len; i++){
}
window.onload = change;
</script>
Please tell me what i am doing wrong.)
You need to run the functions inside the loop using array_of_functions[i](), but if you want to put a delay between each iteration you will need to use setTimeout.
In modern JavaScript, you can use async and await to maintain the imperative style of your code. Since each of the functions in your array are almost identical, you can change the array so that it only stores what changes: the color.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function change() {
for (const color of ['red', 'blue', 'green', 'white']) {
document.getElementById('demo').style.color = color;
await delay(1000);
}
}
window.onload = change;
<p id="demo">I will change colour automatically.</p>
You never execute your functions inside the for loop. Change
for(var i=0, len=array_of_functions.length; i < len; i++){
}
to:
for(var i=0, len=array_of_functions.length; i < len; i++){
array_of_functions[i]();
}
var i = 0;
var array_of_functions = [
function first_function(){
document.getElementById("demo").style.color = "red";
},
function second_function(){
document.getElementById("demo").style.color = "blue";
},
function third_function(){
document.getElementById("demo").style.color = "green";
},
function forth_function(){
document.getElementById("demo").style.color = "brown";
}
];
var time = 1000;
function change(){
for(var i=0, len=array_of_functions.length; i < len; i++){
array_of_functions[i]();
}
}
window.onload = change;
<p id="demo">I will change colour automatically.</p>
for(var i=0, len=array_of_functions.length; i < len; i++){
}
to:
for(var i=0, len=array_of_functions.length; i < len; i++){
array_of_functions[i]();
}
If you want a time delay of 1000ms in between each call (as indicated by the variable time), you can chain promises together using .reduce():
const array_of_functions = [
'red', 'blue', 'green', 'white'
].map(function (color) {
return function () {
document.getElementById('demo').style.color = color;
};
});
var time = 1000;
function sleep(ms) {
return function () {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
};
}
function change() {
array_of_functions.reduce(function (promise, func) {
return promise.then(sleep(time)).then(func);
}, Promise.resolve());
}
window.onload = change;
<p id="demo">I will change colour automatically.</p>
Using ES6 arrow functions, you can simplify it to this:
const array_of_functions = [
'red', 'blue', 'green', 'white'
].map(
color => () => document.getElementById('demo').style.color = color
);
const time = 1000;
const sleep = ms => () => new Promise(resolve => {
setTimeout(resolve, ms);
});
function change() {
array_of_functions.reduce(
(promise, func) => promise.then(sleep(time)).then(func),
Promise.resolve()
);
}
window.onload = change;
<p id="demo">I will change colour automatically.</p>
Finally, using ES2017 async / await, you can further simplify it:
const array_of_functions = [
'red', 'blue', 'green', 'white'
].map(
color => () => document.getElementById('demo').style.color = color
);
const time = 1000;
const sleep = ms => new Promise(resolve => {
setTimeout(resolve, ms);
});
async function change() {
for (const func of array_of_functions) {
await sleep(time);
func();
}
}
window.onload = change;
<p id="demo">I will change colour automatically.</p>
My guess is, you're really trying to do this:
//<![CDATA[
/* external.js */
var doc, bod, htm, M, I, S, Q, rand, old = onload; // for use on other pages
onload = function(){ // load not indented to save space
if(old)old(); // change old var name if using technique on other pages
doc = document; bod = doc.body; htm = doc.documentElement;
M = function(tag){
return doc.createElement(tag);
}
I = function(id){
return doc.getElementById(id);
}
S = function(selector, within){
var w = within || doc;
return w.querySelector(selector);
}
Q = function(selector, within){
var w = within || doc;
return w.querySelectorAll(selector);
}
rand = function(array){
return array[Math.floor(Math.random()*array.length)];
}
var colors = ['red', 'green', 'blue', 'yellow', 'purple', 'orange', 'aqua'];
var demo = I('demo'), dS = demo.style;
setInterval(function(){
dS.color = rand(colors);
}, 300);
} // end load
//]]>
/* external.css */
html,body{
padding:0; margin:0;
}
body{
background:#000; overflow-y:scroll;
}
.main{
width:940px; background:#fff; padding:20px; margin:0 auto;
}
#demo{
color:purple;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='viewport' content='width=device-width' />
<title>Test Template</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div class='main'>
<p id='demo'>I will change color automatically.</p>
</div>
</body>
</html>
Change the colors Array and interval as needed.
Here is an example:
var i = 0;
var demo = document.getElementById("demo");
var array_of_colors = ["red","blue","green","white"];
var time = 1000;
window.onload = function(){
setInterval(function(){
demo.style.color = array_of_colors[i++%4];
}, time)
};
<p id="demo" >I will change colour automatically.</p>
Related
Hello people of stackoverflow!
I'm looking to use a button in Javascript to execute an array of functions sequentially (one after the other) ON BUTTON CLICK, not all at once. (see Function DisplayNext below)
At the moment, the functions all execute simultaneously. Can anyone help!? I want to be able to click the button and have each coloured square appear on the screen one after the other, on each button click.
function red () {
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#red";
ctx.fillRect(20,60,23,23);
}
function blue() {
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#blue";
ctx.fillRect(20,100,23,23);
}
function green() {
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#green";
ctx.fillRect(20,20,23,23);
}
function functionarray() {
var array_of_functions = [
green,
red,
blue,
]
for (i = 0; i < array_of_functions.length; i++) {
array_of_functions[i]();
}
}
function displayNext() {
var array_of_functions = [
green,
red,
blue,
]
for (i = 0; i < array_of_functions.length; i++) {
array_of_functions[i].onclick = array_of_functions[i]();
//array_of_functions[i].onclick();
}
}
<p><button type="button" onclick="displayNext()">On Click, next colour</button></p>
</html>
`
<html>
<head>
<title></title>
</head>
<body>
<p>
<button type="button" id="myID">next color</button>
</p>
<script>
var canvas = document.getElementById("myCanvas"),
ctx = canvas.getContext("2d"),
red = function red() {
ctx.fillStyle="#red";
ctx.fillRect(20,60,23,23);
},
blue = function blue() {
ctx.fillStyle="#blue";
ctx.fillRect(20,100,23,23);
},
green = function green() {
ctx.fillStyle="#green";
ctx.fillRect(20,20,23,23);
},
lastCall = 0,
array_of_functions = [green, red, blue],
displayNext = function displayNext() {
array_of_functions[lastCall]();
lastCall += 1;
};
document.getElementById('myID').addEventListener('click', displayNext);
</script>
</body>
</html>
I am trying to call the JavaScript function repeatedly after the execution.
function startSlide(){
var products = [
['images/product_images/footwear/footwear_1.jpeg'],
['images/product_images/mobile/mobile_1.jpeg'],
['images/product_images/camera/camera_1.jpeg'],
['images/product_images/fashion/fashion_1.jpeg'],
['images/product_images/laptop/laptop_1.jpeg'],
['images/product_images/furniture/furniture_1.jpeg']
];
for (var i = 0; i < products.length; i++) {
var image = products[i][0];
imgslider(image, i * 800);
}
};
function imgslider(image, timeout)
{
window.setTimeout(function() {
document.getElementById('imgslider').innerHTML = "";
var product = document.getElementById('imgslider');
var elem = document.createElement("img");
product.appendChild(elem);
elem.src = image;
},timeout);
startSlide();
}
The startSlide() function iterates the array and fetch the value from array and call the function imgslider(). the imgslider() function appends the image to the div.
at the end of the imgslider() i am trying to call the startSlide() so that it could continue the execution.... but its not working. how can i do this?
The problem is your code is creating an infinite recursion...
Maintianing your code structure you can add a flag to fix the problem
function startSlide() {
var products = [
['//placehold.it/64X64&text=1'],
['//placehold.it/64X64&text=2'],
['//placehold.it/64X64&text=3'],
['//placehold.it/64X64&text=4'],
['//placehold.it/64X64&text=5']
];
for (var i = 0; i < products.length; i++) {
var image = products[i][0];
imgslider(image, i * 800, i == products.length - 1);
}
};
function imgslider(image, timeout, last) {
window.setTimeout(function() {
document.getElementById('imgslider').innerHTML = "";
var product = document.getElementById('imgslider');
var elem = document.createElement("img");
product.appendChild(elem);
elem.src = image;
if (last) {
setTimeout(startSlide, 800);
}
}, timeout);
}
startSlide()
<div id="imgslider"></div>
If you want to loop, then you can use setInterval() instead
function startSlide() {
var products = [
['//placehold.it/64X64&text=1'],
['//placehold.it/64X64&text=2'],
['//placehold.it/64X64&text=3'],
['//placehold.it/64X64&text=4'],
['//placehold.it/64X64&text=5']
],
i = 0;
setInterval(function() {
imgslider(products[i][0]);
if (++i >= products.length) {
i = 0
}
}, 800);
};
function imgslider(image) {
document.getElementById('imgslider').innerHTML = "";
var product = document.getElementById('imgslider');
var elem = document.createElement("img");
product.appendChild(elem);
elem.src = image;
}
startSlide()
<div id="imgslider"></div>
That's because window.setTimeout only calls the function once, so you should use window.setInterval instead. Something like this:
window.setInterval(function () { /* code to update picture... */ }, 3000);
If it's still not working you can check the console log for errors.
That's F12 in IE or Ctrl+Shift+J in Chrome.
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="practise.css"/>
<script type="text/javascript" src="practise.js"></script>
</head>
<body>
<div id="items"><p id="help">Hello World</p></div>
<script>
var para=document.getElementById('help');
var check=true;
//want to return these styles whenever mouse is clicked
function toggle(){
if(check){
para.style.color="#EEFFCC";
para.style.textAlign="center";
para.style.fontSize="1em";
}else{
para.style.color="#223311";
para.style.textAlign="center";
para.style.fontSize="4em";
}
check=!check;
}
para.onclick=toggle();
</script>
</body>
</html>
The code i want to make is that it toggles between two sets of Styles whenever mouse is licked on 'para' element. But i couldn't figure out how to return the styles to the 'para.onclick' call below the function.
Currently you are doing:
para.onclick = toggle();
which means that para.onclick will be the result of executing toggle().
What you want to do is assign toggle to para.onclick:
para.onclick = toggle;
The difference is this:
function result() {
return 2;
}
var res = result();
// res = 2
var fnRes = result;
// fnRes = function() { return 2; }
Just create a little function when you click the onClick it calls your toggle, like so para.onclick = function() {}.
var para = document.getElementById('help');
var check = true;
function toggle() {
if (check) {
para.style.color = "blue";
para.style.textAlign = "center";
para.style.fontSize = "1em";
} else {
para.style.color = "red";
para.style.textAlign = "center";
para.style.fontSize = "4em";
}
check = !check;
}
para.onclick = function() {
toggle()
};
<div id="items">
<p id="help">Hello World</p>
</div>
I have a Javascript function to change colors of a svg ellipse object with id="eye"
document.getElementById("eye").onmouseover = function() {
changeColor()
};
function changeColor() {
document.getElementById("eye").style.fill = "red";
}
document.getElementById("eye").onmouseout = function() {
changeColor2()
};
function changeColor2() {
document.getElementById("eye").style.fill = "green";
}
Now there are 2 more svg objects with id="nose" and id="mouth", how can I apply the same change color founction on these 2 objects? Yes I can repeat the founction 2 more times but there must be a better way to do it. Note The 3 objects shouldn't change color at the same time, which means there no need for loop.
you mean like that? :
document.getElementById("eye").onmouseover = function() {
changeColor("eye")
};
document.getElementById("nose").onmouseover = function() {
changeColor("nose")
};
document.getElementById("mouth").onmouseover = function() {
changeColor("mouth")
};
document.getElementById("eye").onmouseout = function() {
changeColor2()
};
document.getElementById("nose").onmouseout = function() {
changeColor2("nose")
};
document.getElementById("mouth").onmouseout = function() {
changeColor2("mouth")
};
function changeColor(element) {
document.getElementById(element).style.fill = "red";
}
function changeColor2(element) {
document.getElementById(element).style.fill = "green";
}
You could add a parameter to your functions:
function changeColor(element, color) {
element.style.backgroundColor = color;
}
document.getElementById("eye").onmouseover = function(){changeColor(this, "red")};
document.getElementById("eye").onmouseout = function(){changeColor(this, "green")};
document.getElementById("nose").onmouseover = function(){changeColor(this, "blue")};
document.getElementById("nose").onmouseout = function(){changeColor(this, "orange")};
UPDATED
Syntax for background colour fixed(instead of .style.fill it is .style.backgroundColor)
See Demo Fiddle
Reducing element look-ups
Try to make a closure like this:
// Caching elements and closures
var eye = document.getElementById("eye"),
nose = document.getElementById("nose"),
mouth = document.getElementById("mouth"),
change_to_green = change_group_color("green"),
change_to_red = change_group_color("red");
eye.onmouseover = change_to_green;
eye.onmouseout = change_to_red;
nose.onmouseover = change_to_green;
eye.onmouseout = change_to_red;
mouth.onmouseover = change_to_green;
mouth.onmouseout = change_to_red;
function change_group_color(color){
var elem_group = [eye, nose, mouth];
return function(){
var i,l;
for(i=0, l=elem_group.length ; i<l ; i++){
elem_group[i].style.fill = color;
}
}
}
this inside the handler will point to the element that you registered the event with
function onMouseOver() {
this.style.fill = "red";
}
function onMouseOut {
this.style.fill = "green";
}
var eye = document.getElementById("eye");
var nose = document.getElementById("nose");
eye.onmouseover = nose.onmouseover = onMouseOver;
eye.onmouseout = nose.onmouseout = onMouseOout;
I made a function which should disable a button if a variable isn't greater than or equal to another one. This function is run every second on a setInterval(), and the first variable to compare is also incremented by one on the setInterval(). But, the function (evitarNegs()), isn't working properly, and the button is always disabled. Sorry that part of the code is in spanish.
Javascript:
var GmB = {cantidad: 0, perSec: 1};
function Upgrade (pb, ps) {
this.precioBase = pb;
this.perSec = ps;
this.cantidad = 0;
this.precio = pb;
}
Upgrade.prototype.comprar = function() {
GmB.cantidad = GmB.cantidad - this.precio;
GmB.perSec = GmB.perSec + this.perSec;
this.cantidad++;
document.getElementById("gmb").innerHTML = GmB.cantidad;
this.precio = Math.ceil(this.precioBase*Math.pow(1.15, this.cantidad));
evitarNegs();
};
function loop() {
GmB.cantidad = GmB.cantidad + GmB.perSec;
document.getElementById("gmb").innerHTML = GmB.cantidad;
evitarNegs();
}
var upg = new Upgrade(10, 1);
var boton1 = document.getElementById("boton1");
boton1.disabled = true;
window.setInterval(loop, 1000);
//Problematic function
function evitarNegs() {
if (!(GmB >= upg.precio)) {
boton1.disabled = true;
}else {
boton1.disabled = false;
}
}
boton1.onclick = function() {
upg.comprar();
};
HTML:
<html>
<head>
<title>Gummy Bears</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<p id="gmb">0</p>
<button id="boton1" type="button">Upgrade 1</button>
<script src="main.js"></script>
</body>
</html>
You are comparing GmB to upg.precio, but GmB is an object. So you want
function evitarNegs() {
if (!(GmB.cantidad >= upg.precio)) {
boton1.disabled = true;
} else {
boton1.disabled = false;
}
}
However, this can be written much easier as
function evitarNegs() {
boton1.disabled = GmB.cantidad < upg.precio;
}
Fiddle: http://jsfiddle.net/4rRmp/
It seems that you are comparing an object to an integer in GmB >= upg.precio. You probably have to replace it by GmB.cantidad >= upg.precio.