JavaScript Timing - javascript

I want to select all the elements of a class. Then change that class to another class . After 0.5 seconds i want to revert the elements back to their original class. I must do this 8 times in a row. Even though my code achieves that(in a way) i can't see the color changes in the buttons . Can anyone help me ? it's a timing problem i guess. Here is the js code :
$(document).ready(function(){
$('#start').click(function(){
game();
})
function game(){
var ordine = new Array();
for(var t = 1; t <= 8; t++){
var y = 0;
for (var k = 0; k < t; k++) {
var x = Math.floor((Math.random() * 4) + 1);
ordine[y++] = x;
change1(x);
setTimeout(change2(x), 500);
}
}
}
function change1(y){
var z = 'cls' + y;
var t = 'cls' + y + 2;
$("." + z).removeClass(z).addClass(t);
}
function change2(y){
var z = 'cls' + y + 2;
var t = 'cls' + y;
$("." + z).removeClass(z).addClass(t);
}
})
Here you can find the full code(html,css and js)
http://jsfiddle.net/Cx5VK/2/

The problem is in the following line:
setTimeout(change2(x), 500);
You are calling the function change2 here, passing its return value to setTimeout.
What you actually want though is to call the change2 function after 500ms. Change your code to:
setTimeout(function() { change2(x); }, 500);
That way, you are passing an anonymous function to setTimout, which will then be executed by it after 500ms.
EDIT: I've modified your JSFiddle: http://jsfiddle.net/Cx5VK/7/ stripping out a lot of code that didn't do anything in that sample (you quite possibly need it elsewhere):
$(document).ready(function () {
$('#start').click(function () {
game();
})
function game() {
var x = Math.floor((Math.random() * 4) + 1);
change1(x);
}
function change1(y) {
var z = 'cls' + y;
var t = 'cls' + y + 2;
$("." + z).removeClass(z).addClass(t);
setTimeout(function() { change2(y); }, 500);
}
function change2(y) {
var z = 'cls' + y + 2;
var t = 'cls' + y;
$("." + z).removeClass(z).addClass(t);
game();
}
});
Now, the game function simply gets a random number and calls change1 with that number as parameter. change1 itself will set the timeout to reset the color for that square via change2. At the end of that function, the game is "restarted" by a simple call to game(), to get another random number and so on and so forth. I hope this is what you were looking for.

Related

Code doesn't work when inside the function

I have code that works well when used outside a function. But not sure what goes wrong when I just wrap a function around it.
This is my working code: Idea is to move the pencil in a square path. In the working code, it follows the square path but when I wrap around the function, it keeps going on in a straight line.
var direction ='right';
var angle = 0;
var sum_angle = 0;
for (var count = 0; count < 5; count++) {
if(--window.LoopTrap == 0) throw "Infinite loop.";
move_draw_Player(direction, 100);
var new_angle=90;
$('#player').animate({rotate: '90deg'}, 100);
var angle=angle +new_angle;
sum_angle =sum_angle + angle;
}
function move_draw_Player(directionStr, amount) {
directionStr =angle;
var x = Math.sin(angle*Math.PI/-180) * amount;
var y = Math.cos(angle*Math.PI/-180) * amount;
z= amount/100;
$('#pencil').animate({'left': '-='+x+'px', 'top': '-='+y+'px'}, z*350, 'linear', function() {
//window.counter = window.counter +2;
pen.moveTo((pencil.offset().left - cw.offset().left),(pencil.offset().top+ pencil.height() -ac.offset().top));
});
But when I wrap a function around it, it doesn't work. What could be going wrong?
var direction ='right';
var angle = 0;
var sum_angle = 0;
function Draw_Square() {
for (var count = 0; count < 5; count++) {
if(--window.LoopTrap == 0) throw "Infinite loop.";
move_draw_Player(direction, 100);
var new_angle=90;
$('#player').animate({rotate: '90deg'}, 100);
var angle=angle +new_angle;
sum_angle =sum_angle + angle;
}
}
function move_draw_Player(directionStr, amount) {
directionStr =angle;
var x = Math.sin(angle*Math.PI/-180) * amount;
var y = Math.cos(angle*Math.PI/-180) * amount;
z= amount/100;
$('#pencil').animate({'left': '-='+x+'px', 'top': '-='+y+'px'}, z*350, 'linear', function() {
//window.counter = window.counter +2;
pen.moveTo((pencil.offset().left - cw.offset().left),(pencil.offset().top+ pencil.height() -ac.offset().top));
});
}
//}
Draw_Square();

How to figure out how many times a function has been uniquely called

I am new to javascript and trying to learn from the beginning.
I have a script where I can do two different calculations using radio buttons, area and circumference.
I want to display how many times people have counted out different calculations.
If I use to show clicks on button then it counts everything together, but how can I separate them?
document.getElementById("calculate").addEventListener("click", function() {
var button = document.getElementById("calculate");
var x, text;
x = document.getElementById("radius").value;
if (document.getElementById("area").checked) {
if (isNaN(x) || x < 1 || x > 100) {
text = "Fel radie";
document.getElementById('radius').value = '';
} else {
let radius = document.getElementById("radius").value;
area = Math.PI * radius * radius;
}
if (document.getElementById("areaoutput").innerHTML = text);
else(document.getElementById("areaoutput").innerHTML = "Area = " + area);
}
if (document.getElementById("circumference").checked) {
let radius = document.getElementById("radius").value;
if (isNaN(x) || x < 1 || x > 100) {
text = "Fel radie";
document.getElementById('radius').value = '';
} else {
let radius = document.getElementById("radius").value;
circumference = Math.PI * 2 * radius;
}
if (document.getElementById("circoutput").innerHTML = text);
else(document.getElementById("circoutput").innerHTML = "Circumference = " + circumference);
}
if (document.getElementById("area").checked) {
var count = localStorage.on_load_counter || 0;
var button = document.getElementById("calculate");
var display = document.getElementById("areacount");
button.onclick = function() {
localStorage.on_load_counter = display.innerHTML = ++count;
}
}
if (document.getElementById("circumference").checked) {
var count = localStorage.on_load_counter || 0;
var button = document.getElementById("calculate");
var display = document.getElementById("circcount");
}
button.onclick = function() {
localStorage.on_load_counter = display.innerHTML = ++count;
}
}, false);
Try doing something like this
var combinationsDone = [];
Then every time the user does a calculation, you would add an object to combinationsDone.
For example, if they have a radius of 5, and circumference isn't checked, this is what you should do.
var combination = {
radius: 5,
circumference: false
}
if(!combinationsDone.includes(combination)){
combinationsDone.push(combination);
}
What this does is it makes sure that the combination wasn't recorded previously before adding the combination. Then, when you want to get the number of different combinations they have done, just user combinationsDone.length.
You can use a global variable. which is increased every time you call the function.
var myFuncCalls = 0;
function myFunction()
{
myFuncCalls++;
alert( "I have been called " + myFuncCalls + " times" );
}

My javascript slidshow code is not working

I have no clue why.
I have checkt everything but it should work.
This shuld be a slidshow for a webseit
<script src="JS/javascript.js">
"use strict";
var image = ['"bilder/1.png"','"bilder/2.png"'];
var i = 0;
aengereHintergrund();
function aengereHintergrund() {
document.getElementById('hintergund').style.backgroundImage = 'url('+image[i]+')';
if(i < image.length){
i ++
}
else {
i = 0
}
setTimeout(aengereHintergrund(),3000);
}
</script>
Oh, the classic function reference vs invocation problem.
Here's what you wrote:
setTimeout(aengereHintergrund(),3000);
And here's what you should have written:
setTimeout(aengereHintergrund,3000);
In the second case, we're passing the function aengereHintergrund itself to setTimeout, which is what we want. In the first case, you're invoking aengereHintergrund, and passing its result (which is nothing, aka undefined) to setTimeout.
(Note: You should also probably use setInterval instead of setTimeout, so you don't have to invoke it again and again. Also also, instead of branching on i >= image.length you can just use i = (i + 1) % image.length).
If you write if (i < images.length) i++;, i will reach images.length. You can fix this error with i++; if (i >= images.length) i = 0;, or i = (i + 1) % images.length; :
var slides = document.getElementById("slides");
var images = ["v67W6.jpg", "USehe.jpg"];
var path = "https://i.stack.imgur.com/";
var i = 0;
nextSlide();
function nextSlide () {
var bg = "url(" + path + images[i] + ")";
slides.style.backgroundImage = bg;
i = (i + 1) % images.length;
setTimeout(nextSlide, 1000);
};
<img id="slides" width="300" height="100" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

Multidimensional Array problems

I've been trying to fix this for about 3 days now, and I can't seem to find why it doesn't work.
I've got this function, which loads an image, and loads through all the pixels to create a grid of walls for A* pathfinding. I'm using CraftyJS to create this game, maybe it is that?
However, it seems to load perfectly fine, but when I try to use it in my game, it gives me loads of undefined values on most of the tiles. In fact, I feel like it only fills one row, instead of all 45.
This is the function that fills the GRID:
var babyStart = 0, babyNodes = [], grid = new Array(new Array());
function getGridFromImage(img, worldWidth, worldHeight) {
var image = new Image(); //maak een image object
var c = document.getElementById("mapLoader");
var context = c.getContext("2d");
image.src = img; //pak het plaatje erbij
image.onload = function () {
context.drawImage(image, 0, 0);
var data = context.getImageData(0, 0, worldWidth, worldHeight); //Verkrijg de Pixeldata
console.log(data);
var count = 0, tmr = null, length = data.data.length, x = 0, y = 0;
babyNodes = [];
while(count <= length) {
grid[y] = new Array();
//Verkrijg de kleuren DATA
var r = data.data[count]; //Rood channel
var g = data.data[count + 1]; //Groen channel
var b = data.data[count + 2]; //Blauw channel
//console.log(data[0]);
//console.log("Count/length: " + count + "/" + length + ";r: " + r + ";g: " + g + ";b: " + b);
if (r == 0 && g == 0 && b == 0) {
grid[y][x] = 1;
} else {
grid[y][x] = 0;
}
if (b > 0) {
babyNodes[b - 255] = count;
}
if (g == 255) {
babyStart = count;
}
count += 4;
x++;
if (x >= worldWidth) {
y += 1;
x = 0;
}
}
loading = false;
};
};
Sorry the comments are dutch, but I think most of you don't even need these comments anyways :P.
I try to collect the data in another function in another JS file, it looks a little like this:
Crafty.scene("lvlWoonkamer", function () {
Crafty.sprite("images/levels/Woonkamer.png", {
achtergrond: [0,0,1280,720]
});
Crafty.e("2D, DOM, achtergrond").attr({x: 0, y: 0});
console.log("Starting grid count");
for (var i = 0; i < 45; i++) {
var str = "";
for(var ii = 0; ii <= 80; ii++) {
str += grid[i][ii] + ",";
console.log("[" + i + "][" + ii + "]");
}
str += ";";
}
console.log(str);
});
This is the output I receive:
undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,0,undefined,;
Sorry for the bad code blocks and stuff, I have no idea how it works XD (Just pressed ctrl + K and copy paste).
I have no idea why it's doing this, I tried all kinds of things with the multi-dimensional arrays, looked up a lot, copy pasted a lot but it just doesn't seem to work...
(I'm already glad it loads the image tbh XD).
I'm kinda new to JavaScript and HTML5 and all that, so please be easy on me.
Sem Wong.
Edit: So I found out that I was clearing the Array everytime I did grid[y] = new Array();, so I changed it to if (grid[y] == null) grid[y] = new Array();. Now it works partly better, still getting some undefines but I'll get to the bottom of it :).
Edit 2: I fixed it completely and pathfinding is working also (A* OP). Thanks everyone for helping! It was the getGridFromImage function that was failing me, because it constantly cleared my grid[y]. I got a fixed version below for those who had the same problem as I did (Don't think there's anyone as stupid as me , but I guess new developers might have the same issue)
var babyStartX = 0, babyStartY = 0, babyNodes = [], grid = new Array(new Array());
function getGridFromImage(img, worldWidth, worldHeight) {
var image = new Image(); //maak een image object
var context = document.getElementById("mapLoader").getContext("2d");
image.src = img; //pak het plaatje erbij
image.onload = function() {
context.drawImage(image, 0, 0);
var data = context.getImageData(0, 0, worldWidth, worldHeight); //Verkrijg de Pixeldata
console.log(data);
var count = 0, length = data.data.length, x = 0, y = 0;
while(count <= length) {
if (grid[x] == null) grid[x] = new Array();
//Verkrijg de kleuren DATA
var r = data.data[count]; //Rood channel
var g = data.data[count + 1]; //Groen channel
var b = data.data[count + 2]; //Blauw channel
//console.log(data[0]);
//console.log("Count/length: " + count + "/" + length + ";r: " + r + ";g: " + g + ";b: " + b);
if (r == 0 && g == 0 && b == 0) {
grid[x][y] = 1;
} else {
grid[x][y] = 0;
}
if (b > 0 && g == 0 && r == 0) {
babyNodes[b - 254] = [x,y];
}
if (g == 255 && b == 0 && r == 0) {
babyStartX = x;
babyStartY = y;
babyNodes[0] = [x,y];
}
count += 4;
x++;
if (x >= worldWidth) {
y += 1;
x = 0;
}
}
loading = false;
}; };
I am not familiar with Crafty, so sorry if I am wrong, but I suppose Scott Sauyet is right. JavaScript is by default asynchronous, so perhaps you are calling the second function before the first one finished?
There is some background information on callbacks here: http://recurial.com/programming/understanding-callback-functions-in-javascript/
The concept behind callbacks is that you can call a module inside another so they are always ran sequentially.
function build(argument1, argument2) {
// Do things
check;
}
function check() {
// Do things
}
Your case would probably be something like this, but I can't really tell from your code.
function getGridFromImage(img, worldWidth, worldHeight) {
// Rest of your function
check;
}
function check() {
Crafty.scene("lvlWoonkamer", function () {
Crafty.sprite("images/levels/Woonkamer.png", {
achtergrond: [0,0,1280,720]
});
Crafty.e("2D, DOM, achtergrond").attr({x: 0, y: 0});
console.log("Starting grid count");
for (var i = 0; i < 45; i++) {
var str = "";
for(var ii = 0; ii <= 80; ii++) {
str += grid[i][ii] + ",";
console.log("[" + i + "][" + ii + "]");
}
str += ";";
}
console.log(str);
});
}
// Actually start the first function here;
getGridFromImage(img, worldWidth, worldHeight);

trouble with passing values between functions

I'm having trouble figuring out how to pass values from one function to another. I've created a program where I create boxes using values from a form that show up in the webpage. The values I'm talking about are property values of the boxes themselves.
Here is the function where the values are assigned to the boxes:
function addBox(newbox) {
for (var i = 0; i < newbox.number; i++) {
counter++;
var id = counter;
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.value = id;
console.log(div.value);
div.className += " " + "box";
div.innerHTML += newbox.name;
div.style.backgroundColor = newbox.color;
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
div.style.left = x + "px";
div.style.top = y + "px";
scene.appendChild(div);
div.onclick = display;
}
}
Here is the function that I'm having trouble passing the values to. I need to pass them so that I can display them in an alert box when I click on each box:
function display(e) {
alert(e.target.toSource());
}
So far when I click it, I just get an empty pair of brackets in the alert box.
I tried your example in JS Fiddle: http://jsfiddle.net/jCC6n/
I'm seeing at least two problems.
"counter" is undefined, which causes the code to fail when it first attempt to increment it. I added a variable declaration at the top of the function.
toSource is undefined. I replaced that with "outerHTML", which works in Chrome, IE and presumably other browsers.
With the above changes, this worked.
function display(e) {
alert(e.target.outerHTML);
}
function addBox(newbox) {
var counter = 0;
for (var i = 0; i < newbox.number; i++) {
counter++;
var id = counter;
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.value = id;
div.className += " " + "box";
div.innerHTML += newbox.name;
div.style.backgroundColor = newbox.color;
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
//div.style.left = x + "px";
//div.style.top = y + "px";
scene.appendChild(div);
div.onclick = display;
}
}
addBox({ number: 3, name: "Hello", color: '#C00' });
Be advised that event handling using onclick event handlers varies from browser to browser. It will be best to use a JavaScript framework that knows all the differences and gives you a unified way to handle events. jQuery is arguably the most used such framework.

Categories