jQuery src replace crossfade on hover - javascript

I have a couple of images on my Joomla site, each one with a black&white version and a color version. I'd like to change a part of the src ('bw' to 'color') when hovered over with a nice crossfade. I'm very new to jQuery, so the only code I have is this, which is probably completely wrong.
$(".grey img").mouseover(function() {
$(this).attr('src', function(i, src) {
return src.replace( 'bw', 'color' ).fadeIn(800);
});
$(".grey img").mouseout(function() {
$(this).attr('src', function(i, src) {
return src.replace( 'color', 'bw' ).fadeOut();
});
I've searched for a solution for hours and at this point I'm not sure if it's really obvious and I'm completely missing it. So, sorry if it is, or if there is a solution somewhere and I didn't look enough.
I would like to solve this without having to link two images in the html, but if there's no other solution, I would be thankful for any tips on how to achieve this.

You have to get the source initially before you can change it. I'll also clean it up a bit:
$('.grey').on({
mouseenter:function(){
var $this = $(this),
src = $this.attr('src').replace('bw','color');
$this.fadeOut(function(){
$this
.attr('src',src)
.on('load',function(){
$this.fadeIn();
});
});
},
mouseleave:function(){
var $this = $(this),
src = $this.attr('src').replace('color','bw');
$this.fadeOut(function(){
$this
.attr('src',src)
.on('load',function(){
$this.fadeIn();
});
});
}
},'img');
As you can see, you were on the right track, but you just need to capture the source before you can manipulate it. The other changes I made were:
Using .on() which allows for single binding event
Using mouseenter and mouseleave instead of mouseover and mouseout
Delegating .on() assignments to all img contained in .grey
Also I used a variable for cleanliness of reading, but you could have just as easily placed the $(this).attr('src').replace('bw','color') in the assignment and foregone the variable entirely.
EDIT - updated to show fadeIn/fadeOut on image change.

Related

DOM change - no effect. Effect visible only if changed with timeout

Weird problem. I'm modifying shop template:
https://demo.themeisle.com/shop-isle/product-category/clothing/dresses/
At this moment when you hover product's picture there will show "add to cart" button. This is .
Under picture there is price
I prepared code:
var from = document.getElementsByClassName("woocommerce-Price-amount amount");
jQuery(document).ready(function(){
jQuery.each(from, function(i, el) {
jQuery(el.parentNode.parentNode).find(jQuery(".product-button-wrap")).append(el);
});
});
Nothing happens. This code work only if I set timeout:
setTimeout(function() {
var from = document.getElementsByClassName("woocommerce-Price-amount amount");
jQuery(document).ready(function(){
jQuery.each(from, function(i, el) {
jQuery(el.parentNode.parentNode).find(jQuery(".product-button-wrap")).append(el);
});
});
}, 10000);
Of course timeout it's not a solution. I was trying to find out minimal time to obtain best behavior but it's impossible. I have feeling that every browser (and version...) needs personalized time setting.
I thought that after 24-hour break I will get some brillant idea, but that doesn't work, no more ideas.
--- EDIT ---
OK, thanks for pointed mixed common js with jquery - I will correct that later.
jQuery(document).ready(function(){
var from = document.getElementsByClassName("woocommerce-Price-amount amount");
jQuery.each(from, function(i, el) {
jQuery(el.parentNode.parentNode).find(jQuery(".product-button-wrap")).append(el);
console.log(el);
});
});
That's logical that var from should be inside ready but this still doesn't work. No effect.
If I use in loop console.log it will return for me html code of el.
--- EDIT ---
Thanks. While testing I noticed something. I wanted append element .woocommerce-Price-amount.amount to element .product-button-wrap. But how can I do that if element .product-button-wrap isn't originally in source? This object is created dynamically (I don't know how).
-- EDIT --
OK. I checked JS files and found code adding to DOM .product-button-wrap so I putted my code there and now everything works. Thanks for help.
The problem is because you're running your code before the DOM has loaded. You need to retrieve the elements within the document.ready event handler.
Also note that you have an odd mix of native JS and jQuery methods. I'd suggest using one or the other, like this:
jQuery(function($) {
$('.woocommerce-Price-amount.amount').each(function() {
$(this).parent().parent().find('.product-button-wrap').append(this);
});
});
Also note that .parent().parent() should be replace by a single call to closest(), but I can't give you an exact example of that without seeing your HTML.

Animate children of a div that have been created within a function (with js or jquery)

I'm taking a coding class at school and am very new to javascript, so hopefully what I'm asking will make sense!
Right now I have a page where if you click an html button, an image of a worm appears in a div below it (called "bugs"). the same image appears each time you click the button. I've done this by having the button click call a function that creates an img element and adds it as a child of the div. the issue is I want the images to move randomly around the page or even just inside the div. I've found some code that will animate a div so it moves randomly using jQuery (here), but I can't for the life of me figure out how to apply it to the images.
The js code that makes the images looks like this:
var BugSpace = document.getElementById("bugs");
function NewWorm(){
WormPic = document.createElement("img");
WormPic.src = "worm.png";
BugSpace.appendChild(WormPic);
};
Most of my code is pieced together from various tutorials so is likely pretty convoluted. anyway, if anyone can figure this out I'll be eternally grateful :~)
Edit: I suppose I should further clarify that the code includes two other buttons to make two other types of bugs! I'd like to be able to have a few images of each bug moving on the page at once. I figure the best way to do this is to find a way to animate the children of the "bug" div? I am, however, wondering if the answer to my problem might turn out to be a complete reworking of the code I have now!
If you're comfortable using jQuery, then you can use the following solution.
You basically still animate the div and because the img is contained within the div, it will animate too.
All you need to do is call the animateDiv() function after you've added the image.
$(document).ready(function(){
$button = $('#button');
$bug = $('#bug');
$wormimg = "<img src='http://bit.ly/1r7l5ns' class='worm'/>";
$button.on('click', function(){
$bug.html($wormimg);
animateDiv();
});
});
The animateDiv() function here is exactly the same as the link you've provided.
Have a look at the jsfiddle: http://jsfiddle.net/3xgqogkk/
EDIT (based on more information from the comments)
So the new core javascript looks like:
$(document).ready(function(){
$button = $('#button');
$bug = $('#bug');
$wormimg = "<img src='http://bit.ly/1r7l5ns' class='worm'/>";
$button.on('click', function(){
$bug.append($wormimg); //Changed this to append so we can add more than 1
animateDiv($bug.children().last());
//We're basically passing the last worm you've added as a variable
});
});
Which means you have to make some modifications to the animateDiv() method, which is now actually animateDiv($worm)
function animateDiv($worm){
var newq = makeNewPosition();
var oldq = $worm.offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$worm.animate({ top: newq[0], left: newq[1] }, speed, function(){
animateDiv($worm);
});
};
The important thing is to understand everything that's happening here, so if you have any questions, just ask :)
The jsfiddle is also updated: http://jsfiddle.net/3xgqogkk/

jquery show another link then hide itself

I have this following jquery on my view:
$(document).ready(function() {
$(function() {
$('#link1').click(function() {
$('#link2').show();
$('#link1').hide();
$('#frame').attr('src', 'http://google.com/');
});
});
});
$(document).ready(function() {
$(function() {
$('#link2').click(function() {
$('#link1').show();
$('#link2').hide();
$('#frame').attr('src', 'http://yahoo.com/');
});
});
});
On pageload, the link2 is set to hide. What the jQuery does is: when the link with id link1 is clicked, it will show the link with idlink2 and hide itself. And vice versa.
My problem is it seems that my jQuery code can still be simplified. Is there other ways I can do what I wanted with simpler version? Thanks for the help!
Working example : http://jsfiddle.net/cuJBm/
$(document).ready(function() {
$(function() {
var linkSet = $('#link1').add('#link2')
linkSet.click(function() {
linkSet.toggle();
});
});
});
The add method allows you to add a different selector to the set of matchers, thus binding both clicks simultaneously. By saving the constructed set to a variable (linkSet), it stops you from having to traverse the DOM twice.
The only two assumption made here, are
1) That in the initial state only one is visible.
2) That the id structure is meaningful, useful, and classes will not suffice.
http://jsfiddle.net/cuJBm/1/
To answer your second question about setting an attribute on #frame. There are numerous ways of doing this. Perhaps the simplest is to add the following to your .click handler (after the toggle).
if ($(this).attr('id')=='link1'){
$('#frame').attr('src', 'www.google.com');
} else if ($(this).attr('id')=='link2'){
$('#frame').attr('src', 'www.yahoo.com');
}
Personally, I would probably add a custom attribute to your link elements, something like:
<a id='link1' iframe-source='www.google.com'>
<a id='link2' iframe-source='www.yahoo.com'>
And then: (again, just after the toggle):
source = $(this).attr('iframe-source');
$('#frame').attr(src, source);
The reason for saving source if is that if you attempt to get $(this) within the .attr on $('frame'), it will (as always) return the currently matched element, ie $('#frame').
Alternately (and very similiarly to the above approach), you could use the innerHTML of the link. For example:
<a id='link1'>link1<span style="display:none">www.google.com</span></a>
<a id='link2'>link2<span style="display:none">www.yahoo.com</span></a>
And then: (again, just after the toggle):
source = $(this).find('span').text();
$('#frame').attr(src, source);
Personally, I dislike this last method as it pollutes the DOM structure, leading to slightly more expensive rendering times, and (in my opinion) less readable code. Practically, all three methods work just fine.
<p class="link" style="display:none;" data-link="http://google.com/">sfdf</p>
<p class="link" data-link="http://yahoo.com/">ee</p>
$('.link').click(function() {
$('.link').toggle();
$('#frame').text($(this).data("link"));
});
jsfiddle :http://jsfiddle.net/xqDus/1/
Use jQuery toggle()
just add this
Google
Yahoo
target is id of the frame
$(function() {
$('#link1, #link2').click(function() {
$('#link1, #link2').toggle();
});
});

Changing image source with Jquery

Using Jquery, I've managed to make a dropdown login form triggered by clicking a button. However, I am also trying to change the direction of the arrow next to it by replacing the src image, and it appears to do nothing.
$("#login_panel").slideToggle(200).toggle(
function() { $("#arrow").attr('src', '/src/east.gif';) },
function() { $("#arrow").attr('src', '/src/south.gif';) }
);
This can be seen at:
http://dev.mcmodcenter.net (The 'Login' button)
$(document).ready(function() {
$("#login_panel").slideToggle(200).toggle(
function() { $("#arrow").attr('src', '/src/east.gif';) },
function() { $("#arrow").attr('src', '/src/south.gif';) }
);
for (var i = 0; i < 2; i++) {
$(".mod").clone().insertAfter(".mod");
}
$(".mod").lazyload({
effect: "fadeIn"
});
});
You can directly access this.src - no need to create a new jQuery object for that:
$('#arrow').toggle(
function() { this.src = '/src/south.gif'; },
function() { this.src = '/src/east.gif'; }
);
And if you prefer to do it via .attr() at least use $(this) (DRY - don't repeat yourself - in this case, don't specify the selector more often than necessary)
$("#arrow").toggle(
function(){$("#arrow").attr("src", "/src/south.gif");},
function(){$("#arrow").attr("src", "/src/east.gif");}
);
You left off the "#" in the handler functions. By just referring to "arrow", you were telling jQuery to look for (presumably absent) <arrow> tags.
Now, as to the larger situation, what you're setting up there is something that'll make the image change when the image itself is clicked. Your description of your goal makes me think that that's not quite what you want, but it's hard to tell. If you want some other element to control the changes to the image, then you'd attach the handler(s) elsewhere.
Is the image you want to change that little black arrow next to the login button? If so, then what should happen is that the code to set the image should be added to the existing handler that slides the login form up and down. (By the way, in Chrome the login box shows up in what seems like an odd place, far to the left of the button.)
looks like you forget to put the # before the arrow in $("arrow")
it should be like this
$("#arrow").toggle(
function(){$("#arrow").attr("src", "/src/south.gif");},
function(){$("#arrow").attr("src", "/src/east.gif");}
);
$("arrow") will match <arrow>, you lost the #
Also, the toggle method does not take two functions as its arguments, it works in a completely different way to what you are trying to do with it. Yes, it does, there are two different toggle methods for jQuery (insert rant about awful API design)
And now you have completely edited the code…
Your code now immediately assigns strings to the this.src (where this is (I think) the document object), and then passes those two strings as arguments to the toggle method (which are not acceptable arguments for it)
And now you have completely edited it again…
This code should work:
$('#login_button').click(function() {
$(this).find('#arrow').attr('src', function(i, v) {
return v.indexOf('east.gif') < 0 ? '/src/east.gif' : '/src/south.gif';
});
$('#login_panel').slideToggle(200);
});

jQuery Image Change - Gallery View

I have a large image in a gallery that needs to change when one of the thumbnails is clicked within a unordered list below. The images are coming in dynamically so the jquery script needs to be able to take the src of the thumbnail, remove "-thumb" from the filename, and then replace the large image with the new source.
Please let me know what is my best approach to a gallery like this.
Thanks in advance.
-B
Something like:
$('img.thumb').click(function() {
var src = $(this).attr('src');
$('#bigImage').attr('src', src.replace(/-thumb/,''));
});
The below examples apply if your thumbs are being loaded in via ajax:
(1) Using Events/live:
$('img.thumb').live("click", function() {
var src = $(this).attr('src');
$('#bigImage').attr('src', src.replace(/-thumb/,''));
});
(2) As a callback to one of jQuery's ajax methods (e.g.):
function initThumbs()
{
$('img.thumb').click(function() {
var src = $(this).attr('src');
$('#bigImage').attr('src', src.replace(/-thumb/,''));
});
}
$('#thumbsDiv').load('thumbs.php?p=2', initThumbs);
karim79's answer could be shortened slightly:
$('img.thumb').click(function() {
$('#bigImage').attr('src', $(this).attr('src').replace(/-thumb/,''));
});
But otherwise, good answer!
The only addition to karim79's is:
In a case the thumbnails are placed within same parent binding an event on that parent would be much better (elegant?) solution that binding events on all thumbnails. The event is propagated, so you can find thumbnails by checking event target.
$().ready(function() {
//get all images from unordered list and apply click function
$('ul#myList img').each(function() {
$(this).click(function() {
$('#mainImage').attr('src', $(this).attr('src').replace('-thumb', ''));
});
});
});

Categories

Resources