I created a circular linked list to transverse through an ul of images (i made an image gallery and am using the linked list to go through the images with the left and right arrow keys). Everything works fine until I get to the end of the list and try to go back to the first picture (or pressing left, when i get to the beginning and try to get to the last). This is my first time using jQuery and I'm not very good with circular linked lists (i only had to use one once--for school) and it seems like the problem is the if/else statement in my getNextPic function.
BTW I know this is really sloppy. Like I said, first time, so I'm sorry if it's a little difficult to follow. I'm posting a lot of my code because I always see people on here not posting enough to find the problem. Most of this i know works fine. The problem lies in getNextPic function as I said, 3rd snippet down. Thank you to anyone who attempts to help :)
here is a fiddle
html
<div id="gallery">
<div id="main">
<img id="main_img" src="d:/allyphotos/amanda_1.jpg" alt=""/></div>
<div id="thumbnail">
<ul>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/olivia_2.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/autumn_1.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/olivia_2.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/autumn_1.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/olivia_2.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/autumn_1.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/olivia_2.jpg"/></li>
<li><img class="thumb" id="long" src="d:/allyphotos/thumb/autumn_1.jpg"/></li>
</ul>
</div>
</div>
jQuery
document ready function
$(document).ready(function(){
//these ($first and $last) dont change
var $first = $('li:first img', '#gallery ul');
var $last = $('li:last img', '#gallery ul');
//set to current selected image to be displayed
var current = $first;
var previousImage = current;
runGallery(current, $first, $last, previousImage);
});
my runGallery function
function runGallery($current, $first, $last, previousImage){
//first and last thumbnails, selected and current
$("body").keydown(function(e){
// left arrow pressed
if ((e.keyCode || e.which) == 37)
{ $current = getNextPic($current, $first, $last, false);//false gets previous img, true gets following img
fade($current, previousImage);//fade selected, unfade previously selected
previousImage=$current;
var newlink = $($current).attr('src').replace('thumb/', '');
$('#main_img').attr('src', newlink);//set $current to main_img
}
// right arrow pressed
if ((e.keyCode || e.which) == 39)
{
$current = getNextPic($current, $first, $last, true);
fade($current, previousImage);
previousImage=$current;
var newlink = $($current).attr('src').replace('thumb/', '');
$('#main_img').attr('src', newlink);
}
});
$("#gallery li img").click(function()
{
//fade selected and unfade previous selected
fade(this, previousImage);
$current = this;
previousImage = this;
//get src for clicked thumb and change to full version
var newlink = $(this).attr('src').replace('thumb/', '');
$('#main_img').attr('src', newlink);
});
var imgSwap =[];
$("gallery li img").each(function()
{
imgUrl = this.src.replace('thumb/','');
imgSwap.push(imgUrl);
});
$(imgSwap).preload();
}
my getNextPic function -- this is where I believe the problem lies. I have commented the lines that aren't working properly
function getNextPic(current, first, last, boolval)
{
var next = $(current).closest('li');
if(boolval===true)
{
if(current === last)
{
next = first;//this seems to never happen???
}
else
{
next = $(next).next('li');
next = $(next).find('img');
}
}
else
{
if(current === first)
{
next = last;//this also never happens
}
else
{
next = $(next).prev();
next = $(next).find('img');
}
}
return next;
}
my fade function, 99.999% sure this has absolutely nothing to do with the problem but posting it anyway
function fade(current, previous)
{
$(previous).fadeTo('fast',1);
$(current).fadeTo('fast', 0.5);
}
The preload function, which i did not write (i got it from a tutorial) but i know isnt contributing to the problem. Posting so anyone who looks can rule it out too.
$.fn.preload = function(){
this.each(function(){
$('<img/>')[0].src=this;
});
}
Comparison of jquery objects cannot be done directly.
Your code contains, for example
current === last
Instead, as suggested in this answer, use the inner object:
You need to compare the raw DOM elements, e.g.:
if ($(this).parent().get(0) === $('body').get(0))
or
if ($(this).parent()[0] === $('body')[0])
Check out this fixed fiddle for your expected results.
Related
I've been building an image gallery with pictures in the hundreds and I don't want them all to load on page load for obvious bandwidth issues. For starters, I put;
<body onload="removeAttr("src")">
to prevent the pictures from loading which works... too well I'm afraid as it doesn't load my website header banner pic. Anyhow, my gallery is set up with a menu with each button representing a different image. The menu is displayed in this format;
<ul id="menu">
<li>Title</li>
</ul>
with many buttons. When that button is clicked it loads the graphic linked with it into a div called "gallery" All the images are loaded into the "gallery" with overflow: hidden which is why they want to load initially, that code appears as;
<div id="gallery">
<div>
<a name="pic1"></a><img alt="" src="../images/characters/character1.jpg" />
</div>
</div>
Again with many images in it. My script listens for a mouse click and immediately grabs the
a href value associated with it, so "pic1", then it uses that to find the image name linked with it so "character1.jpg" and stores it in a variable. (Which I firmly believe is where my problem lies). It then, targeting the "gallery" div deletes any picture previously in there then inserts the new image (the one stored in a variable). All this is in an attempt to load only the graphic the user wants to see not all of them. That alert displays the button number so that part works, and I know it deletes the image loaded in the div as it seems to be loading the first image in the list which then vanishes upon testing, but then it never replaces it with a new one.
<script type="text/javascript">
window.onclick = function(e) {
var node = e.target;
while (node != undefined && node.localName != 'a') {
node = node.parentNode;
}
if (node != undefined) {
if (this.id == 'alternate-image') {
var Imgsrc = $(this).find('img').attr('src');
alert(src);
}
var dv = document.getElementById('gallery');
// remove all child nodes
while (dv.hasChildNodes()) {
dv.removeChild(dv.lastChild);
}
alert("The button value is: " + node);
var img = document.createElement("IMG");
img.src = Imgsrc;
dv.appendChild(img);
return false; // stop handling the click
} else {
alert('This is not a link: ' + e.target.innerHTML)
return true; // handle other clicks
}
}
</script>
Not sure if I fully understand your issue, but I do see an issue with your code.
You are defining var Imgsrc within an if block. If the expression is not true, then Imgsrc will not be defined. Yet later in your code you use it, regardless of conditions, without checking if it's defined in the first place.
See my code comments below.
<script type="text/javascript">
window.onclick = function(e) {
var node = e.target;
while (node != undefined && node.localName != 'a') {
node = node.parentNode;
}
if (node != undefined) {
if (this.id == 'alternate-image') {
var Imgsrc = $(this).find('img').attr('src'); //<!---- here you define the Imgsrc var
//but what if the this.id != 'alternate-image'??
alert(src);
}
var dv = document.getElementById('gallery');
// remove all child nodes
while (dv.hasChildNodes()) {
dv.removeChild(dv.lastChild);
}
alert("The button value is: " + node);
var img = document.createElement("IMG");
img.src = Imgsrc; //<!---- need to check if this is defined.
dv.appendChild(img);
return false; // stop handling the click
} else {
alert('This is not a link: ' + e.target.innerHTML)
return true; // handle other clicks
}
}
</script>
Any chance you can post your html or more detail so we can resolve this?
Can you post the full source on a GitHub gist or a pastebin?
Here's a simpler way to do it. You don't need to add and remove new image elements, just change the src attribute on an existing one.
<ul class='imageMenu'>
<li data-image="dog.jpg">dog</li>
<li data-image="cat.jpg">cat</li>
<li data-image="donkey.jpg">donkey</li>
</ul>
<img src="" id='selectedImage' />
<script>
const img = document.querySelector('#selectedImage');
document.querySelectorAll('.imageMenu li').forEach(item => {
item.addEventListener('click', evt => {
img.setAttribute('src', evt.target.getAttribute('data-image'));
});
});
</script>
I would propose a revised set of markup and code. Since you appear to have jQuery in your code, I will use that.
Menu of images:
<ul id="menu">
<li class="image-link" data-image="../images/characters/character1.jpg">Title 1</li>
<li class="image-link" data-image="../images/characters/character2.jpg">Title 2</li>
<li class="image-link" data-image="../images/characters/character3.jpg">Title 3</li>
</ul>
One place to show them:
<div id="gallery">
<img alt="" src="" />
</div>
Code to show them:
$('#menu').on('click','.image-link',function(){
$('#gallery').find('img').attr('src', $(this).data('image'));
});
I'm working on a website, and I wanted to do a little extra in the context of the subject (a shooting range) in the menubar. When a user hovers onto the element, a little crosshair would appear next to the cursor and the image would follow the cursor while in the li element.
However it seems a little off sometimes, as in if you keep moving a mouse on the list elements, sometimes the shadow-y hover effect (which is a css :hover thing) gets stuck on the last element. You can see it here. (Just move the mouse on the menu elements.)
At first I thought it's a css problem, but after fiddling with both css and js, it seems to be a javascript problem. If I comment out the "offset" lines, it's working fine. Later I have tried switching out the jquery function to native javascript, but the bug(?) still happens when the offset lines are commented out.
I've found that setting the offset can be slow. Would that cause my problem?
How could I solve this?
Thank you for your help/advice!
This is my jQuery code:
$("nav li").mousemove(function(e) {
var $img = $(this).find("img.crosshair");
$img.css("display", "inline-block");
$img.offset({left:e.pageX-10,top:e.pageY-10});
});
And this is the native javascript:
var menu = document.querySelectorAll("nav li");
for (var i = 0; i < menu.length; i++) {
var elem = menu[i];
elem.addEventListener("mousemove", function(e) {
var img = this.querySelector("img.crosshair");
img.style.display = "inline-block";
img.style.left = (parseInt(e.pageX, 10) - 10) + "px";
img.style.top = (parseInt(e.pageY, 10) - 10) + "px";
});
}
I'd suggest to use only one img.crosshair in your code.. first try to reconstuct your html something like this: (remove redundant img's from each li)
<section class="header">
<img class="crosshair" src="images/xhair.png">
<nav>
<ul>
<li><img class="bullet_hole" src="images/bullet_hole.png">A lőtér</li>
<li><img class="bullet_hole" src="images/bullet_hole.png">Fegyverek</li>
<li><img class="bullet_hole" src="images/bullet_hole.png">Szolgáltatásaink</li>
</ul>
</nav>
<div class="logo">
<img src="images/logo.png"></div>
<nav>
<ul>
<li><img class="bullet_hole" src="images/bullet_hole.png">Egyesület</li>
<li><img class="bullet_hole" src="images/bullet_hole.png">Galéria</li>
<li><img class="bullet_hole" src="images/bullet_hole.png">Információk</li>
</ul>
</nav>
</section>
then try to use jquery like this one below ,, fix the position of image on hover to your needs and that should cover it..
$(document).ready(function() {
$("nav li").click(function(e) {
var $img = $(this).find("img.bullet_hole");
$img.css("display", "inline-block");
$img.offset({left:e.pageX-20,top:e.pageY-10});
setTimeout( function(){
$img.css("display", "none");
},4000);
});
$("nav li").mousemove(function(e) {
var $img = $(this).closest('.header').find("img.crosshair");
$img.css("display", "inline-block");
$img.offset({left:e.pageX-10,top:e.pageY-10});
});
$("nav li").mouseout(function(e) {
var $img = $(this).closest('.header').find("img.crosshair");
$img.css("display", "none");
});
});
the thing that was happening is that hover over each li moved sometimes TWO images when you hovered over one li and one before when mouseover event propagated in browser,, that's where glitch happend
hth, cheers and good luck
An interesting thing has happened as I build an light box using Jquery. I've set up left and right arrow buttons to move through the list so that at the last child the right arrow button begins again from the first child or at the first child, the left arrow button moves to the last child.
What's happening is that my left arrow button is supposed to move from the first child to the last child but instead is skipping over the last child and displaying the photo of the second to last child. I'm not having the same problem with the right arrow button moving from the last child to the first.
Also, when I click the left arrow and console.log the last child, I get the very image that I want to display logged correctly, but the image in the overlay is the second to last image.
<body>
<h1>Image Gallery</h1>
<ul id="imageGallery">
<li>
<a href="images/refferal_machine.png">
<img src="images/refferal_machine.png" width="100" alt="Refferal Machine By Matthew Spiel">
</a>
</li>
<li><img src="images/space-juice.png" width="100" alt="Space Juice by Mat Helme"></li>
<li><img src="images/education.png" width="100" alt="Education by Chris Michel"></li>
<li><img src="images/copy_mcrepeatsalot.png" width="100" alt="Wanted: Copy McRepeatsalot by Chris Michel"></li>
<li><img src="images/sebastian.png" width="100" alt="Sebastian by Mat Helme"></li>
<li><img src="images/skill-polish.png" width="100" alt="Skill Polish by Chris Michel"></li>
<li><img src="images/chuck.png" width="100" alt="Chuck by Mat Helme"></li>
<li><img src="images/library.png" width="100" alt="Library by Tyson Rosage"></li>
<li><img src="images/boat.png" width="100" alt="Boat by Griffin Moore"></li>
<li><img src="images/illustrator_foundations.png" width="100" alt="Illustrator Foundations by Matthew Spiel"></li>
<li><img src="images/treehouse_shop.jpg" width="100" alt="Treehouse Shop by Eric Smith"></li>
</ul>
<script src="http://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript" charset="utf-8"></script>
<script src="js/app.js" type="text/javascript" charset="utf-8"></script>
</body>
The JavaScript:
var $overlay = $('<div id="overlay"></div>');
var $image = $('<img>');
var $caption = $('<p></p>');
var $arrowLeft = $('<button id="left" class="arrow">‹</button>');
var $arrowRight = $('<button id="right" class="arrow">›</button>');
var $exit = $('<button id="exit">X</button>');
//Add image to overlay
$overlay.append($image);
//Add buttons to overlay
$overlay.append($arrowRight);
$overlay.append($arrowLeft);
$overlay.append($exit);
//Add caption to overlay
$overlay.append($caption);
//Add overlay
$('body').append($overlay);
//Capture the click event on a link to an image
$('#imageGallery a').click(function(event) {
event.preventDefault();
var imageLocation = $(this).attr("href");
//Update overlay with the image linked in the link
$image.attr('src', imageLocation);
//Show the overlay
$overlay.show();
//Get child's alt atribute and set caption
var captionText = $(this).children('img').attr('alt');
$caption.text(captionText);
});
//When left arrow is clicked
$arrowLeft.click(function() {
$('#imageGallery li a img').each(function() {
var galleryImage = $(this);
if (galleryImage.attr('src') === $image.attr('src')) {
var li = galleryImage.parent().parent();
if (li.is(':first-child')) {
var gallery = li.parent();
var lastLi = gallery.children(':last-child');
var anchor = lastLi.children('a');
var image = anchor.children('img');
$image.attr('src', image.attr('src'));
console.log(lastLi);
} else {
var prevLi = li.prev();
var anchor = prevLi.children('a');
var image = anchor.children('img');
$image.attr('src', image.attr('src'));
return false;
}
}
});
});
//When right arrow is clicked
$arrowRight.click(function() {
$('#imageGallery li a img').each(function() {
var galleryImage = $(this);
if (galleryImage.attr('src') === $image.attr('src')) {
var li = galleryImage.parent().parent();
if (li.is(':last-child')) {
var gallery = li.parent();
var firstLi = gallery.children(':first-child');
var anchor = firstLi.children('a');
var image = anchor.children('img');
$image.attr('src', image.attr('src'));
} else {
var nextLi = li.next();
var anchor = nextLi.children('a');
var image = anchor.children('img');
$image.attr('src', image.attr('src'));
return false;
}
}
});
});
//When x button is clicked
$exit.click(function() {
//Hide the overlay
$overlay.hide();
});
Update 1:
In the handler, you are running an each loop to test each image element, so make sure return false; is used when you find the matching image, otherwise your loop runs one more time after a match:
//When left arrow is clicked
$arrowLeft.click(function() {
$('#imageGallery li a img').each(function() {
var galleryImage = $(this);
if (galleryImage.attr('src') === $image.attr('src')) {
var li = galleryImage.parent().parent();
if (li.is(':first-child')) {
// if code block
...
} else {
// else code block
...
}
// move this to here
return false;
}
});
});
Make sure to update the arrow right handler as well.
You have an incorrect variable in your click handler:
//When left arrow is clicked
$arrowLeft.click(function() {
if (li.is(':first-child')) {
var gallery = li.parent();
var lastLi = gallery.children(':last-child');
var anchor = lastLi.children('a');
var image = anchor.children('img');
$image.attr('src', image.attr('href'));
console.log(lastLi);
} else {
...
});
Should be:
$image.attr('src', image.attr('src'));
You should look into joining that logic into one handler function to reduce the amount of code.
Also you can simplify this:
var li = galleryImage.parent().parent();
to this:
var li = galleryImage.closest('li');
I'm trying to make a sort of a minimal clickable "slideshow". So far I have only managed to make the image change into another. but I want to add other images to it. I tried to add other ifs and elses on the javascript but it doesn't work. (I'm a noob...) How can I do it? I juts want to click and the images change. This is my code so far:
<div> <img alt="" src="1.jpg" id="imgClickAndChange" onclick="changeImage()"/> </div>
<script language="javascript">
function changeImage() {
if (document.getElementById("imgClickAndChange").src = "1.jpg")
{
document.getElementById("imgClickAndChange").src = "2.jpg";
document.getElementById("imgClickAndChange").src = "3.jpg";
}
}
</script>
thank you!
In your condition you need a double equals == - you can also pass this in to avoid getElementById multiple times. If you want to make a cycler - you can put your sources into an array and cycle thru that:
<img alt="" src="1.jpg" id="imgClickAndChange" onclick="changeImage(this)"/>
var images = ["1.jpg", "2.jpg", "3.jpg"];
function changeImage(img) {
var currentIndex = images.indexOf(img.src);
var zeroBasedLength = images.length - 1;
if (currentIndex == zeroBasedLength)
img.src = images[0];
else
img.src = images[++currentIndex];
}
If you want to cycle through those images, I'd make an array and swap the position of the elements in it like:
var imgs = ["2.jpg", "3.jpg", "1.jpg"];
function changeImage() {
document.getElementById("imgClickAndChange").src = imgs[0];
imgs.push(imgs.shift())
}
jsFiddle example
Is there any way to switch images using next/prev buttons with jQuery? Here's the code:
<div class="prevDiv">
<img src="images/prev.png" alt="previous" />
</div>
<div class="pic" id="picwebd">
<img src="images/portfolio/webdesign/webd1.jpg" class="portPic" />
</div>
<div class="nextDiv">
<img src="images/next.png" alt="previous" />
</div>
I tried modifying this code to my needs: http://jsfiddle.net/x5mCR/16/ but I haven't succeed. I think that incrementing and decrementing number in the image src would be enough, but I can't come up with decent code do this. Google doesn't help neither.
In case anyone reading this post want a different approach still using JQuery fadeIn, Im posting below the code for that.
Here you can find the fiddle for it.
Here's the Javascript Part
//At the start will show the first image
$('#fullimage img.fullimage:first-child').fadeIn();
//Keep track of the image currently being visualized
var curr = $('#fullimage img.fullimage:first-child');
$('#next').on('click', function() {
//Hide Current Image
curr.hide();
//Find Next Image
var next = curr.next();
//If theres no next image (is the last img), go back to first
if (next.length == 0) next = $('#fullimage img:first');
//Fade In
next.fadeIn();
//Save in curr the current Image
curr = next;
return false;
});
$('#prev').on('click', function() {
curr.hide();
var prev = curr.prev();
if (prev.length == 0) prev = $('#fullimage img:last');
prev.fadeIn();
curr = prev;
return false;
});
Here's the HTML part
<div id="fullimage">
<img class="fullimage" src="http://i.imgur.com/RHhXG.jpg" />
<img class="fullimage" src="http://i.imgur.com/p1L2e.jpg" />
<img class="fullimage" src="http://i.imgur.com/NsrI0.jpg" />
<img class="fullimage" src="http://i.imgur.com/Ww6EU.jpg" />
</div>
<label id="prev">previous</label>
<label id="next">next</label>
Here is dynamic and simple script reducing your html code
http://jsfiddle.net/x5mCR/32/
$("#thumbnail a").on('click', function (eve) {
eve.preventDefault();
var link = ($(this).attr("href"));
var content = '<img src="' + link + '"/>';
$("#fullimage").hide().html(content).fadeIn('slow');
});
Remove the anchors with class thumbnail and give the corresponding <img> tags the thumbnail class, then use jQuery click methods for the thumbnail class:
$(".thumbnail").click(function() {
$(".fullimage").src = $(this).attr("src");
});
Make sure you have a single .fullimage in the #fullimage div.
This isn't the same as a next / previous button - but it would fix the JSFiddle that you made.
http://jsfiddle.net/x5mCR/34/
var picNumber = 1;
$(".nextDiv").click(function() {
picNumber++;
if (picNumber > 3) picNumber = 1; // Change 3 to how many pictures there are.
$(".pic img").attr("src", "images/portfolio/webdesign/webd" + picNumber + ".jpg");
});
$(".prevDiv").click(function() {
picNumber--;
if (picNumber < 1) picNumber = 3; // Change 3 to how many pictures there are.
$(".pic img").attr("src", "images/portfolio/webdesign/webd" + picNumber + ".jpg");
});
If I understand correctly, you're trying to use the arrow keys to move back and forth between pictures...so if this is the case, I would recommend taking a look at this post: Binding arrow keys in JS/jQuery
Also, for your convenience, I just took the code from that post and combined it with the function in your fiddle to get this:
$(document).keydown(function (e) {
if (e.keyCode == 39) {
$(".fullimage").hide();
var next = $(this).next();
if (next.length > 0) {
next.fadeIn();
} else {
$('#fullimage img:first').fadeIn();
}
return false;
}
});
In testing it looks like it might need some modification, and also, you would obviously need to create a similar function for when the back button is pressed, but I think if I'm understanding your issue correctly this is a good starting place.