I'm currently learning basic JavaScript/JQuery but I'm in need of a quick fix to a problem which is slightly beyond what I'm capable of solving right now.
I'm looking to create a feature that allows me to click through images, and when I click on the last image it will return to the first image, in a loop.
(I'm trying to make something similar to this: https://www.antennebooks.com/product/east-end-of-europe/)
Any help would be greatly appreciated!
this is what I have so far:
<script>
var images = [
"images/img1.png",
"images/img2.png",
"images/img3.png",
"images/img4.png"
]
var step = 0;
changeImage();
function changeImage() {
document.getElementById('imgClickAndChange').src = images[step];
step++;
}
Assuming the function changeImage() is called when you click on the image displayed, you just have to change the step++; to step = (step + 1) % images.length; and place it as the first line of your function.
Each time step + 1 equals to images.length, step would be reset to 0.
We could use jQuery and manipulate the DOM via events, which would make more sense in this situation. A "click" event could be triggered when the user clicks on an image. You could store the images in a set, and when the number of clicks is greater than the length of the set, display the first card and start the process over again. Here is an example of the JavaScript code utilizing the jQuery libary:
$(document).ready(function (){
var card = $('.card'); //store each card with an image in it in a set
card.css('cursor', 'pointer'); //set the cursor to pointer to make a click obvious to user
card.not(':first').hide(); //hide all but the first image (card)
count = 1; //set the initial click count to one
card.on('click', function() { //listen for an image to be clicked
$(this).hide(); //hide the image that has been clicked
$(this).next().show(); //show the next image
count++; //increment the count
if(count > card.length) { //if the count is greater than the length of the set, you are out of images (cards)
count = 1; //reset the count
card.first().show(); //show the first card and start process over
}
});
});
This is the html code that I am using to simulate the events you are looking for:
<div class="card" style="max-width: 18rem;">
<img class="card-img-top" src="/path">
<div class="card-body">
<p>This is a random card and stuff</p>
</div>
</div>
<div class="card" style="max-width: 18rem;">
<img class="card-img-top" src="/path">
<div class="card-body">
<p>This is a random card and stuff</p>
</div>
</div>
<div class="card" style="max-width: 18rem;">
<img class="card-img-top" src="/path">
<div class="card-body">
<p>This is a random card and stuff</p>
</div>
</div>
As you can see, we have three cards that basically store our images. If you just want images and no cards, then do that, because that part of it is trivial. What matters here is the programming logic. I would simply set a counter and once that counter is greater than the length of the set (collection) of cards (a set/collection is an array-link object) then show the first card again and start the process over as I showed you in JavaScript.
Related
I want click neighbor and change the main country. I click first card ok no problem. but other cards not working. This is my code:
function renderNeighbors(data) {
let html = "";
for (let country of data) {
html += `
<div class="col-2 mt-2">
<div class="card click-change">
<img src="${country.flags.png}" class="card-img-top">
<div class="card-body">
<h6 class="card-title neighborName">${country.name.common}</h6>
</div>
</div>
</div>
`;
}
document.querySelector("#neighbors").innerHTML = html;
document.querySelector(".click-change").addEventListener("click", () => {
let neighborName = document.querySelector(".neighborName").innerHTML;
getCountry(neighborName);
})
}
in photos I point red circle in my browser. that's only working card.
enter image description here
I want to click neighbors and change main country. but only work for first neighbor
here is my all html code https://pastebin.com/Sb9XWZhy
here, the problem you are setting your event only for the first chosen element that matches your locator .
querySelector return only the first element that matches.
you should add the event for all of your nodes that match the locator.
It's supposed that querySelectorAll returns an array that you can loop over it like that.
for (let element of document.querySelectorAll(".click-change")){
element.addEventListener("click", () => {
let neighborName =
element.children[1].children[0].innerHTML;//here I'm accessing the neighbourName from the element itself, I'm not sure about the indices but you can handle them yourself
getCountry(neighborName);
})
}
I've been trying to solve this for the last couple of hours but all attempts failed...
What I need to do is to click on a DIV that will cause another DIV to pop up.
Inside the pop up there are some <li> and after clicking it, the attribute name is "transferred" to the first DIV clicked.
Ok, I managed to do that but after I update the first DIV and when I try to update the second DIV, the first DIV also gets updated and when I try to update the third DIV the other two gets updated ass well.
Can anyone help me to fix it and only update the DIV it was clicked on leaving the previous as it was supposed to be?
Here is the code:
HTML
<div class="num-1">
<img src="http://dummyimage.com/180x180/eeeeee/000000.jpg" width="180" height="180">
<p class="brand"></p>
<p class="name"></p>
</div>
<div class="num-2">
<img src="http://dummyimage.com/180x180/eeeeee/000000.jpg" width="180" height="180">
<p class="brand"></p>
<p class="name"></p>
</div>
<div class="num-3">
<img src="http://dummyimage.com/180x180/eeeeee/000000.jpg" width="180" height="180">
<p class="brand"></p>
<p class="name"></p>
</div>
<div class="num-4">
<img src="http://dummyimage.com/180x180/eeeeee/000000.jpg" width="180" height="180">
<p class="brand"></p>
<p class="name"></p>
</div>
<div class="num-5">
<img src="http://dummyimage.com/180x180/eeeeee/000000.jpg" width="180" height="180">
<p class="brand"></p>
<p class="name"></p>
</div>
<div class="popup">
<ul>
<li name="{{PHP GENERATED $name}}">{{PHP GENERATED $name}}</li>
<li name="{{PHP GENERATED $name}}">{{PHP GENERATED $name}}</li>
<li name="{{PHP GENERATED $name}}">{{PHP GENERATED $name}}</li>
</ul>
</div>
jQuery
//Openning the .popup and assigning the names
//First check the number of the div it was clicked on
$('img').on('click', function() {
var num = $(this).parent().attr('class').match(/\d+/)[0];
$('.popup').fadeIn();
//Click li to update the brand and name on the page
$('.popup li').on('click', function() {
//Check the name and split it
var nameComplete = $(this).attr('name');
var Array = nameComplete.split(" ");
//Check the first word and identify it as brand, also update on the page
var brand = Array[0];
$('.num-' + num + ' .brand').text(brand);
//Check the rest of the array for the name and update it on the page
var name = '';
for(var i=1; i<Array.length ;i++) {
name = name + Array[i] + ' ';
}
name = $.trim(name);
$('.num-' + num + ' .name').text(name);
$('.popup').fadeOut();
});
});
Someone might wonder if I'm getting the number of the DIV correctly.
I did console.log(num); and it shows that I'm clicking on the correct DIV because the DIV class is num-X (X = 1 to 5), 1 for 1, 2 for 2,...
The names of the <li> are ok, it works as it should, split it and get the right part to "transfer".
I guess I made the proper modifications to better understanding the code.
$('img').on('click', function() {
var num = $(this).parent().attr('class').match(/\d+/)[0];
window.num = num;
$('.popup').fadeIn();
});
//Click li to update the brand and name on the page
$('.popup li').on('click', function() {
//Check the name and split it
var nameComplete = $(this).attr('name');
var Array = nameComplete.split(" ");
//Check the first word and identify it as brand, also update on the page
var brand = Array[0];
$('.num-' + window.num + ' .brand').text(brand);
//Check the rest of the array for the name and update it on the page
var name = '';
for(var i=1; i<Array.length ;i++) {
name = name + Array[i] + ' ';
}
name = $.trim(name);
$('.num-' + num + ' .name').text(name);
$('.popup').fadeOut();
});
Separate both the click events in separate functions. Probably whats happening in your code is that every time you click on a div a new click event handler is attached to the '.popup li' and every time you click on one of the '.popup li' all the click handlers are activated. Thus explaining the multiple divs being updated.
Second option you have is to use jquery.off. This way every time you attach an event handle with .click to the '.popup li' you also remove it after you work is done and complete. Since this would have made your code harder to debug and to read i have preferred the first method in this answer.
NOTE**- i have changed the num to window.num which isnt a very good practice (keeping a global variable) but im sure you will be able to refactor the code once you get it to work
I am creating a simple Memory card game. I have the structure and card designs set up with CSS, now I just need to enable the actual playing of the game.
I need to have only two clicks allowed at a time. If the two cards match, the cards are removed. If the two cards don't match, they are "flipped" back over.
...I am only including the first row of the game, even though it is a 4x4 setup.
HTML
<div class="cardHolder">
<div id="card1" class="card" onClick="revealBlueCard()"></div>
<div id="card2" class="card" onClick="revealGreenCard()"></div>
<div id="card3" class="card" onClick="revealGreenCard()"></div>
<div id="card4" class="card" onClick="revealBlueCard()"></div>
</div>
JAVASCRIPT
// blue cards
var card1Ref = document.getElementById("card1");
var card4Ref = document.getElementById("card4");
card1Ref.addEventListener("click", revealBlueCard);
card4Ref.addEventListener("click", revealBlueCard);
function revealBlueCard(event){
event.target.style.backgroundColor = "#2155a8";
event.target.innerHTML = "<p>8</p>";
}
// green cards
var card2Ref = document.getElementById("card2");
var card3Ref = document.getElementById("card3");
card2Ref.addEventListener("click", revealGreenCard);
card3Ref.addEventListener("click", revealGreenCard);
function revealGreenCard(event){
event.target.style.backgroundColor = "#3cb260";
event.target.innerHTML = "<p>3</p>";
}
I am still very new to Javascript. I am assuming I am using a click event for "card" and applying if statements. I am also wondering if I need to apply data attributes to each card.
Why don't you add classes to the cards like blue class and green class.
CSS:
.blue{
background: #2155a8;
}
.green{
background: #3cb260
}
and also use event delegation (try to avoid adding event listeners to each card)
document.querySelector('#cardHolder').addEventListener('click', function(evt){
var clickedCard = evt.target;
if(clickedCard.classList.contains('blue'){
//do whatever for blue card
} else if(clickedCard.classList.contains('green')){
//do whatever for green card
}
});
there's a better way:
Use
onclick="cardClicked(this)"
for all your cards.
then in js
function cardClicked(elCard) {
if (elCard.classList.contains('flipped')) {
return;
}
// Flip it
elCard.classList.add('flipped');
I create simple grid application using basic grid example in visual studio and this tutorial. I expected this animation will work on all item's, but it seems that it works only on first one. My question is, how can I animate this on all item's? And if it is possible to animate randomly(not all at once! Example: windows 8 start menu).
Item template:
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
<div class="item">
<img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
<img class="item-image-new" src="#" data-win-bind="src: backgroundImage; alt: title" />
<div class="item-overlay">
<h4 class="item-title" data-win-bind="textContent: title"></h4>
<h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
</div>
</div>
</div>
Js animation:
var darkGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY3B0cPoPAANMAcOba1BlAAAAAElFTkSuQmCC";
var lightGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
var mediumGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
// Play the Peek animation
function peekTile(tile1, tile2) {
// Create peek animation
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-250px";
tile2.style.top = "0px";
// Execute animation
peekAnimation.execute();
}
function changeImage() {
// Get the two image elements
var images = document.querySelector(".item-image");
var imagesNew = document.querySelector(".item-image-new");
// Swap out the old image source and choose the new image source
images.src = imagesNew.src;
if (images.src == lightGray)
imagesNew.src = mediumGray;
else if (images.src == mediumGray)
imagesNew.src = darkGray;
else
imagesNew.src = lightGray;
// Reset the elements for the pre-animation position and trigger the animation
images.style.top = "0px";
imagesNew.style.top = "250px";
peekTile(images, imagesNew);
};
And interval, that changes images(it is written inside ready function):
setInterval(function () { changeImage() }, 4000);
When you call document.querySelector it will only return the first matching element, which in your case will be the first list item. If you want to animate any random item, just call document.querySelectorAll(".item"), pick a random item from the result list and then call querySelector('.item-image') on it, proceeding as you currently do.
I have series of divs, that represent similar to a chess board. but this is a kinda tricky chess. basically users clicks on a piece, and clicks on enemy piece. if it can kill. it should move it to the enemies position. And enemy should be deleted.
<div class="column" data-square="4-4">
<div class="white-king lol">a</div>
</div>
<div class="column" data-square="4-5">
<div class="black-pawn lol">b</div>
</div>
<div class="column" data-square="4-6">
<div class="blue lol">c</div>
</div>
//so when users first clicks on whiteking, we get the data-square, assign it to a variable $from, then clicks on enemy black-pawn. does some validation in server, and should move the
inner div of square = 4-4 to inner div of square = 4-5 , the inner div of square = 4-5 should be deleted and the inner div of square= 4-4 should be presnet
I have tried using jquery clone. but it doesnt works out well
fiddle: http://jsfiddle.net/jm4eb/13/
I personally wouldn't get too bent out of shape replacing one element with another. I'd look at just swapping the attributes from one element to another. Remove the white-king class from one element and add it to another.
This is not the good way still, but you can try
(function() {
var from = null;
var $change =null;
var to = null;
$(".column" ).click(function(){
if(from === null)
{
$(this).css("background-color","yellow");
from = $(this).data('square');
$change= ($('<div/>').append($(this).clone(true).children()).html());
}
else
{
to = $(this).data('square');
$(this).html("").html($change);
$('div[data-square="'+from+'"]').html("<div class=lol>empty</div>").css("background-color","");
from = to = null;
}
});
}());