Fading in with jQuery creating a queue - javascript

I'm trying to create a simple sequence: find first element, hide its siblings and then fade it in. I have this sort of working; however, it does not wait for its siblings to fade out first:
var $firstCaption = $('.caption').first();
$firstCaption.appendTo('.caption-content').siblings('.caption').fadeOut(function(){
$firstCaption.fadeIn(); // this is not waiting
});
I could use a delay, but I think that's quite a messy solution? Is there another method?
JSFIDDLE:
http://jsfiddle.net/tmyie/8VjLD/

You could use a promise:
DEMO jsFiddle
$('a').click(function () {
var $firstCaption = $('.caption').first();
$firstCaption.appendTo('.caption-content').siblings('.caption').fadeOut().promise().done(function () {
$firstCaption.fadeIn();
});
});
BTW, you could wish to use .finish() here if button clicked multiple times in a row:
DEMO with finish
$firstCaption.appendTo('.caption-content').siblings('.caption').finish()...

Related

JavaScript alert callback not working inside a function

I am trying to make a image preview containing of about 5-6 images which will appear one after another when user hovers over it (not like a carousel with prev and next buttons). Here is the fiddle consisting of what I gathered so far.. i don't know if this approach is right or not.. but I am stuck as the alert callback is not working. Could someone please tell me what is wrong?
$(function()
{
var imageCount = $('#product_grid_list').find('figure')[0].getElementsByTagName('img');
for (var i = 0, n = imageCount.length; i < n; i++) {
imageCount[i].on('click', function(e)
{
alert('Everything is going fine!');
}
);
}
}
);
The root cause of click event callback can't be triggered is that you're trying to register a event handler on a "DOM" (in this case: imageCount[i]) element in jQuery way. Try to register the event handler like this if you want to use pure javascript solution:
imageCount[i].addEventListener('click', function(e){
alert('Everything is going fine!');
});
Here is a jsfiddle demo.
Note: I didn't consider the cross browser issue in this case.
BTW, try to cache the length of imageCount node list, it will improve the performance.
You are using js AND jQuery at same time. It's wrong. If you use jQuery, than click event will be like this:
$(document).('click', '#product_grid_list figure img', function(){
alert('Everything is going fine!');
});
You are using a mix of jQuery and standalone javascript. You might as well go all the way to jQuery, with something like:
$('#product_grid_list figure:first img').click(function(e) {
alert('Everything is going fine, hopefully!');
});
You did not send the corresponding HTML, so we cannot test whether the above is correct.
it's just a simple click event in jQuery, no need to use js: http://jsfiddle.net/wP3QQ/11/
$('#product_grid_list').find('figure img').click(function(e){
alert('Everything is going fine!');
e.preventDefault();
});
You want the hover effect, so click event should not be used over here. It should be mouseover.
Working Fiddle
Code Snippet:
$(document).on('mouseover','#product_grid_list figure img',function(e){
alert("now it is working");
});
You are attempting to call on(), a jQuery method, on an HTMLElement (a DOM element). You can't do that, jQuery methods can only be called on jQuery collections. It's easy to get a jQuery collection for the elements you desire:
Use .find() to match the images
There's no need for a for() loop, jQuery's .on() will handle looping for you.
You may also want to prevent the default behaviour of your anchors
$(function () {
var imageCount = $('#product_grid_list').find('figure img');
imageCount.on('click', function (e) {
e.preventDefault()
alert('Everything is going fine!');
})
});
JSFiddle

Showing text for a while

http://jsfiddle.net/639RF/
$("button").click(function () {
//#t holds 'X'
$('#t').fadeOut(1000).text('ZZ').fadeIn(1000);
$('#t').delay(1000);
$('#t').fadeOut(1000).text('YY').fadeIn(1000);
});
I'm trying to show some text for a while, then replacing it with some other text.
The way I was trying to do it ignores the first text I am trying to show, and replacing it with the last one from the beginning.
It should:
Fade 'X' out,
Fade 'ZZ' in,
hold for a second
Fade 'ZZ' out,
Fade 'YY' in.
Every time you call $("#t"), you are creating a new jQuery object. That object may have the same element, but it is still a different object with different properties.
Try this:
var t = $("#t");
t.fadeOut(1000,function() {t.text("ZZ")}).fadeIn(1000);
t.delay(1000);
t.fadeOut(1000,function() {t.text("YY")}).fadeIn(1000);
Edit again: Figured it out! You need to use the animation callback to handle things that aren't normally part of the animation queue.
You can use callbacks as a second parameter to fadeOut and FadeIn, also to wait for a second, you can also use the raw setInterval method.
$(document).ready(function () {
$("button").click(function () {
var $dom = $('#t');
$dom.fadeOut(1000, function(){ //first, fades out.
$dom.text('ZZ').fadeIn(1000,function(){ //changes the text to ZZ,
var $wait = setInterval(function(){ //wait for a second
clearInterval($wait); //prevent the loop of waiting
$dom.fadeOut(1000,function(){ //fadeout for a second
$dom.text('YY').fadeIn(1000); //change the text into YY, and fade in
});
},1000);
});
});
});
});
JSFiddle: http://jsfiddle.net/639RF/3/
How about this?
Note: feel free change the duration as you like.
Demo: JSFiddle
$(document).ready(function () {
$("button").click(function () {
$('#t').fadeOut(500, function(){ //fadeout in half a second and when complete
//fadein in half a second, wait for 2 seconds, when complete
$(this).text('ZZ').fadeIn(500).delay(2000).fadeOut(500, function(){
//fadein in half a second
$(this).text('YY').fadeIn(500)
});
});
});
});

Toggling one thing with two different elements

In my previous question I asked about how can I toggle a textarea with a paragraph. I got the answer. Now I want to do the opposite of it. First I was showing the already hidden textarea + 2 buttons by a click of a hyperlink. Now on the click of one of the buttons I want to hide the text + 2 buttons and show the paragraph that was first already shown.
I have tried this JS so far but it's not working:
$(document).ready(function () {
$(".no_link").click(function (e) {
e.preventDefault();
});
$(".edit_offer").on('click', function () {
toggleEditPanel($(this));
});
$("#cancel_edits").on('click', function () {
$(this).closest("button").hide();
$(this).closest("textarea").hide();
$(this).closest("p.content").show();
});
});
function toggleEditPanel(link) {
link.parent().parent().parent().find("textarea").toggle();
link.parent().parent().parent().find("button").toggle();
link.parent().parent().parent().find("p.content").toggle();
}
But its not working. How can I solve this error?
If I am trying to call the function toggleEditPanel() again. Its not working then aswell.
You can find the markup in the fiddle. Here's the fiddle.
UPDATE 1:
Just came up with a solution. I can use the $.siblings() function to toggle the elements beside the button. Still, is there any better solution?
Here's the code that I came up with:
$("#cancel_edits").on('click', function () {
$(this).hide();
$(this).siblings("button").hide();
$(this).siblings("textarea").hide();
$(this).siblings("p.content").show();
});
UPDATE 2:
The problem in the above code is that if there are more than one panels like this then the code is not working. How can I solve that issue aswell?
You are using Id for selector $("#cancel_edits") .
Id selectors returns only first element , so if there are multiple pannel it will work only for first.
Instead give some class name and use it for selector. Further you can use chaining and caching in your code for better performance.
$(".cancel_edits").on('click', function () {
var elm=$(this);
elm.add(elm.siblings("button,textarea")).hide();
elm.siblings("p.content").show();
});
I would recommend referencing your elements by ID:
$("#cancel_edits").on('click', function () {
$('#save_edits').hide();
$('#edited_content').hide();
$(this).hide();
$("p.content").show();
});
JSFiddle
The great thing about using IDs is that you are guaranteed they are unique - no need to use closest() to find the element you want. If, however, you're using classes instead, closest() might be necessary or helpful.

js number +1 problem

I need click div.toggle1,control slideup, slidedown the div#text1,
click div.toggle7,control slideup, slidedown the div#text7.
here is my code, also in http://jsfiddle.net/qHY8K/ my number +1 not work, need a help. thanks.
html
<div class="toggle1">click</div>
<div id="text1">text1</div>
<div class="toggle7">click</div>
<div id="text7">text2</div>
js code
jQuery(document).ready(function() {
counter = 0;
for(i=1;i<11;i++){
(function(i){
counter = counter +1;
$('.toggle'+counter).toggle(function(){
$('#text'+counter).css('display','none');
},
function() {
$('#text'+counter).css('display','block');
});
})(i);
};
});
Lets simplify things a bit. One of the nice things about jQuery is that you can apply an event handler to many elements all at the same time. Start by adding a common classname to all of your 'toggle' divs:
HTML
<div class="toggle toggle1">click</div>
<div id="text1">text1</div>
<div class="toggle toggle7">click</div>
<div id="text7">text2</div>
Now you can use just one selector to target all of those divs. The rest is just a matter of pulling out the numeric difference in each 'toggle' div's classname:
JavaScript
jQuery(document).ready(function() {
$('.toggle').toggle(off, on);
function on() {
var i = this.className.match(/[0-9]+/)[0];
$('#text'+i).css('display','block');
}
function off() {
var i = this.className.match(/[0-9]+/)[0];
$('#text'+i).css('display','none');
}
});
I've updated your jsFiddle project. Hopefully this works out for you: http://jsfiddle.net/ninjascript/qHY8K/3/
Two solutions:
With your HTML as quoted, you can just do this:
jQuery(document).ready(function() {
$("div.toggle").click(function() {
$(this).next().toggle();
});
});
...since the div you're toggling is the next adjacent div. Note also that I'm using jQuery's toggle function to toggle the visibility.
But if it's possible that may change and you're defending against that, read on...
In your JavaScript code, you're already doing something that makes it possible to avoid the counter entirely, as knitti pointed out. But the way you're doing it creates functions unnecessarily and by using the same name (i) for both your loop counter and the argument to your anonymous function, you're making it very difficult to read and maintain that code.
So:
jQuery(document).ready(function() {
for(i=1;i<11;i++){
makeToggler(i);
}
function makeToggler(index){
$('.toggle'+index).click(function(){
$('#text'+index).toggle();
});
}
});
You can see how nice and clear that makes things, and in particular using a different name for the loop counter and the argument to makeToggler avoids confusion. And again, using jQuery's toggle function, no need for you to do it at the click level. (Also note that you don't put ; after the ending brace of a for statement.)
You don't need hard coded loop.
Preserve your current HTML and have such jQuery code instead:
$("div[class^='toggle']").each(function() {
var num = $(this).attr("class").replace("toggle", "");
$(this).toggle(function(){
$('#text' + num).css('display','none');
},
function() {
$('#text' + num).css('display','block');
});
});
This will iterate over all the <div> elements with class name starting with toggle and attach them the proper toggle function.
Updated jsFiddle: http://jsfiddle.net/qHY8K/5/
why do you introduce a new variable counter? (you should use var counter = 0; if you do).
in your function you could simply use your copied loop variable i:
for(i=1;i<11;i++){
(function(i){
$('.toggle'+i).toggle(function(){
$('#text'+i).css('display','none');
},
function() {
$('#text'+i).css('display','block');
});
})(i);
};
If your HTML has the structure as above, you could give all the toggleX elements the same class toggle and then all you have to do is:
$('.toggle').toggle(function(){
$(this).next().css('display','none');
},
function() {
$(this).next().css('display','block');
});
DEMO

How to toggle a function for multiple divs at once?

I previously got this (useful!) answer about using .next() for a DIV "blinds" toggling effect.
However, I can't seem to get this simple function to work for more than one DIV at the same time:
$(document).ready(function () {
$("#closeButton").click(function () {
$(this).next().toggle("fast");
});
});
Any ideas?
The selector you are using is only selecting one element. You would need to change is to it selected a collection of elements.
$(document).ready(function () {
$(".wider_div h3").click(function () {
$(this).next().toggle("fast");
});
});
This might work given the structure.
Is it about a specific type of button that occurs multiple times on a page? Try using jQuery's live():
$(document.ready(function() {
$('button.your_class').live('click', function (){
$(this).toggle('fast');
});
});
and attach the appropriate class to the buttons you want to 'be listened'.

Categories

Resources