Memory game flipping individual cards isn't working - JavaScript - javascript

I've created a memory game. Most of the functions work, but one thing I'm struggling with is getting the cards to flip correctly. Here is the function I'm using to swap between the back of the card (card.jpg) and the front of the card (image names found in the ImagesArr array):
// Swap out cards for shuffled images
function swapImages() {
for(var i = 0; i < images.length; i++) {
if(images[i].src !== "/img/card.jpg") {
images[i].src = imagesArr[i];
} else {
images[i].src = "/img/card.jpg";
}
}
}
It works to show the hidden images, but it shows ALL of them, not just the one that's clicked. I also have this function above it which helps with the flip animation and adding some necessary classes as well as calling the swapImages function.
// Flip the cards over on click and start the timer
function flipCards() {
cards.forEach(card => {
card.addEventListener("click", () => {
card.classList.toggle("flipped");
card.classList.toggle("chosen");
chosenCards.push(card);
startTimer();
swapImages();
checkMatch();
});
});
}
I feel like I need a forEach loop or something like that, but I'm not sure how to implement it or where to implement it. I also could be completely wrong and don't need a forEach loop at all. TIA for any help!

I think that you need to use target event (https://www.w3schools.com/jsref/event_target.asp). So that program know which card is on other side .By the code that you provided l suspect that on click all cards flip.

Related

how can i update the items at html page

let bricks = document.querySelectorAll(".brick");
bricks.forEach((brick) => {
brick.addEventListener("click", function () {
let bricktype = brick.getAttribute("type");
console.log(bricktype);
});
});
from the above code ...
bricks variable get updated while the page first load. then i have form to add extra items to the bricks variable.. but i can't get update it .. if i try to reload page all the value eraes from memory
i want add values to that brocks array while i dynamicall add values in the html page
Yes, that code will only be executed at page load. This is a design problem, try refactoring your system some like this:
First, a function to add a listener for a single brick
function setupBrick(brick) {
brick.addEventListener("click", function () {
let bricktype = brick.getAttribute("type");
console.log(bricktype);
});
}
Now, in first page load:
let bricks = document.querySelectorAll(".brick");
bricks.forEach((brick) => {
setupBrick(brick)
});
And when user dynamically push a brick, do the following:
// get brick from form and store it in the "brickToPush" variable
setupBrick(brickToPush) // before push the brick
bricks.push(brickToPush)
That should solve your problem, you need to manually add that listener somehow, and encapsulating that logic in a function is a good practice

Issue calling a class function from a for loop

I have been bashing my head on this and I know that it's probably an easy fix but I can't for the life of me figure out what is wrong. I am trying to call a class function within a for loop and I've tried a few methods but i've come up with diddly-squat so far. I'll plug in the relevant snippets below. For reference this is a project to make a web-based simple game and I've chosen a bastardization of galaga and asteroids hence, "ship" and "asteroids." My question is why won't it populate the class function .spawn(); that's been assigned to the items in the "rock" iterative? Any advice would be extremely helpful.
var rock = []; //I know global variables = evil, but I'm still early in development
function setup() {
...
//Asteroids
for(var i = 0; i<5; i++){
var y = random(0,350);
var speed = random(2,5);
rock.push(new asteroid(800,y,speed,10));
}
...
}
function draw() {
...
//Spawn Asteroids
//rock[0].spawn(); //<-------Single instance of object from array(works as intended)
/*for (let c of rock){ //<-------Tried changing variable type to const as well because I was pulling my hair out and that did nothing either.
this.spawn();
}*/
/*for (let c in rock){ //<-------Covering my bases
this.spawn();
}*/
rock.forEach(index => this.spawn()); //<------Last thing I tried
...
}
//////////////////////////////////////////////////////////////////////////////
class asteroid {
...
spawn(){
this.move();
this.display();
this.offScreen();
this.speed = random(2,5);
}
...
}
////////////////////////////////////////////////////////////////////////////////////////////
Note: I tried to create a facsimile of another for loop that I used for
the ship attack but it didn't work either. It's this snippet below.
draw(){
this.bullets.forEach((bullet) => {
if(this.isBulletOffScreen(bullet)){
const index = this.bullets.indexOf(bullet);
this.bullets.splice(index, 1);
}
bullet.draw();
});
}
I don't have the one I tried to adapt because I felt I was way over complicating a simple object so I erased it but this is the working code for the projectile controller class that I was copying from.
P.S. Here is the Error message I keep getting.
*🌸 p5.js says: [sketch.js, line 86] "spawn" could not be called as a function. Verify whether "this" has "spawn" in it and check the
spelling, letter-casing (JavaScript is case-sensitive) and its type.
More info: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong
sketch.js:86*
** Uncaught TypeError: this.spawn is not a function
at draw (sketch.js:86:10)
at p5._main.default.redraw (p5.js:71990:27)
at _draw (p5.js:64140:25) ​**
#Teemu had the answer and it took a bit for my thick skull to work it out. By adjusting the forEach to resemble this:
rock.forEach(index => index.spawn());
They spawn and now I can start moving forward again. Thank you again Teemu!

Iterate over cue method with popcorn.js

I am attempting to set multiple cue points in a video. Instead of writing each cue out, I would like to iterate over an object that has the data I need, such as the time of the cue and some info about what to do with the call back.
The problem is when I try to iterate over the object it overwrites all the cues except for the last one.
var products = myVideo.products;
var video = Popcorn('#mainVideo');
for (product in products){
var obj = products[product],
start = obj.start,
img = obj.image,
$targetDiv = $("#"+obj.targetDiv);
video.cue( start, function(){
$('<img>', {
class : "isImage",
src : 'images/' + img
}).prependTo( $targetDiv );
})
}
Any help would be greatly appreciated.
In this code, every cue has its own callback function, but every function refers to the same variable img and the same $targetDiv. By the time they run, those variables will be set to their respective values for the last item in products.
If you've ever run code through jslint and seen the warning, don't make functions in a loop, this is why. A good way to do what you're trying to do is to put those variables inside of a function that gets called immediately and returns another function, which is your callback. Like this:
function makeCallback(obj) {
return function() {
$('<img>', {
class : "isImage",
src : 'images/' + obj.img
}).prependTo( $("#"+obj.targetDiv) );
};
}
for (var product in products) {
var obj = products[product];
video.cue( obj.start, makeCallback( obj ) );
}
Alternatively, you can use forEach, which does the same thing under the hood. (Popcorn provides its own version, which handles both arrays and objects.)
Popcorn.forEach(products, function(obj) {
video.cue( start, function(){
$('<img>', {
class : "isImage",
src : 'images/' + obj.img
}).prependTo( $("#"+obj.targetDiv) );
});
});
I should note that you have another problem in this code, which is that you have Popcorn creating a new image every time you pass through the cue point. So, if the user ever skips back to replay some of the video, the images will start to pile up. Also, the images don't start loading until right when they become visible, so if there's a slow-ish network connection, the images may not show up until it's too late.
The best way to handle these is usually to create your images ahead of time but make them invisible with CSS, and then have the Popcorn events make them visible at the right time. You might consider using the image plugin, which will do most of your heavy lifting for you.

Highcharts Image click event

We are using Highcharts api in our application.
The below url will give the problem scenario.
http://jsfiddle.net/jnjqt/40/
I need a different click event for each image. But I am getting the same result for each image.
Like if I get alert value of corresponding i for each image, my problem will be solved.
Thanks in advance.
That’s a more common problem. We use closures in a loop (for or while) and it always keep the last value of the increment.
You just need to return a function when you make the following loop:
for (var i = 0; i < chart.series[0].data.length; i++) {
......
}
This code should fix your problem:
.on('click', function(i) {
return function () {
alert(" image:"+i);
}
}(i))
Here the solution: http://jsfiddle.net/jnjqt/42/

Javascript how to build loop with unconstant time of iterations

need to be consulted by JS jedi.
Situation: I got array with USER_IDs and need to call social network function to post on their walls. So I need to launch wallpost function, listen to its answer and then continue iterating my loop.
Code I have written is able to leave post to the last person from array, to the first, to none and many others useful functions :s . Need your help jedis
function showPost() {
for(i in selFriends) { //selFriends - massive with user_id
alert(i+' '+selFriends[i]); //checkplace
VK.api('wall.post',{
owner_id:selFriends[i], //element
message:htmlres, // content
attachment:photoID // id of the mediacontent
},function(receive) {
showPost();
});
return;
}
}
This code need to be fixed, because now it is just iterationg wall.post for 1st element from the massive.
By the way method VK.api is almost similar to Facebook UI method 'feed'.
Thank you very much :)
I'm no jedi, but are you trying to run the first index in your selFriends array through VK.api, and call the next index in the callback? And then repeat for each element in the selFriends array?
function postId(index) {
if (index === selFriends.length)
return;
VK.api('wall.post',{
owner_id:selFriends[i], //element
message:htmlres, // content
attachment:photoID // id of the mediacontent
},function(receive) {
postId(index + 1);
});
}
And then
function showPost() {
postId(0);
}

Categories