Essentially I have an interactive map which contains 4 div statements each of which contains an image of an island. I would like to create an on hover event which will display a corresponding sailing timetable depending on which image the user hovers. e.g. island 1 should display timetable 1.
I have the following code so far and ideally I am looking for a javascript or css solution:
<div class="Map">
<div id="Island_Morar">
<img src="images/IsleOfMorar.jpg"/>
</div>
<div id="Island_Rum">
<img src="images/IsleOfRum.jpg"/>
</div>
<div id="Island_Eigg">
<img src="images/IsleOfEigg.jpg"/>
</div>
<div id="Island_Muck">
<img src="images/IsleOfMuck.jpg"/>
</div>
</div>
<img id="TimetableEigg" src="images/TimetableEigg.jpg">
any help is appreciated.
You need some different markup if you want a plain css solution. If you want to have different timetables for each hover you should go with something like this:
markup
<div class="tt-container" id="Island_Rum">
<img src="images/IsleOfRum.jpg"/>
<img class="timetable" src="images/TimetableRum.jpg">
</div>
<div class="tt-container" id="Island_Eigg">
<img src="images/IsleOfEigg.jpg"/>
<img class="timetable" src="images/TimetableEigg.jpg">
</div>
<div class="tt-container" id="Island_Muck">
<img src="images/IsleOfMuck.jpg"/>
<img class="timetable" src="images/TimetableMuck.jpg">
</div>
</div>
css
.timetable {
display : none;
}
.tt-container:hover .timetable {
display : block;
}
That should do the trick
If you want to keep your current HTML code, I'd make three image blocks for timetables, and initially set them all to display: none; and add onmouseover event handlers to island elements which would contain Javascript statement which will set disply: block; on appropriate timetable.
Something like this:
<div class="Map">
<div id="Island_Morar" onmouseover="document.getElementById('TimetableEigg1').style.display = 'block';">
<img src="images/IsleOfMorar.jpg"/>
</div>
<div id="Island_Rum" onmouseover="document.getElementById('TimetableEigg2').style.display = 'block';" >
<img src="images/IsleOfRum.jpg"/>
</div>
<div id="Island_Eigg" onmouseover="document.getElementById('TimetableEigg3').style.display = 'block';" >
<img src="images/IsleOfEigg.jpg"/>
</div>
<div id="Island_Muck" onmouseover="document.getElementById('TimetableEigg4').style.display = 'block';" >
<img src="images/IsleOfMuck.jpg"/>
</div>
</div>
<img id="TimetableEigg1" src="images/TimetableEigg1.jpg">
<img id="TimetableEigg2" src="images/TimetableEigg2.jpg">
<img id="TimetableEigg3" src="images/TimetableEigg3.jpg">
<img id="TimetableEigg4" src="images/TimetableEigg4.jpg">
Seems you barely know the basics of HTML and already trying to jump too deep. External libraries will help you and speed up your progress. I see people gave you CSS solutions so here is a JS solution.
First thing is download the well known JS library called jQuery.
then load this file to your page and add a script at the bottom of your body tag:
$("div.map").on("mouseover", "#Island_Morar", function(e) {
$(this).show(); // option one
//$(this).addClass("class-name"); // option two
}).on("mouseout", "#Island_Morar", function(e) {
$(this).hide(); // option one
//$(this).removeClass("class-name"); // option two
});
With this script you can do whatever you want, for example - use the second option of adding and removing classes in order to animate your Timetables (see Example).
Possible CSS / JQuery solution:
$(".Map a").hover(
function() {
$('#' + $(this).attr('class')).show();
}, function() {
$('#' + $(this).attr('class')).hide();
}
);
.timetables img { display:none; }
<div class="Map">
<a href="#" class="islandmorar">
<img src="images/IsleOfMorar.jpg"/>
</a>
<a class="islandrum">
<img src="images/IsleOfRum.jpg"/>
</a>
<a class="islandeigg">
<img src="images/IsleOfEigg.jpg"/>
</a>
<a class="islandmuck">
<img src="images/IsleOfMuck.jpg"/>
</a>
</div>
<div class="timetables">
<img id="islandmorar" src="images/TimetableEigg.jpg"/>
<img id="islandrum" src="images/TimetableEigg.jpg"/>
<img id="islandeigg" src="images/TimetableEigg.jpg"/>
<img id="islandmuck" src="images/TimetableEigg.jpg"/>
</div>
Pure CSS solution but you need to place the large image in .main div
the first image will be displayed first and will change on hover on other images and when you leave move out of the main div it will show the first image
Note: used random images
.Map > div {
display: inline-block;
}
img.two,
img.three,
img.four,
#Island_Rum:hover ~ img.one,
#Island_Muck:hover ~ img.one,
#Island_Eigg:hover ~ img.one {
display: none;
}
img.one {
display: block;
}
#Island_Morar:hover ~ img.one {
display: block;
}
#Island_Rum:hover ~ img.two {
display: block;
}
#Island_Eigg:hover ~ img.three {
display: block;
}
#Island_Muck:hover ~ img.four {
display: block;
}
<div class="Map">
<div id="Island_Morar">
<img src="http://placeimg.com/100/100/any/animals" />
</div>
<div id="Island_Rum">
<img src="http://placeimg.com/100/100/any/arch" />
</div>
<div id="Island_Eigg">
<img src="http://placeimg.com/100/100/any/nature" />
</div>
<div id="Island_Muck">
<img src="http://placeimg.com/100/100/any/tech" />
</div>
<img class="one" src="http://placeimg.com/400/400/any/animals" />
<img class="two" src="http://placeimg.com/400/400/any/arch" />
<img class="three" src="http://placeimg.com/400/400/any/nature" />
<img class="four" src="http://placeimg.com/400/400/any/tech" />
</div>
Don't put class="map" to the wrapper div, give it to every div with id beginning with "Island_...".
Do the same with your timeTable images, give them a class "timeTable".
Put this before your "head" end tag :
<script>
"use strict";
//wait for every element to be loaded
window.onload = function(){initialization();}
</script>
Then, put this before your "body" end tag :
<script>
"use strict";
//first create a function that hides elements with class 'timeTable'
function hide(elements){
var htmlClass = document.getElementsByClassName(elements);
//hide every element with class
for (var i = 0 ; i < htmlClass.length ; i++){
htmlClass[i].style.display = "none";
htmlClass[i].style.visibility = "hidden";
}
}
//create a function that show only the timeTable you want
function show(element){
document.getElementById(element).style.display = "block";
document.getElementById(element).style.visibility = "visible";
}
function initialization(){
//replace 'someMapId' with the id of the image you are hovering
//replace 'someTimeTableId' with the id of the image you want to show
//replace 'timeTable' with the name of a class you want to hide
document.getElementById("someMapId").onmouseover = function(){
hide("timeTable");
show("someTimeTableId");
}
//repeat these 3 lines for every image the user will hover
}
</script>
Don't forget the quotes when using the functions.
You should use css for styling and javascript for interactions.
You don't need jQuery for basic scripts like that, it only slows page loading and keeps you away from learning basic javascript.
(Ok, I edited mistakes, now it works ;)
jsFiddle
Related
I was looking for a way to change image A to B and B to A by just
clicking them.
So far, this is what I'm using.
<img id="pixelbutton" src="images/pixelbutton.png" />
<img id="pixelbutton2" src="images/pixelbutton_press.png" style="display: none;" />
<script type="text/javascript">
$(document).ready(function(){
$("#pixelbutton").click(function(){
$("#pixelbutton").css({'display':'none'})
$("#pixelbutton2").css({'display':'block'});
})
$("#pixelbutton2").click(function(){
$("#pixelbutton2").css({'display':'none'})
$("#pixelbutton").css({'display':'block'});
})
})
</script>
The script works well for a pair of image.
Now if I have 100 pair of image.
"A <--> B"
"C <--> D"
"E <--> F"
and so on...
Do I have to copy the body HTML and script 100 times and change their ID+URL or there is another more efficient way?
To create hundreds of them... First, use a class.
Then, use a data attribute to store the "alternate" URL.
<img class="pixelbutton" src="images/pixelbutton.png" data-altsrc="images/pixelbutton_press.png"/>
<script type="text/javascript">
$(document).ready(function(){
$(".pixelbutton").click(function(){
// Get the two values
var src = $(this).attr("src");
var altSrc = $(this).data("altsrc");
// Switch them
$(this).attr("src",altSrc).data("altsrc",src);
});
})
</script>
This will work for thousands of .pixelbutton...
;)
EDIT
As per this other .data() documentation, (I wonder why there's two different documentation pages...) the data-* have to be lowercase... Because when trying to get altSrc, it is interpreted as alt-src.
I just learned that... That is quite a strange new standard, from jQuery 3.
So here is your CodePen updated.
You could probably set a naming pattern and use delegation to make an event handler on the images' container.
You could check if the event's target is an image and retrieve its id. Using that id, you could use the pattern you've set to change the images interchangeably.
There are multiple solutions to this, but this is by far the simplest approach:
Wrap your image pairs in a parent <div>
Use .toggleClass() to toggle a class, say .hide, in the images in the element
This solution assumes that you have images in pairs :) see proof-of-concept example:
$(document).ready(function() {
$('img').click(function() {
console.log($(this).siblings());
$(this).add($(this).siblings()).toggleClass('hide');
});
});
/* For layout only */
div {
display: inline-block;
}
/* Used to hide image */
.hide {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<img src="http://via.placeholder.com/100x100/999999/ffffff" />
<img src="http://via.placeholder.com/100x100/b13131/ffffff" class="hide" />
</div>
<div>
<img src="http://via.placeholder.com/100x100/999999/ffffff" />
<img src="http://via.placeholder.com/100x100/b13131/ffffff" class="hide" />
</div>
<div>
<img src="http://via.placeholder.com/100x100/999999/ffffff" />
<img src="http://via.placeholder.com/100x100/b13131/ffffff" class="hide" />
</div>
<div>
<img src="http://via.placeholder.com/100x100/999999/ffffff" />
<img src="http://via.placeholder.com/100x100/b13131/ffffff" class="hide" />
</div>
<div>
<img src="http://via.placeholder.com/100x100/999999/ffffff" />
<img src="http://via.placeholder.com/100x100/b13131/ffffff" class="hide" />
</div>
<div>
<img src="http://via.placeholder.com/100x100/999999/ffffff" />
<img src="http://via.placeholder.com/100x100/b13131/ffffff" class="hide" />
</div>
Try this one:
jQuery(document).ready(function($) {
var $imgBlock = $('#images');
var html = '';
var imgArr = [
'http://i0.wallpaperscraft.com/image/surface_shape_metal_116716_200x300.jpg',
'http://i0.wallpaperscraft.com/image/universe_space_face_rocket_116714_200x300.jpg',
'http://i0.wallpaperscraft.com/image/letter_surface_wooden_116674_200x300.jpg',
'http://i0.wallpaperscraft.com/image/mountains_lake_reflection_116663_200x300.jpg',
'http://i1.wallpaperscraft.com/image/leaf_drops_surface_116678_200x300.jpg',
'http://i1.wallpaperscraft.com/image/candle_spruce_christmas_decoration_116684_200x300.jpg'
];
$.each(imgArr, function(index, url) {
html += (index % 2 === 0) ? '<div>' : '';
html += '<img src="' + url + '"/>';
html += (index % 2 === 1 || index === imgArr.length - 1) ? '</div>' : '';
});
$imgBlock.append(html);
$imgBlock.on('click', 'img', function(e) {
$(this).parent('div').find('img').removeClass('red');
$(this).addClass('red');
});
});
img {
border: 2px solid #ccc;
}
.red {
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="images"></div>
I have a problem and I need your help. I have several links (in <aside>) leading to several different menus (in <section>). On click over the link, only the relevant div in <section> is shown, the rest are hidden. This part is ok and working. What is not working is when I click over an image:
the current div (.menu) in <section> should be hidden;
the same picture (with bigger size) should be shown;
when you click once again over the big image, the big image should disappear and the current div in .menu (the one that was hidden on the first step) should appear one more time. Sort of toggling between content.
So if I click on a picture on the "second div" content, the same picture with bigger size should be show (the "second div" content should be hidden) and when I click once again over the big picture it should disappear and the "second div" content to be returned.
I tried with toggle() but had no success. Either I did not use it correctly, or it is not suitable for my case. This is where I managed to reach to.
I will really appreaciate your support - how to show only the hidden div, not all hidden div's. Right now, when you click on the big image it did not show the hidden div.
$(window).on("load", function() {
$("div.menu:first-child").show();
});
$(".nav a").on("click", function() {
$("div.menu").fadeOut(30);
var targetDiv = $(this).attr("data-rel");
setTimeout(function() {
$("#" + targetDiv).fadeIn(30);
}, 30);
});
var pictures = $(".img-1, .img-2").on("click", function() {
$("div.menu:active").addClass("hidden");
//how to reach out only the current, active div (not all div's in .menu)?
$(".menu").hide();
var par = $("section")
.prepend("<div></div>")
.append("<img id='pic' src='" + this.src + "'>");
var removePictures = $("#pic").on("click", function() {
$(this).hide();
$(".hidden").show();
});
});
.menu {
width: 100%;
display: none;
}
.menu:first-child {
display: block;
}
.row {
display: inline-block;
width: 100%;
}
.img-1,
.img-2 {
width: 120px;
height: auto;
}
<!doctype html>
<html>
<head>
</head>
<body>
<aside>
<ul class="nav">
<li>To first div
</li>
<li>To second div
</li>
<li>To third div
</li>
</ul>
</aside>
<section>
<div class="menu" id="content1">
<h3>First Div</h3>
<div class="present">
<div class="row">
<div>
<p>Blah-blah-blah. This is the first div.</p>
<img class="img-1" src="http://www.newyorker.com/wp-content/uploads/2014/08/Stokes-Hello-Kitty2-1200.jpg">
</div>
</div>
<div class="row">
<div>
<img class="img-2" src="https://jspwiki-wiki.apache.org/attach/Slimbox/doggy.bmp">
<p>Blah-blah-blah. This is the first div.</p>
</div>
</div>
</div>
</div>
<div class="menu" id="content2">
<h3>Second Div</h3>
<div class="present">
<div class="row">
<div>
<p>
Blah-blah-blah. This is the second div.
</p>
<img class="img-1" src="http://www.newyorker.com/wp-content/uploads/2014/08/Stokes-Hello-Kitty2-1200.jpg">
</div>
</div>
<div class="row">
<div>
<img class="img-2" src="https://jspwiki-wiki.apache.org/attach/Slimbox/doggy.bmp">
<p>
Blah-blah-blah. Yjis is the second div.
</p>
</div>
</div>
</div>
</div>
<div class="menu" id="content3">
<h3>Third Div</h3>
<div class="present">
<div class="row">
<div>
<p>
Blah-blah-blah. This is the third div.
</p>
<img class="img-1" src="http://www.newyorker.com/wp-content/uploads/2014/08/Stokes-Hello-Kitty2-1200.jpg">
</div>
</div>
<div class="row">
<div>
<img class="img-2" src="https://jspwiki-wiki.apache.org/attach/Slimbox/doggy.bmp">
<p>
Blah-blah-blah. This is the third div.
</p>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
</body>
</html>
Sorry for the ugly sketch and pictures - it is only to get an idea what it should look like....
In general, it's poor form to ask on Stack Overflow how to code for a specific behavior. However, that takes some understanding of the libraries you're using, and what you are trying to achieve. Hopefully, my answer will help you better articulate and form your questions in the future.
Here's a fiddle for you: https://jsfiddle.net/hwd4b0ag/
In particular, I've modified your last click listener:
var pictures = $(".img-1, .img-2").on("click", function() {
var parentDiv = $(this).closest('div.menu').hide();
var blownUpPic = $("<img>").attr({
id: 'pic',
src: this.src,
'data-parent': parentDiv.attr('id')
})
.appendTo("section")
.on('click', function() {
$('#' + $(this).attr('data-parent')).show();
$(this).remove();
});
});
Now, let's review it!
First,
var parentDiv = $(this).closest('div.menu').hide();
In a jQuery listener, the this variable stores the current javascript DOM element that is the recipient of the event listener. In your case, it refers to an element that matches ".img-1, .img-2".
.closest(selector) will traverse up the DOM (including the current element) and find the first matching element for the provided selector. In this case, it finds your container div with class menu. Then we hide that div and save a reference to it in a variable.
Next, we create a full-sized version of the picture and assign it some attributes:
var blownUpPic = $("<img>").attr({
id: 'pic',
src: this.src,
'data-parent': parentDiv.attr('id')
})
We set the data-parent attribute to the id of our container div, so we have a reference back to it later.
We then add our image to the DOM:
.appendTo("section")
And declare a new click listener for it:
.on('click', function() {
$('#' + $(this).attr('data-parent')).show();
$(this).remove();
});
With $(this).attr('data-parent') we use the reference to our container div that we assigned earlier, and then retrieve that element by its id. We unhide the container div and remove the full-sized image.
All done!
There are better ways to code this, but I think this is a good next step for you that's analogous to your current code.
I have a div called masterdiv, inside this div there are 3 other div div1, div2, and div3,
This is the html for these html:
<div id="masterdiv" class="masterdivclass">
<div id="div1"><img class="div1class" src="image1.jpg" id="div1id" /></div>
<div id="div2"><img class="div2class" src="image2.jpg" id="div2id" /></div>
<div id="div3"><img class="div3class" src="image3.jpg" id="div3id" /></div>
</div>
I also have another div:
<div id=”reload”><img src="reload.png" width="200" height="70" onclick=loadDIV();></div>
What I’m trying to do is to reload the masterdiv div whenever the reload div is clicked on. Hiding and then showing the div isn’t enough as I need the content to be reloaded when the refresh div is clicked on. I don’t want to reload the entire page, just the masterdiv which contains the 3 other div. But I’m not certain this is possible.
I’m trying to do it with this Javascript function:
<script type="text/javascript">
function loadDiv(){
$("<div id="masterdiv" class="masterdivclass">
<div id="div1"><img class="div1class" src="image1.jpg" id="div1id" /></div>
<div id="div2"><img class="div2class" src="image2.jpg" id="div2id" /></div>
<div id="div3"><img class="div3class" src="image3.jpg" id="div3id" /></div>
</div>").appendTo("body");
}
</script>
This isn’t working, I think maybe I'm going about this in the wrong way? Maybe I’m missing something very simple here? I’d really appreciate any help with this, thank you in advance!
UPDATE
After reconsidering my project's requirements, I need to change part of my question, I now need to randomise the images displayed in the divs, and have a new random image load every time the reload div is clicked on. I also need to remove each class that’s currently in each of the three divs and then reattach the same classes to the divs (if I don’t remove and reattach the classes then the divs just display the plain images without any class/effect applied to them, it seems like I need to reload the class every time I load an image into a div in order for the class/effect to be applied successfully).
I have 5 images, and I’m using each div’s id tag to attach a random image to each div.
First I’m assigning the 5 different images to 5 different ids:
<script>
document.getElementById('sample1').src="images/00001.jpg";
document.getElementById('sample2').src="images/00002.jpg";
document.getElementById('sample3').src="images/00003.jpg";
document.getElementById('sample4').src="images/00004.jpg";
document.getElementById('sample5').src="images/00005.jpg";
</script>
And then I’m trying to use the following Javascript to load a randomised id (and its assigned image) to each of the 3 divs when the reload div is clicked:
<script>
$(function() {
$('#reload').on('click',function(){
$("#masterdiv").find("div[id^='div']").each(function(index){
//First, remove and reattach classes “div1class”, “div2class” and “div3class”
//from “easyDIV”, “mediumDIV” and “hardDIV” respectively:
$(“#easyDIV”).removeClass('div1class');
$(“#easyDIV”).addClass('div1class');
$(“#mediumDIV”).removeClass('div2class');
$(“#mediumDIV”).addClass('div2class');
$(“#hardDIV”).removeClass('div3class');
$(“#hardDIV”).addClass('div3class');
//Get a random number between 1 and 5, then attach it to “sample”,
//so that the result will be either “sample1”, “sample2”, “sample3”, “sample4” or “sample5”,
//call this variable “variablesample”:
var num = Math.floor(Math.random() * 5 + 1);
variablesample = "sample" +num;
//Attach this randomised id to all three divs using “variablesample”:
jQuery(this).prev("easyDIV").attr("id",variablesample);
jQuery(this).prev("mediumDIV").attr("id",variablesample);
jQuery(this).prev("hardDIV").attr("id",variablesample);
});
var p = $("#masterdiv").parent();
var el = $("#masterdiv").detach();
p.append(el);
});
});
</script>
I’m trying to make it so that all 3 divs will show the same randomised picture (that’s why they’re all sharing the variable “variablesample”), and each div will reload its own class/effect (div1class, div2class and div3class) but it’s not working. I’m not sure if it’s correct to use jQuery inside a Javascript function, or if my syntax for updating the ids of the divs is incorrect.
Perhaps my logic to solving this problem is all wrong? I’d really appreciate any more help with this problem. Thanks again in advance!
Original question was edited many times, so here is the correct answer for the latest edit. Answer to the question; "How to use random image, but same image on all 3, and 3 class on/off switching":
$(function() {
var imageArray = [
'https://via.placeholder.com/40x40',
'https://via.placeholder.com/80x40',
'https://via.placeholder.com/120x40',
'https://via.placeholder.com/160x40',
'https://via.placeholder.com/200x40'];
reloadImages(imageArray);
$('#reload').on('click',function(){
$( "#masterdiv img[id^='div']" ).each(function(index){
$(this).removeClass("div"+(index+1)+"class");
$(this).fadeOut( "slow", function() {
if(index==0) {
reloadImages(imageArray);
}
$(this).addClass("div"+(index+1)+"class");
$(this).fadeIn();
});
});
});
});
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function reloadImages(array){
shuffleArray(array);
for(var i=0;i<3;i++){
// places the first image into all divs, change 0 to i if you want different images in each div
document.getElementById('div'+(i+1)+'id').src=array[0];
}
}
.div1class {
border:2px dashed #0F0;
}
.div2class {
border:2px dashed yellow;
}
.div3class {
border:2px dashed red;
}
#reload {
background-color:blue;
color:white;
width:100px;
height:30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='reload'>Click here</div>
<div id="masterdiv" class="masterdivclass">
<div id="div1">
<img src="https://via.placeholder.com/20x40" class="div1class" id="div1id" />
</div>
<div id="div2">
<img src="https://via.placeholder.com/20x40" class="div2class" id="div2id" />
</div>
<div id="div3">
<img src="https://via.placeholder.com/20x40" class="div3class" id="div3id" />
</div>
</div>
Line breaks and un-escaped quotes are why the functions is not working.
function loadDiv(){
$('#masterdiv').remove();
$("<div id='masterdiv' class='masterdivclass'><div id='div1'><img class='div1class' src='image1.jpg' id='div1id' /></div><div id='div2'><img class='div2class' src='image2.jpg' id='div2id' /></div><div id='div3'><img class='div3class' src='image3.jpg' id='div3id' /></div></div>").appendTo("body");
}
try:
function loadDiv(){
$("#masterdiv").load(location.href + " #masterdiv");
}
Here's the code pen demo:
http://codepen.io/anon/pen/xwgRWm
If content of container is not being changed dynamically then there is no point reloading it. appendTo wiil append DOM in existing DOM structure, you will need html() here which will replace the content inside container. Also note you had typo here onclick=loadDiv();
HTML:
<div id="masterdiv" class="masterdivclass">
<div id="div1"><img class="div1class" src="image1.jpg" id="div1id"/></div>
<div id="div2"><img class="div2class" src="image2.jpg" id="div2id"/></div>
<div id="div3"><img class="div3class" src="image3.jpg" id="div3id"/></div>
</div>
<div id="reload"><img src="reload.png" width="200" height="70" onclick=loadDiv();></div>
JS:
function loadDiv() {
$("#masterdiv").html('<div id="div1"><img class="div1class" src="image1.jpg" id="div1id" /></div>\
<div id="div2"><img class="div2class" src="image2.jpg" id="div2id" /></div>\
<div id="div3"><img class="div3class" src="image3.jpg" id="div3id" /></div>');
}
I have two matching div that are siblings, they each have 2 images in them. I have one image showing in each sibling div by default and the other hidden. I then have a control to click to hide the current image and show the other.
My problem is that only the images in the first div are updating, the images in the second div are not changed.
I'm being fairly generic in my traversal, not a lot of specific classes, and I need to keep it that way.
Feels like I'm missing something really simple or maybe I'm not understanding how .eq() works in some way that limits the change to the first ".images" div?
How can I fix this to have the images in both divs change at the same time?
My html is is basically:
<div class="main">
<div class="image-group">
<h2> Title </h2>
<div class="color-selection">
<img alt="Black and Red" title="Black and Red">
<img alt="Black and Matte Black" title="Black and Matte Black">
</div>
<div class="images">
<img style="display: inline;">
<img style="display: none;">
</div>
<div class="images">
<img style="display: inline;">
<img style="display: none;">
</div>
</div><!--end image group -->
<div class="image-swap">
<i class="js-profile current">View 1</i>
<i class="js-angle">View 2</i>
</div>
</div><--/end main -->
And the jquery:
$(document).on("click" , ".js-profile" , function(){
var itemImage = $(this).parent().prev().find(".images img");
$(itemImage).eq(1).fadeOut(200);
$(itemImage).eq(0).fadeIn(200);
$(this).addClass("current");
$(this).next().removeClass("current");
return false;
})
$(document).on("click" , ".js-angle" , function(){
var itemImage = $(this).parent().prev().find("images img");
$(itemImage).eq(0).fadeOut(200);
$(itemImage).eq(1).fadeIn(200);
$(this).addClass("current");
$(this).prev().removeClass("current");
return false;
})
Firstly, you have some naming issues:
var bikeImage = $(this).parent().prev().find("images img");
$(itemImage).eq(0).fadeOut(200);
It should be
var itemImage = $(this).parent().prev().find(".images img");
$(itemImage).eq(0).fadeOut(200);
Let's asume that's due to posting it there and concentrate on the main problem.
$(this).parent().prev().find(".images img");
This returns a set of four images, always, not some 2x2 matrix, so
$(itemImage).eq(0).fadeOut(200);
$(itemImage).eq(1).fadeIn(200);
This part always targets the first set of images, as they have indexes 0 and 1, the other two images have indexes 2 and 3. So yes, eq does something else than you expect because your selection is different than what you might think.
Simple solution would be to filter then like this
$(itemImage).filter(':first-child').fadeOut(200);
$(itemImage).filter(':last-child').fadeIn(200);
This again takes a set of 4 images but doesn't limit the query to index 0 or 1 but rather to first-child, so it gets first image of both subset.
... maybe I'm not understanding how .eq() works in some way that limits the change to the first ".images" div?
You are correct. Please refer to the documentation for .eq():
Reduce the set of matched elements to the one at the specified index.
This means you are only selecting the first image element in the jQuery collection, not the first element in each div.
To resolve this you should use the :nth-child() pseudo-selector as follows:
$(itemImage).filter(':nth-child(1)').fadeOut(200);
$(itemImage).filter(':nth-child(2)').fadeIn(200);
According to the jQuery documentation for :first-child, it can also be used in place of :nth-child(1).
itemImage will be an array of count 4
by eq(0) and eq(1) you are targeting only img tag in your first div
For the second div it should be eq(2) and eq(3)
Also there is a scope issue for var itemImage This variable is not accessible in the event handler $(document).on("click" , ".js-angle" , function(){...}
The below code should work for you.
$(document).on("click" , ".js-profile" , function(){
var itemImage = $(this).parent().prev().find(".images:first img"); // this line is updated
$(itemImage).eq(1).fadeOut(200);
$(itemImage).eq(0).fadeIn(200);
$(this).addClass("current");
$(this).next().removeClass("current");
return false;
})
$(document).on("click" , ".js-angle" , function(){
var bikeImage = $(this).parent().prev().find("images:nth-child(2) img"); // this line is updated
$(bikeImage).eq(0).fadeOut(200); // itemImage changed to bikeImage
$(bikeImage).eq(1).fadeIn(200); // itemImage changed to bikeImage
$(this).addClass("current");
$(this).prev().removeClass("current");
return false;
})
Try this
$(document).on("click" , ".js-profile" , function(){
var itemImage = $(this).parent().prev().find(".images");
itemImage.each(function(){
$(this).find('img').eq(1).fadeOut(200);
});
itemImage.each(function(){
$(this).find('img').eq(0).fadeIn(200);
});
$(this).addClass("current");
$(this).next().removeClass("current");
return false;
})
$(document).on("click" , ".js-angle" , function(){
var itemImage = $(this).parent().prev().find(".images");
itemImage.each(function(){
$(this).find('img').eq(0).fadeOut(200);
});
itemImage.each(function(){
$(this).find('img').eq(1).fadeIn(200);
});
$(this).addClass("current");
$(this).prev().removeClass("current");
return false;
})
.images img:first-child{
width:100px;
height:100px;
background:#ccc;
}
.images img{
width:100px;
height:100px;
background:#f00;
}
.image-swap{
padding:5px;
}
.image-swap i{
padding:5px;
margin:5px;
border:1px solid #ccc;
cursor:pointer;
}
.image-swap i:hover{
background:#000;
color:#fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div class="image-group">
<h2> Title </h2>
<div class="color-selection">
<img alt="Black and Red" title="Black and Red">
<img alt="Black and Matte Black" title="Black and Matte Black">
</div>
<div class="images">
<img style="display: inline;">
<img style="display: none;">
</div>
<div class="images">
<img style="display: inline;">
<img style="display: none;">
</div>
</div><!--end image group -->
<div class="image-swap">
<i class="js-profile current">View 1</i>
<i class="js-angle">View 2</i>
</div>
</div>
Hope this Helps..
Basically I am trying to make a minimize/maximize div with jquery animation. I have a wrapper div named leftFilterBox. In leftFilterBox, there is another div to wrap all the contents named filterContent. So when I minimized the window, the filterContent should be collapse and the leftFilterBox will be shifted down at the same time when filterContent is collapse with jquery animation. Same goes to maximize. Here is my html code:
<div id='leftFilterBox'>
<div style='background: linear-gradient(#848484, #2E2E2E);color: white;line-height:2.2em;padding-left:5%;width:auto;font-weight:bold;'>Traffic Conditions
<div id='filterWindowNav'><img class='minMaxFilterBox' src='img/minimizeFilterWindow.png' onClick='minimizeFilterWindow();' />
<img class='minMaxFilterBox' src='img/maximizeFilterWindow.png' onClick='maximizeFilterWindow();' />
<img class='closeFilterBox' onclick='closeLeftFilterBox();' alt='close' src='img/closeFilterWindow.png' /></div></div><br/>
<div id='filterContent'><span class='getLiveTrafficTitle'><center>Select date</center></span><hr width='85%'></div>
</div>
And my CSS:
#filterWindowNav {
float:right;
}
.minMaxFilterBox, .closeFilterBox {
width: 28px;
height: 28px;
cursor: pointer;
}
And my JavaScript:
function minimizeFilterWindow() {
$('#leftFilterBox').css('height', '25px');
$('#leftFilterBox').css('top', '90%');
}
function maximizeFilterWindow() {
$('#leftFilterBox').css('height', '65%');
$('#leftFilterBox').css('top', '30%');
}
Here is my jsFiddle link: Fiddle
Currently, my code is just collapsing the filterWindow by setting specific some css such as height and top. I wonder is it possible to use some jquery animation like slideUp() or slideDown() for enhcnacement because I tried it, but it does not work.
Thanks in advance.
Hmm, I couldn't get your code to work, but I organized it and added some click events to call your functions. I also added a background color to show the maximize effect is happening as it wasn't as obvious.
Updated fiddle demo
$('#minimize').click(function(){
minimizeFilterWindow();
});
$('#maximize').click(function(){
maximizeFilterWindow();
});
function minimizeFilterWindow() {
$('#leftFilterBox').css('height', '25px');
$('#leftFilterBox').css('top', '90%');
}
function maximizeFilterWindow() {
$('#leftFilterBox').css('height', '65%');
$('#leftFilterBox').css('top', '30%');
$('#leftFilterBox').css('background-color', '#000');
}
And, the updated HTML
<div id='leftFilterBox'>
<div style='background: linear-gradient(#848484, #2E2E2E);color: white;line-height:2.2em;padding-left:5%;width:auto;font-weight:bold;'>Traffic Conditions
<div id='filterWindowNav'>
<img id='minimize' src='img/minimizeFilterWindow.png' />
<img id='maximize' src='img/maximizeFilterWindow.png' />
<img id='close' alt='close' src='img/closeFilterWindow.png' />
</div>
</div>
<br/>
<div id='filterContent'><span class='getLiveTrafficTitle'><center>Select date</center></span>
<hr width='85%' />
</div>
</div>