I have a list of images and I want to be changed when I hover on it and then change back to the previous image on mouse leave. and each image is different. I have done it but the event is being executed on two images only when the mouse hovers on the first item. and I couldn't figure out the right way.
//html code//
<li>
<div class="card">
<img class="my-img" id="my-img1" src="./images/AMH010301_G-1-dresslink.jpg" alt="Denim Jeans">
<h1>Lorem1</h1>
<span class="price-first">$24.99</span>
<span class="price">$17.99</span>
<br>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star"></span>
<span class="fa fa-star"></span>
<p>Lorem ipsum dolor sit amet..</p>
<button class="add-to">Add to Cart</button>
</div>
</li>
<li>
<div class="card">
<img class="my-img" id="my-img2" src="./images/AMH010327_W-1-dresslink.jpg" alt="Denim Jeans">
<h1>Lorem2</h1>
<span class="price-first">$24.99</span>
<span class="price">$14.99</span>
<br>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star"></span>
<span class="fa fa-star"></span>
<p>Lorem ipsum dolor sit amet..</p>
<button class="add-to">Add to Cart</button>
</div>
</li>
//JavaScript//
let img = document.querySelectorAll('.card img');
for (var i = 0; i < img.length; i++) {
img[i].addEventListener('mouseover', hover);
img[i].addEventListener('mouseout', leave);
}
function hover() {
document.getElementById("my-img1").src = "./images/AMH010301_G-5-dresslink.jpg";
document.getElementById("my-img2").src = "./images/AMH010327_W-5-dresslink.jpg";
}
function leave() {
document.getElementById("my-img1").src = "./images/AMH010301_G-1-dresslink.jpg";
document.getElementById("my-img2").src = "./images/AMH010327_W-1-dresslink.jpg";
}
First it seems you are only attaching your event to one of the images and not both. The code below will loop through all of the images and attach event to them.
let img = document.querySelectorAll('.card img');
for (var i = 0; i < img.length; i++)
{
img[i].addEventListener('mouseover', hover);
img[i].addEventListener('mouseout', leave);
}
Second the event that you are attaching to the images does not look at which image is being hovered it just changes the images for both of them. The following code will look at the image that you are hovering over and only modify that.
function hover(e) { e.target.src = e.target.getAttribute("data-hover-img"); }
function leave(e) { e.target.src = e.target.getAttribute("data-leave-img"); }
Finally for each image to have different images to change to and from on and off hover you need to store that information somewhere connected to the image. I chose to go with data attributes as seen above. So the HTML for your images should look like this.
<img class="my-img" id="my-img1" src="./images/AMH010301_G-1-dresslink.jpg" data-hover-img=""./images/AMH010301_G-5-dresslink.jpg"" data-leave-img="./images/AMH010301_G-1-dresslink.jpg" alt="Denim Jeans">
<img class="my-img" id="my-img2" src="./images/AMH010327_W-1-dresslink.jpg" data-hover-img="./images/AMH010327_W-5-dresslink.jpg" data-leave-img="./images/AMH010327_W-1-dresslink.jpg" alt="Denim Jeans">
On every iteration you select the same image....
document.querySelector('.my-img') <-- selects first image with the class
So you just bound mouseover to the first image multiple times. Now if you fixed the loop to select the correct image, you still would have an issue because your hover code does not look know what image you are hovering and you change all of the images inside of the method.
So you could add in logic into the hover or you could just simplify your code.
So what you want to do is when you hover over an image it changes to a different image. One of the easiest things to do is to use data-attributes and a mouse events.
document.querySelectorAll('[data-src2]').forEach(function (img) {
img.addEventListener('mouseenter', function() {
if (!img.dataset.src) { // see if we hovered yet
img.dataset.src = this.src // if not set orginal source so we can flip back
}
img.src = this.dataset.src2 //set src to second image
})
img.addEventListener('mouseleave', function() {
img.src = this.dataset.src //set back to orginal
})
})
<img src="https://placekitten.com/200/300" data-src2="https://placekitten.com/g/200/300" />
<img src="https://placekitten.com/200/200" data-src2="https://placekitten.com/g/200/200" />
Are you asking how to register the eventlisteners and be able to backtrack which element fired the event? Something like:
img[i] = document.querySelector('.my-img').addEventListener('mouseover', function() { theselectedElement=i; hover();});
(2 statements- one for the event and another for the element) and then process the events depending on the selected element?
Related
I have two functions one thats triggered on a mouseenter event and the other on mouseleave. Both of these functions are repeated three times.
On mouseenter the classlist "active" is addded 5x and the text content is changed.
On mouseleave the classlist active is removed 5x and the text content is set to an empty string, and the original image is displayed again.
When the mouseenter event listener is triggered, Depending on which image is being hovered (3 images).
the text content property that gets added various between the three "Photosnap" "Dine" "Nike".
As-well as the background color that gets triggered various between "red" "blue" "pink".
Hover state shown as red left image and normal state shown as right image
-The image shown here is one of three. It is displayed with a red background and the text content of "photosnap".
-The other with a blue background and the text content of "Dine".
-The third and final with a pink background and the text content of "Nike".
I hope this paints a clear picture i am having a hard time making this a code snippet.
I am trying to refactor this javascript so its not so repetitive. I'm new to javascript and having a hard time getting this to work as something other than what i currently have. I'm not clear on how to make a function that i can call inside of other functions to cut down on the repeated code. Or possibly use the "this" keyword ?
Javascript--
// //Photosnap Project #1 ---------------------------------------------------------
// Content in project on hover
let projectTitle = document.querySelector('.projectTitlePhotosnap');
let projectLine = document.querySelector('.hoverLinePhotosnap');
// View live View code text wrapper
let projectRowWrap = document.querySelector('.flexWrapperRowPhotosnap');
// Background color + image
let photosnapBackground = document.querySelector('.photosnapBackground');
let photosnapImg = document.querySelector('.photosnap');
// Mouse in add background color title and links
photosnapBackground.addEventListener('mouseenter', function() {
photosnapBackground.classList.add('active');
photosnapImg.classList.add('active');
projectTitle.textContent = 'Photosnap';
projectTitle.classList.add('active');
projectLine.classList.add('active');
projectRowWrap.classList.add('active');
});
// Mouse out remove all
photosnapBackground.addEventListener('mouseleave', function() {
photosnapBackground.classList.remove('active');
photosnapImg.classList.remove('active');
dineBackground.classList.remove('active');
dineImg.classList.remove('active');
projectTitle.textContent = '';
projectTitle.classList.remove('active');
projectLine.classList.remove('active');
projectRowWrap.classList.remove('active');
});
//Dine Project #2 ---------------------------------------------------------------
// Content in project on hover
let projectTitleDine = document.querySelector('.projectTitleDine');
let projectLineDine = document.querySelector('.hoverLineDine');
// View live View code text wrapper
let projectRowWrapDine = document.querySelector('.flexWrapperRowDine');
// Background color + image
let dineBackground = document.querySelector('.dineBackground');
let dineImg = document.querySelector('.dine');
// Mouse in add background color title and links
dineBackground.addEventListener('mouseenter', function() {
dineBackground.classList.add('active');
dineImg.classList.add('active');
projectTitleDine.textContent = 'Dine';
projectTitleDine.classList.add('active');
projectLineDine.classList.add('active');
projectRowWrapDine.classList.add('active');
});
// Mouse out remove all
dineBackground.addEventListener('mouseleave', function() {
dineBackground.classList.remove('active');
dineImg.classList.remove('active');
projectTitleDine.textContent = '';
projectTitleDine.classList.remove('active');
projectLineDine.classList.remove('active');
projectRowWrapDine.classList.remove('active');
});
//Nike Project #3 ---------------------------------------------------------------
// Content in project on hover
let projectTitleNike = document.querySelector('.projectTitleNike');
let projectLineNike = document.querySelector('.hoverLineNike');
// View live View Code wrapper
let projectRowWrapNike = document.querySelector('.flexWrapperRowNike');
// Background color + image
let nikeBackground = document.querySelector('.nikeBackground');
let nikeImg = document.querySelector('.nike');
// Mouse in add background color title and links
nikeBackground.addEventListener('mouseenter', function() {
nikeBackground.classList.add('active');
nikeImg.classList.add('active');
projectTitleNike.textContent = 'Nike';
projectTitleNike.classList.add('active');
projectLineNike.classList.add('active');
projectRowWrapNike.classList.add('active');
});
// Mouse out remove all
nikeBackground.addEventListener('mouseleave', function() {
nikeBackground.classList.remove('active');
nikeImg.classList.remove('active');
projectTitleNike.textContent = '';
projectTitleNike.classList.remove('active');
projectLineNike.classList.remove('active');
projectRowWrapNike.classList.remove('active');
HTML--
<!-- Projects desktop -->
<div id="horizontalScroll" class="horizontalScroll projectsContainer">
<!-- Photosnap -->
<div class="projectsWrapper photosnapBackground">
<span class="testFunc hoverTitleFont projectTitlePhotosnap"></span>
<div class="testFunc hoverLine hoverLinePhotosnap"></div>
<img src="assets/projects/photosnap-desktop-p.jpg" alt="photosnap project" class="photosnap">
<div class="testFunc flexWrapperRow flexWrapperRowPhotosnap">
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Dine -->
<div class="projectsWrapper dineBackground">
<span class="testFunc hoverTitleFont projectTitleDine"></span>
<div class="testFunc hoverLine hoverLineDine"></div>
<img src="assets/projects/dine-desktop-p.png" alt="dine project" class="dine">
<div class="testFunc flexWrapperRow flexWrapperRowDine">
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Nike -->
<div class="projectsWrapper nikeBackground">
<span class="hoverTitleFont projectTitleNike"></span>
<div class="hoverLine hoverLineNike"></div>
<img src="assets/projects/nike-desktop-p.png" alt="nike project" class="nike">
<div class="flexWrapperRow flexWrapperRowNike">
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
</div>
Yes you're using 3 times the same function, so we sure can do better.
Here is a first simple idea, make a loop on the tree elements :
JAVASCRIPT
let slide = ['Photosnap', 'Dine', 'Nike'] ;
for (let i = 0; i < slide.length ; i++ ) {
let lowercaseName = slide[i].toLowerCase() ;
let projectTitle = document.querySelector('.projectTitle' + slide[i]);
let projectLine = document.querySelector('.hoverLine' + slide[i]);
// View live View code text wrapper
let projectRowWrap = document.querySelector('.flexWrapperRow'+ slide[i]);
// Background color + image
let background = document.querySelector('.'+ lowercaseName+'Background');
let img = document.querySelector('.'+ lowercaseName);
// Mouse in add background color title and links
background.addEventListener('mouseenter', function() {
background.classList.add('active');
img.classList.add('active');
projectTitle.textContent = slide[i];
projectTitle.classList.add('active');
projectLine.classList.add('active');
projectRowWrap.classList.add('active');
});
// Mouse out remove all
background.addEventListener('mouseleave', function() {
background.classList.remove('active');
img.classList.remove('active');
background.classList.remove('active');
img.classList.remove('active');
projectTitle.textContent = '';
projectTitle.classList.remove('active');
projectLine.classList.remove('active');
projectRowWrap.classList.remove('active');
});
}
Another approche, or to upgrate this solution can be use "data" attribute, like "data-id" or "data-color" you can give the name you want and have as many "data" atributes you want on DOM element.
You could save classname too, catching element's child of the main block with .childNodes.
I would suggest some updation in html structure before we move to javascript.
We want to keep HTML as much strucutural as we want. So that similar elements can be easily selected.
Make it easier to group project related element.
Remove unnecessary class name.
Added comments where every necessary.
<!-- Projects desktop -->
<div id="horizontalScroll" class="horizontalScroll projectsContainer">
<!-- Photosnap -->
<div class="projectsWrapper photosnap Background"> <!-- Remove backgound here, if you its needed for class selection in css seperate it -->
<span class="testFunc hoverTitleFont projectTitle"></span> <!-- Remove photosnap-->
<div class="testFunc hoverLine"></div> <!-- Remove hoverLinePhotosnap-->
<img src="assets/projects/photosnap-desktop-p.jpg" alt="photosnap project" class="photosnapImg"> <!-- Since there is only 1 img tag inside photosnap we can select through img tag-->
<div class="testFunc flexWrapperRow"> <!-- remove flexWrapperRowPhotosnap-->
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Dine -->
<div class="projectsWrapper dine Background"> <!-- seperated background-->
<span class="testFunc hoverTitleFont projectTitle"></span> <!--remove Dine-->
<div class="testFunc hoverLine"></div> <!--remove hoverLineDine-->
<img src="assets/projects/dine-desktop-p.png" alt="dine project" class="dineImg">
<div class="testFunc flexWrapperRow"> <!--removed flexWrapperRowDine-->
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Nike -->
<div class="projectsWrapper nike Background"> <!--seperated backgound-->
<span class="hoverTitleFont projectTitle"></span> <!--removed nike-->
<div class="hoverLine"></div> <!--removed hoverLineNike-->
<img src="assets/projects/nike-desktop-p.png" alt="nike project" class="nikeImg">
<div class="flexWrapperRow"> <!--removed flexWrapperRowNike-->
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
</div>
Now we have our proper html structure we can move to js
A function to add class and other property to the element
A function to remove class from the element
// property being an object {textContent: "photosnap", backgroundColor: "red"}
function addProperty(element, property) {
// I belive there are 4 Elements that need to be selected
const title = element.querySelector("projectTitle");
const projectLine = element.querySelector("hoverLine");
const projectRowWrap = element.querySelector("flexWrapperRow");
const image = element.querySelector("img");
// if removing looks like code duplicate elements can be pushed to an array, and iterate over it to add/remove the class
/*
const elementList = [];
elementList.push(element);
elementList.push(image);
elementList.push(title);
elementList.push(projectLine);
elementList.push(projectRowWrap);
elementList.forEach(el => {
el.classList.add("active");
});
*/
title.textContent = property.textContent;
element.classList.add("active");
image.classList.add("active");
title.classList.add("active");
projectLine.classList.add("active");
projectRowWrap.classList.add("active");
}
function removeProperty(element) {
const title = element.querySelector("projectTitle");
const projectLine = element.querySelector("hoverLine");
const projectRowWrap = element.querySelector("flexWrapperRow");
const image = element.querySelector("img");
title.textContent = "";
element.classList.remove("active");
image.classList.remove("active");
title.classList.remove("active");
projectLine.classList.remove("active");
projectRowWrap.classList.remove("active");
}
const element = document.querySelector("photosnap");
element.addEventListener("mouseenter", (event) => {
const eventElement = event.target;
const property = { textContent: "photosnap" };
addProperty(eventElement, property);
});
element.addEventListener("mouseleave", (event) => {
removeProperty(event.target);
});
Hi I am building a small slideshow of icons and also want to have data inside the icons like its speed and color. I've loaded jQuery from the top of my page.
<body>
<div class="main-container">
<div class="object-container">
<div class="icon-container">
<i class="fa fa-car" id="active"></i>
<i class="fa fa-bicycle" id="not-active"></i>
<i class="fa fa-plane" id="not-active"></i>
<i class="fa fa-ship" id="not-active"></i>
<i class="fa fa-fighter-jet" id="not-active"></i>
<i class="fa fa-space-shuttle" id="not-active"></i>
</div>
<div class="arrow-buttons">
</div>
</div>
</div>
</body>
Here is the jquery to press the right arrow button to change slide across the icons but it doesnt seem to be working?
$(document).ready(function(){
$('.right-arrow').on('click', function(){
let currentImg = $('#active');
let nextImg = currentImg.next();
if(currentImg.length){
currentImg.removeAttr('#active').css('z-inex', -10)
nextImg.attr('#active').css('z-index', 10);
}
});
});
First of all, I recommend using class instead of id. Even if you are going to use id, it is not recommended to use this way. The id value must be uniq. In your case, your ID's are not uniq. And also this is better to use like this ID selector.
id="notActive"
You can just try with each function to get current div. I tried with your code but did not work, with each yes.
$('.fa').each(function(){
if( $(this).hasClass('active') ){
currentImg = $(this);
}
})
And bonus : You can also use current div index value, then you dont have to use prev, next. You can increase or decrease index the value one by one. Just a suggestion.
You are using the id attribute incorrectly, as every id must be unique.
Also, setting the z-index on elements has no effect.
Finally, jQuery is not helping and can be eliminated.
Here's a more standard way to make something active/inactive, using a class named `active':
// control buttons
const right = document.querySelector('.right-arrow');
// handle right click
right.onclick = function() {
const activeImg = document.querySelector('i.active');
const nextImg = activeImg.nextElementSibling;
if (activeImg && nextImg) {
activeImg.classList.remove('active');
nextImg.classList.add('active');
}
};
i {
font-size: 32px;
z-index: -10; /* this has no effect */
}
.active {
z-index: 10;
background-color: yellow;
}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<div class="main-container">
<div class="object-container">
<div class="icon-container">
<i class="fa fa-car active"></i>
<i class="fa fa-bicycle"></i>
<i class="fa fa-plane"></i>
<i class="fa fa-ship"></i>
<i class="fa fa-fighter-jet"></i>
<i class="fa fa-space-shuttle"></i>
</div>
<div class="arrow-buttons">
right-arrow
</div>
</div>
</div>
I have the following code which adds divs within a container (#subtask_container) via clicking a link (similar to Google Tasks):
HTML:
<p class="text-muted">
<i class="fas fa-tasks mr-2"></i>
Add subtasks
</p>
<div id="subtask_container"></div>
JS (this successfully adds unique inputs within the subtask container div along with a clickable x after each input)
var i = 1
$("#add_subtask").click(function () {
$("#subtask_container").append('<input name="subtask'+i+'" class="mt-1" id="subtask'+i+'" placeholder="Enter subtask"><i class="fas fa-times ml-1 text-muted"></i><br>');
i++;
});
What logic do I need to add to the x class to remove it's associated input?
I've tried
$('.fa-times').click(function(){
$(this).prev('input').remove();
});
but it doesn't seem to work...
Thanks!
You can simply wrap your subtask append in a div and simply use .parent() and .remove() function on that. No need to use <br>
Also, do not use .fa-times as primary click event handler as you might have other fa-times on the same page as well Which might cause issues later on. Add a custom class to your fa item (.subtask_remove_icon)
Live Demo:
var i = 1
$("#add_subtask").click(function() {
$("#subtask_container").append('<div><input name="subtask' + i + '" class="mt-1" id="subtask' + i + '" placeholder="Enter subtask"><i class="fas fa-times ml-1 text-muted subtask_remove_icon"></i></div>');
i++;
});
$(document).on('click', '.subtask_remove_icon', function() {
$(this).parent().remove(); //remove the input when X clicked
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<p class="text-muted">
<i class="fas fa-tasks mr-2"></i>
Add subtasks
</p>
<div id="subtask_container"></div>
The event handler gets attached to all elements that are on the page load. Since the icons are appended, the right way to do this would be the following:
var i = 1
$("#add_subtask").click(function () {
$("#subtask_container").append('<div><input name="subtask'+i+'" class="mt-1" id="subtask'+i+'" placeholder="Enter subtask"><i class="fas fa-times ml-1 text-muted removeIcon"></i><br></div>');
i++;
});
$(document).on('click', '.removeIcon', function(){
$(this).parent().remove();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<p class="text-muted">
<i class="fas fa-tasks mr-2"></i>
Add subtasks
</p>
<div id="subtask_container"></div>
what i want to do is to click on this icons (there are like 16 per website, one by one, click the first, go to the next available, etc....
To understanding...
And sometimes it has this other eye icon: (it changes the code a bit)
I know we could do it from the console, but for comfort i would prefer to do this from the bookmarks (adding the code to a bookmark, then click it when i need it)
So, what i know (thanks to #Sphinx) is that we have to write in a bookmarkletjavascript:$("span.icon.icon_eye").click() but the main problem is that when i click it, it clicks the first icon eye, and i need to click first the 1st eye icon, then the second, then the third, etc...
Based on your comments, below codes should be what you need.
bind click event for all span.icon_eye.
Click each <span class="icon icon_eys"> second by second (setTimeout).
function clickSomething() {
$('span.icon.icon_eye').on('click', function(){console.log('You clicked', $(this).html())});
$('span.icon.icon_eye').each(function(index){setTimeout(()=>{$(this).click()}, index*1000);});
}
setTimeout(clickSomething, 1000)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span class="icon icon_eye">A</span>
<span class="icon icon_eye">B</span>
<span class="icon icon_eye">C</span>
<span class="icon icon_eye">D</span>
<span class="icon icon_eye">E</span>
<span class="icon icon_eye">F</span>
</div>
try:
var currentBookmark = $($('.icon_eye').get(0));
var bookmarkClicker = function() {
console.log('you clicked bookmark at ' + currentBookmark.text());
setTimeout(function() {
currentBookmark = currentBookmark.next('.icon_eye');
if (currentBookmark) {
currentBookmark.on('click', bookmarkClicker);
currentBookmark.click();
}
}, 500);
};
currentBookmark.on('click', bookmarkClicker);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span class="icon icon_eye">A</span>
<span class="icon icon_eye">B</span>
<span class="icon icon_eye">C</span>
<span class="icon icon_eye">D</span>
<span class="icon icon_eye">E</span>
<span class="icon icon_eye">F</span>
</div>
I've code few line of jQuery for Hide/Show many elements on single click and it's working. But problem is; i've many more image class items, so my script going to long, my question is how to simplify or make short my script, i mean any alternatives or any new idea? please suggest.
HTML:
<div id="choose-color">
<span>
<i class="images-red" style="">Red Image</i>
<i class="images-blue" style="display: none;">Blue Image</i>
<i class="images-pink" style="display: none;">Pink Image</i>
<!-- many many images -->
</span>
<button class="red">Red</button>
<button class="blue">Blue</button>
<button class="pink">Pink</button>
</div>
JS: live demo >
$("button.red").click(function(){
$(".images-red").show();
$(".images-blue, .images-pink").hide();
});
$("button.blue").click(function(){
$(".images-red, .images-pink").hide();
$(".images-blue").show();
});
$("button.pink").click(function(){
$(".images-red, .images-blue").hide();
$(".images-pink").show();
});
Please suggest for short and simple code of my script. Thanks.
You can do it by adding just a common class to those buttons,
var iTags = $("#choose-color span i");
$("#choose-color button.button").click(function(){
iTags.hide().eq($(this).index("button.button")).show();
});
The concept behind the code is to bind click event for the buttons by using the common class. Now inside the event handler, hide all the i elements which has been cached already and show the one which has the same index as clicked button.
DEMO
For more details : .eq() and .index(selector)
And if your elements order are not same, both the i and button's. Then you can use the dataset feature of javascript to over come that issue.
var iTags = $("#choose-color span i");
$("#choose-color button.button").click(function(){
iTags.hide().filter(".images-" + this.dataset.class).show()
});
For implementing this you have to add data attribute to your buttons like,
<button data-class="red" class="button red">Red</button>
DEMO
This works
$("#choose-color button").click(function(){
var _class = $(this).attr('class');
$("#choose-color i").hide();
$(".images-"+_class).show();
});
https://jsfiddle.net/455k1hhh/5/
I know this might not be the prettiest solution, but it should do the job.
$("button").click(function(){
var classname = $(this).attr('class');
$("#choose-color span i").hide();
$(".images-"+classname).show();
});
You're making future extensibility a little difficult this way due to relying on class names but this would solve your immediate need:
<div id="myImages">
<i class="images-red" style="">Red Image</i>
<i class="images-blue" style="display: none;">Blue Image</i>
<i class="images-pink" style="display: none;">Pink Image</i>
<!-- Many many image -->
</div>
<div id="myButtons">
<button class="red">Red</button>
<button class="blue">Blue</button>
<button class="pink">Pink</button>
</div>
$("#myButtons button").click(function(){
var color = $(this).attr("class");
var imageClass = ".images-"+color;
$('#myImages').children("i").each(function () {
$(this).hide();
});
$(imageClass).show();
});
Here's a JSFiddle
Edit: Note how I wrapped the buttons and images in parent divs to allow you to isolate just the buttons/images you want to work with.
You can do the following using data-* attributes, because when you have more elements of the same color, using index of the button won't work. And simply using the whole class attribute won't work if you have to add more classes to the button in future.
$("button").click(function() {
var color = $(this).data('color');
var targets = $('.images-' + color);
targets.show();
$("span i").not(targets).hide();
});
.hidden {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<br/>
<br/>
<div id="choose-color">
<span>
<i class="images-red">Red Image</i>
<i class="images-blue hidden">Blue Image</i>
<i class="images-pink hidden">Pink Image</i>
<!-- Many many image -->
</span>
<br/>
<br/>
<button data-color="red">Red</button>
<button data-color="blue">Blue</button>
<button data-color="pink">Pink</button>
</div>
It would make sense to have all images share a single class (.image for example). Then you just use a shared class for the button and the image; in this example I used the color name. Now, when any button is clicked, you can grab the class name of the image you want to show.
Give this a try:
$("button").click(function(){
$(".image").hide();
var className = $(this).attr("class");
$("." + className).show();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<br/><br/>
<div id="choose-color">
<span>
<i class="image red" style="">Red Image</i>
<i class="image blue" style="display: none;">Blue Image</i>
<i class="image pink" style="display: none;">Pink Image</i>
<!-- Many many image -->
</span>
<br/><br/>
<button class="red">Red</button>
<button class="blue">Blue</button>
<button class="pink">Pink</button>
</div>
You may try this:
<div id="choose-color">
<span>
<i class="images-red" style="">Red Image</i>
<i class="images-blue" style="display: none;">Blue Image</i>
<i class="images-pink" style="display: none;">Pink Image</i>
<!-- Many image -->
</span>
<br/><br/>
<button class="colour red" onclick="myFunction(this)">Red</button>
<button class="colour blue" onclick="myFunction(this)">Blue</button>
<button class="colour pink" onclick="myFunction(this)">Pink</button>
</div>
JS: see here
$(".colour").click(function(){
var colors = ["red", "blue", "pink"];
for (i = 0; i < colors.length; i++) {
if($(this).hasClass(colors[i])){
$(".images-"+colors[i]).show();
}else{
$(".images-"+colors[i]).hide();
}
}
});