Fairly new to JavaScript and very new to jQuery. Can someone have a look at the following code and see where I am going wrong.
This is the main part of the jQuery code:
$(document).on("hover", ".crrightcontainer img", function() { /* trigger event on hover on an img in class crrightcontainer */
var src = $(this).attr('src'); // get full path and filename from thumbnail
var index = src.lastIndexOf('/') + 1; // get index to last occurrenace of file path delimiter "/"
var fullsizeimgname = src.substr(index); // get actual filename only i.e. "cs1.jpg"
fullsizeimgname = "/painted/fp-images/" + fullsizeimgname; // add path to give full path to the full sized image.
$('.crleftcontainer img').animate({opacity: 0.0},1000); // fade out old full size image
$('.crleftcontainer img').attr("src",fullsizeimgname).animate({opacity: 1.0},1000); // set full size image in browser and fade in
});
http://jsfiddle.net/deanflyer/CfxyJ/1
It works, it just seems to fire off multiple mouse events. Just move the mouse a few times over the thumbnail images and youll see what I mean, giving multiple fades.
I've tried using .stop() on the main image with animate() but this just stops everything.
Many Thanks.
Is something like this your requirement try this: http://jsfiddle.net/CfxyJ/13/
$('.crrightcontainer img').css('opacity', 0.7);
$('.crrightcontainer img').mouseenter(function () {
$(this).stop().animate({opacity: 1.0}, 600);
var src = $(this).attr('src');
var index = src.lastIndexOf('/') + 1;
var fullsizeimgname = src.substr(index);
fullsizeimgname = "http://thepaintedtree.co.uk/fp-images/" + fullsizeimgname;
$('.crleftcontainer img').fadeOut('slow', function(){
$('.crleftcontainer img').attr("src", fullsizeimgname).fadeIn('slow');
});
});
$('.crrightcontainer img').mouseleave(function () { //fadeout
$(this).stop().animate({
opacity: 0.7
}, 600);
});
Try using mouseenter event. See updated fiddle http://jsfiddle.net/CfxyJ/25/. Is it what you are looking for?
Related
I'm working to create an image gallery where the images will be composed by progressively fading in layers one on top of the other to form the final image.
I have many such layers so instead of loading them into many different <img> elements all at once (which would slow load time) I want to start off with a single <img id="base"> and then progressively add image elements with the jQuery .after() method, assign them the relevant sources and fade them in with a delay.
The problem is that I can't attach animations to the newly created elements because (I'm assuming) they don't exist yet within the same function. Here is my code:
HTML
<div id="gallery">
<img id="base" src="image-1.jpg">
</div>
CSS
#base {
opacity: 0;
}
.layers {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
JavaScript
$(document).ready(function () {
$("#base").animate({opacity: 1}, 300); //fade in base
for (var i = 1; i <= numberOfLayers; i++, gap += 300) {
// create a new element
$("#base").after("<img class='layers' src='" + imgName + ".png'>");
// fade that new element in
$("#gallery").children().eq(i).delay(gap).animate({opacity: '1'}, 300);
}
}
Please note that I've altered my actual code to illustrate this better. I'm fairly new at JavaScript but I'm a quick learner so I'd appreciate if you could tell me what I'm doing wrong and what solution I should pursue.
EDIT: I've included my code inside your JSFiddle (all you need to do is add the library-X.jpg images) : http://jsfiddle.net/pgoevx03/
I've tried to replicate the intent of the code in a cleaner/more flexible way. Please let me know if I can do anything else to help.
I'm not saying this is the best way to do it, but it should be easy enough to understand and use.
The code is untested, but should work just fine. The comments should help you out if there's any compilation error.
Note that I removed the first image in the gallery (with ID "base") from the HTML file. It will be appended the same way as the rest.
// Array storing all the images to append to the gallery
var galleryImages = [
"image-1.jpg",
"image-2.jpg",
"image-3.jpg",
"image-4.jpg",
"image-5.jpg",
"image-6.jpg",
"image-7.jpg",
"image-8.jpg",
"image-9.jpg",
"image-10.jpg"
];
// Index of the image about to be appended
var imgIndex = -1;
var baseID = "base";
$(document).ready(function() {
// Start appending images
appendAllImages();
});
// Append the images, one at a time, at the end of the gallery
function appendAllImages() {
//Move to the next image
imgIndex++;
//We've reached the last image: stop appending
if (imgIndex >= galleryImages.length) return;
//Create image object
var img = $("<img>", {
src: galleryImages[imgIndex],
});
if (imgIndex === 0) { // It's the base!
//Give the base ID to the first image
img.attr("id", baseID);
//Append the image object
$("#gallery").append(img);
} else { // It's a layer!
//Give the base ID to the first image
img.attr("class", "layers");
//Append the image object
$("#" + baseID).after(img);
}
//Fade in the image appended; append the next image once it's done fading in
img.animate({
opacity: 1,
}, 300, appendAllImages);
}
I don't know how much people have used this plugin, demo but what I want is to change the default behavior of the plugin to something like animated. Currently, when you click on next or previous button, the images will be just appended without any visual animation. I just want to animate the images while appending! Can anybody suggest any good solution!! Below is the code where appending on the image takes place:
if (href.match(/\.(jpeg|jpg|gif|png)$/i) !== null) {
var img = $('<img>', { src: href });
img.one('load', function () {
var wrap = $('<div class="nivo-lightbox-image" />');
wrap.append(img); //gets appended here
content.html(wrap).removeClass('nivo-lightbox-loading');
// Vertically center images
wrap.css({
'line-height': $('.nivo-lightbox-content').height() + 'px',
'height': $('.nivo-lightbox-content').height() + 'px' // For Firefox
});
}).each(function () {
if (this.complete) $(this).load();
});
}
OK with any sort of animation
Well I just added a fadeIn after appending which seems to do some sort of animation although which is what I was accepting. Here is what I did:
wrap.append(img).fadeIn('4000');
I'm trying to create an image slider using Jquery.
What I have is a main div with 3 sub divs with images.
Take a look at this fiddle. FIDDLE
Ok now i got the design just the way I want it. What is missing is the functionality.
When i hover over the div or the images, I want it to act like a clockwise slider.
This may look a bit confusing. Take a look at this demo. This is what i want.
DEMO
This is what i want.The right div gets filled with the middle image src , the middle div gets the left div src. The left div get an new src from an array of images i have defined. Currently i can only change one image div at a time.
However I don't want to use any more plugins. Only Jquery plugin. A CSS only solution would be the best but I do not think it will be possible.
JQUERY
$('.maindiv img').mouseover(function () {
var image = this;
loop = setInterval(function () {
if (i < images.length - 1) {
i++;
$(image).attr('src', images[i]);
} else {
i = 0;
$(image).attr('src', images[i]);
}
}, 1500);
EDIT: I managed to get one part of this working. CHECK THIS.Just need to add fade effect Now the problem is after the images in the array end the first images dont loop back... Had not thought of this before.Does Anybody know how i can get over this issue?
Mabye something like this:
jQuery(document).ready(function () {
var images = [];
var loop;
var i = 0;
images[0] = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ1GfA01TRDgrh-c5xWzrwSuiapiZ6b-yzDoS5JpmeVoB0ZCA87";
images[1] = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQQSyUWiS4UUhdP1Xz81I_sFG6QNAyxN7KLGLI0-RjroNcZ5-HLiw";
images[2] = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT_E_OgC6RiyFxKtw03NeWyelfRgJ3Ax3SnZZrufNkUe0nX3pjQ";
$('img', '.maindiv').mouseover(function () {
//Get divs inside main div and reverse them, so right is first
var divs = $($('div','.maindiv').get().reverse());
//Set up loop
loop = setInterval(function(){
divs.each(function(key, div){
if (divs[key+1])
{
//All divs gets image src from previous div > img
$('img', div).attr('src', $('img', $(divs[key+1])).attr('src'));
}
else
{
//This is left div
if (images && images[i])
{
//If picture url not in array then add it
if ($.inArray($('img', div).attr('src'), images) == -1)
{
images.push($('img', div).attr('src'));
}
$('img', div).attr('src', images[i]);
i++;
if (i>= images.length) i = 0;
}
}
});
}, 1500);
}).mouseout(function(){
clearInterval(loop);
});
});
Fiddle
I currently use the following to fade images on my site:
$(document).ready(function() {
$('ul.image-switch li').mouseover(function(e) {
if (e.target.nodeName.toLowerCase() == 'a') return;
var image_src = $('a', this).data('image');
var img = $('.image-container img');
if (img.attr('src') != image_src) { // only do the fade if other image is selected
img.fadeOut(200, function() { // fadeout current image
img.attr('src', image_src).fadeIn(200); // load and fadein new image
});
}
});
});
An example of this in action is at http://www.sehkelly.com/#news.
As you can see, the current image must fade out before the new one fades in.
I'd like the action to be simulaneous. Please -- does anyone know how I can achieve this?
Many thanks.
EDIT: Clueless novice. Code examples very much appreciated.
Create a new img element on top of the actual one, then fadeIn this new image. You'll need a bit of css to put the new image on top of the old one.
In no way you can do that with only one img element.
if (img.attr('src') != image_src) { // only do the fade if other image is selected
img.after(
$('<img />').attr('src', image_src).fadeIn(200)
);
img.fadeOut(200);
}
You would too want to wait for the new image to be loaded before starting fades. (checkout jQuery doc for the right function for that, and fade the images in the load callback).
Here's an implementation of Ulflander's idea, since the code posted is not complete http://jsfiddle.net/8nBqD/1/
The trick is to absolutely position the second image on top of the one you're fading out
HTML
<img id='pic1' src="http://periodictable.com/Samples/009.3b/s7.JPG" />
<img id='pic2' src="http://icons.iconarchive.com/icons/vargas21/aquave-metal/256/Sample-icon.png" />
CSS
#pic2 {
position: absolute;
display: none;
}
JS
// Fade out the image, and replace it with the new one after the fade is over
$("#pic1").fadeOut(500, function() { // fadeout current image
this.src = 'http://icons.iconarchive.com/icons/vargas21/aquave-metal/256/Sample-icon.png';
$(this).show();
});
// Fade in the new image placing it on top of the original one
$("#pic2").offset($("#pic1").offset()).fadeIn(500, function(){
// Hide it since we are showing the original image with the new src
$(this).hide();
});
We could even write a plugin to make this easy to reuse
(function($) {
$.fn.imageFader = function(newSrc, seconds) {
$(this).each(function() {
var $img = $(this);
$img.fadeOut(seconds, function() {
this.src = newSrc;
$img.show();
});
var $tempImg = $('<img src="'+newSrc+'" style="position:absolute;display:none;" />').appendTo('body');
$tempImg.offset($img.offset()).fadeIn(seconds, function(){
$tempImg.remove();
});
});
};
})(jQuery);
And use it like http://jsfiddle.net/8nBqD/5/
$('img').imageFader('picture.png', 1000);
I've got quite the problem with jQuery and a custom photo gallery I am building. I've searched high and low and tried endlessly different solutions but nothing is working perfectly. So let me present the information:
This photo gallery has thumbnails on the left side and a big image in the center. Every thumbnail can be clicked which calls a function passing in its' ID. What I want it to do is, AJAX POST to server to get image comment and image name. Fadeout the current big picture div, switch the src in the img tag, get the new image's width, set the width of an overlaying comment div, fadeIn the big picture div.
The problem is that I can't get the width of the new image after it has loaded (even using the a form of .load() to wait for the image to finish loading). Now I can get it to work when I fadeIn the new image and then get the width but that isn't what I need. I need to get the width and set the div's width before I fadeIn.
Any ideas or corrections would be great, hopefully I have provided enough information.
Here is the code I am wrestling with:
function thumbClick(val) {
$.post('ajax.php', {
photo_in: val
}, function (data) {
$('div#picture').fadeOut('slow', function () {
//$('img#big-picture').load(function(){
$('img#big-picture').one('load', function () {
//alert($('img#big-picture').width());
//will alert 0
$('div#picture').fadeIn('slow', function () {
$('div#comment-box').width($('img#big-picture').width());
//set comment to what I want
$('p#comment').html("");
//alert($('img#big-picture').width());
//will alert new image width after FadeIN
$('p#comment').html(data.comment);
});
}); //end of one(load)
$('img#big-picture').attr("src", data.newImage);
}); //end of fadeout
}, "json"); //end of post
}
I've encountered this before; what seems to be the easiest solution is to quickly show the image, grab it's width, and hide it again. This operation occurs so quickly users will never notice.
In your case, i believe the code would be:
$("#big-picture").show();
alert($('#big-picture').width()); //this should be the real width, now
$("#big-picture").hide();
The width is zero because hidden elements (elements with display: none have, by definition, zero height and width). After fadeOut(), jQuery hides the element(s). A few different solutions:
Use .fadeTo(), not .fadeOut():
$('#picture').fadeTo('slow', 0, function () {
var $pic = $(this);
$('#big-picture').one('load', function () {
var $bigPic = $(this);
$pic.fadeIn('slow', function () {
$('#comment-box').width($bigPic.width());
$('#comment').html(data.comment);
});
}).attr('src', data.newImage);
});
Use a separage <img> element:
$('#picture').fadeOut('slow', function () {
var $pic = $(this);
$('#big-picture').one('load', function () {
var img = new Image(),
width;
img.src = this.src;
width = img.width;
$pic.fadeIn('slow', function () {
$('#comment-box').width(width);
$('#comment').html(data.comment);
});
}).attr('src', data.newImage);
});
Use the "off-left" technique:
CSS
.off-left {
position: absolute;
left: -99999px;
}
JavaScript
$('#picture').fadeOut('slow', function () {
var $pic = $(this);
$('#big-picture').one('load', function () {
var $this = $(this),
width = $this.addClass('off-left').show().width();
$this.removeClass('off-left').hide();
$('#picture').fadeIn('slow', function () {
$('#comment-box').width(width);
$('#comment').html(data.comment);
});
}).attr('src', data.newImage);
});
Notes
When using an ID selector, there's no point in qualifying the selector further, since element IDs must be unique.
Pick a quote style and use it consistently. Avoid mixing single- and double-quotes as string delimiters.
You should be able to set the CSS property visibility to hidden and then get the width, as visibility doesn't take it out of the document flow (like display: none), but simply makes it invisible. Just make sure you set the visibility property back to visible when you fade in.