JQuery click() strange behavior - javascript

I want to make a simple photo gallery function. However, there are some strange behavior of JQuery's click().
After the user clicks the forward button, 10 next images should be shown. After the user clicks the backward button, 10 previous images should be shown.
In the following code, 4 lines which works fine in my code are commented. I expect the JQuery click() should do the same thing as the commented lines, but it doesn't. Code using JQuery click() doesn't work after I click backward and forward several times. I want to ask where's the problem of the code. Thank you.
<script type="text/javascript">
$(document).ready(function() {
var numImages = imagesObj.images.image.length;
var imagePath = "images/";
var currentIndex = 0;
function changeImageList(startIndex){
var imageIndex = 0;
$("#imagesList img").css("display","none");
for (var i=startIndex; i<numImages && i<startIndex + 10; i++)
{
var imageId = "image" + imageIndex;
var image = imagesObj.images.image[i];
$("#" + imageId).attr("src",imagePath + image.imageurl).css("display","");
imageIndex++;
}
currentIndex = startIndex;
if (numImages > currentIndex+10){
$('#forward').css("cursor","pointer");
//document.getElementById("forward").onclick = function(){changeImageList(currentIndex+10);};
$('#forward').click(function(){ changeImageList(currentIndex+10);});
}else{
$('#forward').css("cursor","default");
//document.getElementById("forward").onclick = function(){};
$('#forward').click(function(){});
}
if (currentIndex < 10){
$('#backward').css("cursor","default");
//document.getElementById("backward").onclick = function(){};
$('#backward').click(function(){});
}else{
$('#backward').css("cursor","pointer");
//document.getElementById("backward").onclick = function(){changeImageList(currentIndex-10);};
$('#backward').click(function(){changeImageList(currentIndex-10);});
}
}
changeImageList(0);
});
</script>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center"><img id="backward" src="images/lft_arrow.gif" alt="" width="39" height="44" /></td>
<td id="imagesList" align="center">
<img id="image0" width="77" style="display:none; cursor:pointer" />
<img id="image1" width="77" style="display:none; cursor:pointer" />
<img id="image2" width="77" style="display:none; cursor:pointer" />
<img id="image3" width="77" style="display:none; cursor:pointer" />
<img id="image4" width="77" style="display:none; cursor:pointer" />
<img id="image5" width="77" style="display:none; cursor:pointer" />
<img id="image6" width="77" style="display:none; cursor:pointer" />
<img id="image7" width="77" style="display:none; cursor:pointer" />
<img id="image8" width="77" style="display:none; cursor:pointer" />
<img id="image9" width="77" style="display:none; cursor:pointer" />
</td>
<td align="center"><img id="forward" src="images/rgt_arrow.gif" alt="" width="39" height="44" /></td>
</tr>
</table>
</body>

This is the normal behaviour of event binding : when you call click, the event callback is added to the element and does not replace existing callbacks. When you click backward and forward buttons multiple times, you assign multiple handlers for the click event and now you know that this is bad :)
There are two solutions to you problem :
use eg $('#backward').unbind('click') before you assign a new event, this is the easy fix for your code.
assign only one event to the buttons with a relative index, eg $('#backward').click(function(){ changeImageList(-10);});. I find it cleaner will a simple check at the beginning of changeImageList to calculate startIndex, but you'll still have to set the cursor to default/pointer.

Related

How to determine how many visible images within spans with the same "data-id" attribute have the same 'longdesc' attribute

I am trying to make it so that when someone enables more than one secondary phone, they are alerted that there may be charges. They are allowed to have one primary, and one secondary.
They are able to set the phones active themselves, and they should be alerted when they try to activate more than one secondary phone. They should also be told to call customer service if they try to disable their primary phone. (That part is working.)
From the code provided, you can see what parts are working. I am hard-coding some of the values here for an example. In the sample code, I am searching for how many times the 'longdesc' of 1234 appears in visible images.
Can anyone tell what I am doing wrong? Or, if there is a better way to search for how many times the value 1234 appears in visible images in 'secondary' spans?
$(".tog").click(function(){
var id = $(this).attr('id');
var option = $(this).attr('name');
if (option == "primary") {
alert("Please call customer service to set the Primary phone on the account.");
}
else {
$('img',this).toggle();
if (search($(this).find('img').attr('longdesc')) > 1)
document.getElementById('alert').value = "More than 1 selected.";
else
document.getElementById('alert').value = "1 or less selected.";
}
});
function search(v) {
var numfound = 0;
var out = document.querySelectorAll('img[longdesc]' == v);
[].forEach.call(out, function(x) {
numfound++;
});
return numfound;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Primary Phone
<span name="primary" data-id="784" class="tog">
<img longdesc="1234" alt="on" align="top" style="width:22px" src="http://findicons.com/files/icons/1964/colorcons_green/128/checkmark.png" />
<img alt="off" align="top" style="display:none;width:22px" src="https://www.sfpcu.org/UserControls/BrowserDetection/images/red-x-mark.png" /></span>
Second Phone
<span name="secondary" data-id="784" class="tog">
<img longdesc="1234" alt="on" align="top" style="display:none;width:22px" src="http://findicons.com/files/icons/1964/colorcons_green/128/checkmark.png" />
<img alt="off" align="top" style="width:22px" src="https://www.sfpcu.org/UserControls/BrowserDetection/images/red-x-mark.png" /></span>
Third Phone
<span name="secondary" data-id="784" class="tog">
<img longdesc="1234" alt="on" align="top" style="width:22px" src="http://findicons.com/files/icons/1964/colorcons_green/128/checkmark.png" />
<img alt="off" align="top" style="display:none;width:22px" src="https://www.sfpcu.org/UserControls/BrowserDetection/images/red-x-mark.png" /></span>
<span id='alert'></span>
ID cannot be repeated. If at you apply any logic on that, only first occurrence of the ID is considered. Try using class instead.
HTML:
<span>
<img src="" class="class1" longdesc="123" />
<img src="" class="class2" longdesc="123" />
<img src="" class="class1" />
<img src="" class="class1" />
<img src="" class="class1" longdesc="123" />
</span>
jQuery:
var count = 0;
$(".class1").each(function( el) {
if($(this).attr('longdesc'))
count++;
});
I hope this helps! :)
In case anyone is searching for this, I discovered jquery's multiple selectors and other things that helped. First, thank you to Edison and Scott for their help.
What I ended up using that worked best was several "data-" elements and a complex selector statement in jquery. We also decided not to allow multiple secondary phones altogether, which made the answer a bit different, but this all works perfectly now.
Here is the new snippet:
$(".tog").click(function(){
var id = $(this).attr('data-phone-id');
var option = $(this).attr('data-name');
var contactId = $(this).attr('data-contactId');
var el = this;
var found = $("span[data-name='"+option+"'][data-contactId='"+contactId+"'][data-phone-id!="+id+"]");
found.each(function(){
var thisspan = this;
var image = $("img[alt='on']:visible",this);
image.each(function() {
$('img',thisspan).toggle();
});
});
if (option == "primary") {
alert("Please call customer service to set the Primary phone on the account.");
}
else {
$('img',el).toggle();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Primary Phone
<span data-phone-id="121" data-name="primary" data-contactId="784" class="tog">
<img longdesc="1234" alt="on" align="top" style="width:22px" src="http://findicons.com/files/icons/1964/colorcons_green/128/checkmark.png" />
<img alt="off" align="top" style="display:none;width:22px" src="https://www.sfpcu.org/UserControls/BrowserDetection/images/red-x-mark.png" /></span>
Second Phone
<span data-phone-id="122" data-name="secondary" data-contactId="784" class="tog">
<img longdesc="1234" alt="on" align="top" style="display:none;width:22px" src="http://findicons.com/files/icons/1964/colorcons_green/128/checkmark.png" />
<img alt="off" align="top" style="width:22px" src="https://www.sfpcu.org/UserControls/BrowserDetection/images/red-x-mark.png" /></span>
Third Phone
<span data-phone-id="123" data-name="secondary" data-contactId="784" class="tog">
<img alt="on" align="top" style="width:22px" src="http://findicons.com/files/icons/1964/colorcons_green/128/checkmark.png" />
<img alt="off" align="top" style="display:none;width:22px" src="https://www.sfpcu.org/UserControls/BrowserDetection/images/red-x-mark.png" /></span>
<span id='alert'></span>

Changing the picture description in the preview

Im curently creating a picture gallery for my project in school. I came across the problem that i don't know how to add a picture description that will only show under the big preview picture and not next to the small pictures at the top. Every small picture will have a different description. I tried some stuff myself but i failed miserably, Im still new to all of this :)
Any solutions to that problem?
<head>
<title>Gallery</title>
<link href="galery.css" rel="stylesheet" type="text/css">
</head>
<body background="cosmic.jpg">
<div class="gallery" align="center">
<div class="smallpics">
<img onclick="getElementById('bigpic').src=this.src" id="picture1" src="images/picture1.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture2" src="images/picture2.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture3" src="images/picture3.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture4" src="images/picture4.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture5" src="images/picture5.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture6" src="images/picture6.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture7" src="images/picture7.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture8" src="images/picture8.png" />
<img onclick="getElementById('bigpic').src=this.src" id="picture9" src="images/picture9.png" />
</div>
<div class="bigpic" align="center">
<img id="bigpic" src="images/picture1.png" alt="" />
</div>
<div class="smallpics">
<img onclick="getElementById('bigpic').src=this.src; getElementById('bigpicDesc').innerHTML(this.alt) " id="picture1" src="images/picture1.png" alt="The Description" />
....
</div>
<div class="bigpic" align="center">
<img id="bigpic" src="images/picture1.png" alt="" />
<div id="bigpicDesc"> </div>
</div>
or
<div class="smallpics">
<img onclick="showInBig(this)" id="picture1" src="images/picture1.png" alt="The Description" />
....
</div>
<div class="bigpic" align="center">
<img id="bigpic" src="images/picture1.png" alt="" />
<div id="bigpicDesc"> </div>
</div>
function showInBig(element){
document.getElementById('bigpic').setAttribute('src',element.getAttribute('src'));
document.getElementById('bigpicDesc').innerHTML(element.element.getAttribute('alt'));
}
Given that alt of the small images are the descriptions.
The first thing is to clean up your HTML and separate out the JavaScript. This has a number of benefits. It keeps your HTML and JS separate without muddying one with the other.
All of your onclick code can be handled thus:
var big_pic = document.querySelector('#bigpic');
document.querySelector('body').addEventListener('click', function(evt) {
if (!/^picture\d+$/.test(evt.target.id)) return;
big_pic.src = evt.target.src;
}, false);
Now, let's consider adding a description. The first question is, how are you going to store these, and in relation to the images?
An obvious solution is to store them in a data attribute on the pictures elements. So just as we read the src from the clicked pic's element, we'll read its description from the same source.
So our elements become:
<img id='picture1' src='some/src.jpg' data-descr='Picture description here' />
Then you're going to need a description placeholder in the big picture area, so add a paragraph.
Finally, change the above JS code to factor in the description also:
var
big_pic = document.querySelector('#bigpic'),
big_pic_descr = document.querySelector('.bigpic p');
document.querySelector('body').addEventListener('click', function(evt) {
if (!/^picture\d+$/.test(evt.target.id)) return;
big_pic.src = evt.target.src;
big_pic_descr.innerHTML = evt.target.getAttribute('data-descr');
}, false);
Could be done in 2 ways, first by making use of data- attribute (1)
jsFiddle 1
var pics = document.querySelectorAll('.smallpics img'),
bigPic = document.getElementById('bigpic'),
descP = document.getElementById('description');
for (var i = 0, ln = pics.length; i < ln; i++) {
// we pass each img with its src and data-desc attributes to the function.
var $this = pics[i];
theClickFunction($this, $this.getAttribute('src'), $this.getAttribute('data-desc'));
}
function theClickFunction($th, $src, $desc) {
$th.addEventListener('click', function() {
//on click we update the bigpic display and thedescription paragraph
bigPic.setAttribute('src', $src);
bigPic.style.display = 'block';
descP.innerHTML = $desc;
});
}
body { margin: 0; padding: 0; }
.smallpics img { width: 19%; cursor: pointer; }
#bigpic { display:none}
<div class="gallery" align="center">
<div class="smallpics">
<img id="pic1" src="//dummyimage.com/300x100?text=pic1" data-desc="description of picture 1" />
<img id="pic2" src="//dummyimage.com/300x100?text=pic2" data-desc="description of picture 2" />
<img id="pic3" src="//dummyimage.com/300x100?text=pic3" data-desc="description of picture 3" />
<img id="pic4" src="//dummyimage.com/300x100?text=pic4" data-desc="description of picture 4" />
<img id="pic5" src="//dummyimage.com/300x100?text=pic5" data-desc="description of picture 5" />
<img id="pic6" src="//dummyimage.com/300x100?text=pic6" data-desc="description of picture 6" />
<img id="pic7" src="//dummyimage.com/300x100?text=pic7" data-desc="description of picture 7" />
<img id="pic8" src="//dummyimage.com/300x100?text=pic8" data-desc="description of picture 8" />
<img id="pic9" src="//dummyimage.com/300x100?text=pic9" data-desc="description of picture 9" />
<img id="pic10" src="//dummyimage.com/300x100?text=pic10" data-desc="description of picture 10" />
</div>
<hr>
<div class="bigpic" align="center">
<img id="bigpic" src="images/picture1.png" alt="" />
<p id="description"></p>
</div>
The other way is by using some hidden element, I used <ul> with its lis here but it could be divs or p etc.., while this way adds extra markup to the page it suits better when you have HTML, styled and/or long descriptions rather than just normal text.
jsFiddle 2
var pics = document.querySelectorAll('.smallpics img'),
DescLis = document.querySelectorAll('#hiddenDescs li'),
bigPic = document.getElementById('bigpic'),
descP = document.getElementById('description');
for (var i = 0, ln = pics.length; i < ln; i++) {
// we pass each img with its src attribute.
var $this = pics[i];
theClickFunction($this, $this.getAttribute('src'), i);
}
function theClickFunction($th, $src, i) {
$th.addEventListener('click', function() {
//on click we update the bigpic display and thedescription paragraph
bigPic.setAttribute('src', $src);
bigPic.style.display = 'block';
// get the inner html of the corresponding li and inject it as innerHTML
// of the descreption p
descP.innerHTML = DescLis[i].innerHTML;
});
}
(1) Using alt attribute, as in #Thuin's answer, rather than data-* is better because: This attribute defines the alternative text describing the image. Users will see this text displayed if the image URL is wrong, the image is not in one of the supported formats, or if the image is not yet downloaded.

How to swap an image with another when hovering on the other image?

I have 5 small images and 1 image that is twice the size as the small ones. What I'm trying to do is whenever you hover on the small images the big image changes to the image you are hovering. I am having a hard time searching for methods and functions but luck as of yet. this is what I have
<div class="bigImg">
<img id="image0" src="images/image1.png">
</div>
<img id="image1" src="images/image1.png">
<img id="image2" src="images/image2.png">
<img id="image3" src="images/image3.png">
<img id="image4" src="images/image4.png">
<img id="image5" src="images/image5.png">
I was trying to add this function that I saw somewhere else here
function mouseOver() {
document.getElementById("image0").innerHTML = '<"image2.png"/>';
}
function mouseOut() {
document.getElementById("image0").innerHTML = '<img src="image1.png" />';
}
I wrote the img tag as
<img id="image1" onmouseover="mouseOver()" onmouseout="mouseOut()" src="images/image1.png">
for all of the images but wasn't working. Can someone steer me in the right direction, please?
This is how I did it:
function mouseOut() {
document.getElementById("image0").src = 'http://lorempixel.com/g/600/600/';
}
function changePic(elem) {
document.getElementById("image0").src = elem.src;
}
Here is the JSFiddle demo
If you want to do it using Jquery you can try this.
<div class="bigImg"></div>
<img class="imgLink" src="http://dummyimage.com/100x100/eb00eb/fff" target="http://dummyimage.com/100x100/eb00eb/fff">
<img class="imgLink" src="http://dummyimage.com/100x100/000/fff" target="http://dummyimage.com/100x100/000/fff">
<img class="imgLink" src="http://dummyimage.com/100x100/999/fff" target="http://dummyimage.com/100x100/999/fff">
JS
$('.imgLink').hover(function(){
$('.bigImg').css({'background':'url('+ $(this).attr('target') +')'});
},function(){
$('.bigImg').css({'background':''});
});
Demo here
Basic concept behind this is we have to catch mouseover and mouseout events. Now, on mouse over we have to change the src attribute of that particular Image and vice versa for getting back the original image.
Try this one :
function mouseOver(element) {
document.getElementById(element).src = 'https://www.google.co.in/images/google_favicon_128.png';
}
function mouseOut(element) {
document.getElementById(element).src = 'https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png';
}
<div class="bigImg"><img id="image0" src="https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png"></div>
<img id="image1" onmouseover="mouseOver('image1')" onmouseout="mouseOut('image1')" src="https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png">
<img id="image2" onmouseover="mouseOver('image2')" onmouseout="mouseOut('image2')" src="https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png">
<img id="image3" onmouseover="mouseOver('image3')" onmouseout="mouseOut('image3')" src="https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png">
<img id="image4" onmouseover="mouseOver('image4')" onmouseout="mouseOut('image4')" src="https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png">
<img id="image5" onmouseover="mouseOver('image5')" onmouseout="mouseOut('image5')" src="https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png">

Image onclick not working

I have an image which is set relative to a background image.
I want to call a function on the click but i seem to have been facing a problem.
The hyperlink seems to be working but the function is not being called.
This is how my code looks like
<img src=".." width="100%" height="80" id="ril_logo"/>
<div id="logo-wrapper1">
<img src="..." width="5%" height="45"/>
</div>
<div id="logo-wrapper2">
<a href="#">
<img id="charger" onclick="abc();" src=".." width="4%" height="50" />
</a>
</div>
function abc()
{
alert();
}
Are you 100% sure that the call to abc() is not working? Is there any errors in the console log.
Also you might consider event bubbling. You click on the image and it fires of it's event. This then bubbles to the a href element which then bubbles to the next available element and so forth etc.
Your code could be changed to:
<img id="charger" onclick="abc(); return false;" src=".." width="4%" height="50" />
or
<img id="charger" onclick="return abc();" src=".." width="4%" height="50" />
function abc() { ... return false; }
This will prevent the event bubbling any further than the img onclick function.
Since your img is inside an a tag, the click on the image would cause a click on the a and hence you see the hyperlink working.
If you instead put the onclick on a it would trigger the function call.
try this, and src="imagepath" add your image path
<img src=".." width="100%" height="80" id="ril_logo" />
<div id="logo-wrapper1">
<img src="..." width="5%" height="45" />
</div>
<div id="logo-wrapper2">
<a href="#">
<img id="charger" onclick="abc();" src=".." width="4%" height="50" />
</a>
</div>
<script type="text/javascript">
function abc() {
alert();
}
</script>
Just add your function abc() inside script tags
<script type="text/javascript">
function abc() {
alert("Success");
}
</script>

jquery issue: how to break and reset setinterval?

I created a image loop by using jquery and it works fine. Here is my code.
$(document).ready(function(){
$('.images').hide();
$('#image1').show('slide', {direction: 'right'}, 500);
$('#image1').delay(2000).hide('slide', {direction: 'left'}, 500);
var sc = $('#image img').size();
var count = 2;
setInterval(function(){
$('#image'+count).show('slide', {direction: 'right'}, 500);
$('#image'+count).delay(2000).hide('slide', {direction: 'left'}, 500);
if(count == sc){
count = 1;
}else{
count = count + 1;
}
}, 3000);
$('.name').click(function(){
var name = $(this).attr('id');
name = name.replace('name', '');
count = name;
});
});
Here is the html code.
<div id="image">
<img class="images" id="image1" alt="Image loop" src="image1.jpg" width="550px" height="400px"/>
<img class="images" id="image2" alt="Image loop" src="image2.jpg" width="550px" height="400px"/>
<img class="images" id="image3" alt="Image loop" src="image3.jpg" width="550px" height="400px"/>
<img class="images" id="image4" alt="Image loop" src="image4.jpg" width="550px" height="400px"/>
<img class="images" id="image5" alt="Image loop" src="image5.jpg" width="550px" height="400px"/>
</div>
<div id="name">
<div class="name" id="name1">
<img src="image1.jpg" width="80px" height="80px"/>
</div>
<div class="name" id="name2">
<img src="image2.jpg" width="80px" height="80px"/>
</div>
<div class="name" id="name3">
<img src="image3.jpg" width="80px" height="80px"/>
</div>
<div class="name" id="name4">
<img src="image4.jpg" width="80px" height="80px"/>
</div>
<div class="name" id="name5">
<img src="image5.jpg" width="80px" height="80px"/>
</div>
The css controls the name sets to the right. My idea is, click the small image on the right to immediately switch the image which user choose.
It seems working a little bit. The setInterval is still runing and the loop is ruined. How can I deal with this properly? Here is the jsfiddle link. Thanks!
You can stop setInterval from running with clearInterval. Specifically, you need to call it on the return value of setInterval.
var interval = setInterval(...
clearInterval(interval);
EDIT: this doesn't apply directly to your problem. What you can do is just create a separate function that does the callback to setInterval. Then, also call that function as part of the callback to the click event. Whether you want to clear the interval or not (halt the animation) is up to you.
The problem occurs because you change the type of count from a number to a string inside your click handler - when you assign name to count. I've edited your code to include parseInt.
$('.name').click(function(){
var name = $(this).attr('id');
name = name.replace('name', '');
count = parseInt(name, 10);
});
Here's a simple working example
var interval;
var times;
function doSomething() {
if (times == 100) {
// Unset the interval:
clearInterval(interval);
} else {
alert("Hey");
times++;
}
}
// Initialize interval:
interval = setInterval(doSomething, 1000);

Categories

Resources