Reverting jquery animations back to original css states - javascript

I've got a page of elements, each of which, depending on user interaction, may be animated away by the given function:
function slideAndFade(id){
$(id).animate({opacity: 'toggle', width: 'toggle'}, 500);
}
I want to create a reset function that brings all the elements back onto the page. Running all the elements through the toggle function above won't work, because currently hidden elements will be shown, and currently shown elements will be hidden.
Essentially looking for way to revert all elements to their original css states, regardless of whether they've been acted upon by jquery animation.
Thanks-
Edit:
Just realized all I need to do is replace 'toggle' with 'show':
function revertSlideAndFade(id){
$(id).animate({opacity: 'show', width: 'show'}, 500);
}
Calling this on any element will ensure the element is reverted back to visible in this case. However, see Nick's answer below for a more generally applicable approach.

If you could identify all the elements that might be passed into this function, say they had a class .toggleElem you could use that to store the values on page load and restore then when needed, like this:
$(function() {
$(".toggleElem").each(function() {
var $this = $(this);
$.data(this, 'css', { opacity: $this.css('opacity'),
width: $this.css('width') });
});
});
Then you could restore them at any point later:
function restore() {
$(".toggleElem").each(function() {
var orig = $.data(this, 'css');
$(this).animate({opacity: orig.opacity, width: orig.width}, 500);
});
}

Related

Why a click event in jquery doesn't apply to my new element?

I have three divs with left, center and right classes and I want to interchange their position and apply new classes as they go to thei new positions. But for some reason it doesn't work
This is my script:
$(function() {
$(".left").css("left","50px");
$(".center").css("left","300px");
$(".center").css("width","300px");
$(".center").css("height","300px");
$(".center").css("top","25px");
$(".right").css("left","650px");
$(".right").click(function(){
$(".left").animate({
left: '650px'
}, 1000, function() {
});
$(".center").animate({
left: '50px',
width: '200px',
top: '75px',
height: '200px'
}, 1000, function() {
});
$(".right").animate({
left: '300px',
width: '300px',
height: '300px',
top: '25px'
}, 1000, function() {
});
$(".bule").removeClass("left right center");
$(".second").addClass("left");
$(".third").addClass("center");
$(".first").addClass("right");
$(".bule").removeClass("first second third");
$(".left").addClass("first");
$(".center").addClass("second");
$(".right").addClass("third");
});
});
Here is a working example.
When you select elements using a jQuery selector $('...') - the selection is evaluated and the following actions are taken on those elements. If later, you remove a class or change the ID of a selected element, those actions have already been taken - so they will stick. Similarly, they won't automatically inherit actions from other selectors (since they didn't have that class/ID at the time the selection was made).
If you want to bind events once, and have them work when new elements are added, or classes are changed, you need to use a slightly different event syntax:
$('body').on('click', '.right', function() {
});
Notice how the selector is now the body element (since the body element will always exist when this runs). What you are telling jQuery here is to bind a click event to the <body> element, and, when a child of <body> is clicked, evaluate the element against the expression .right. If that expression matches, call my function.
This method takes advantage of javascript event propagation, where events bubble all the way back up to their highest ancestor. This means that clicking on a link inside of a div will trigger a click event for the link, div, and body - in that order.

Checking for visibility of a toggled element

I have a button which toggles the visibility of a <div> below it and want to modify the text on the button depending on the visibility of said <div>.
Here is a live demo on jsFiddle
If you click on "Saved Data", the first time it works correctly, but the next time you click the text does not change. This in itself is behaviour that I don't understand.
Now, I could use multiple handlers for slideToggle(), however, elsewhere in the code I also set intervals which load data next to "Cookie data:" and "Server data:". I don't want these intervals to do anything if the <div> is not visible so I use something like this:
this.timer_cookiedata = setInterval(function(){
if (!$savedData.is(':visible'))
{
return null;
}
// ..
});
I'm worried these intervals are not going to work properly because of this is(':visible') business. So the question is, why does this happen (else statement is ignored), and what can I do to mitigate this?
Check out the updated fiddle. When you check for visibility right after you call slideToggle, jQuery may not have updated the visibility of the element yet since the animation takes some time to finish. For this exact reason, slideToggle has a callback you can use to perform operations after the animation has finished:
$(function () {
var $savedData = $('#savedData');
$('#btn-savedData')
.click(function () {
var $button = jQuery(this);
//I'm checking the visibility in the callback. Inside the callback,
//I can be sure that the animation has completed and the visibility
//has been updated.
$savedData.slideToggle('fast', function () {
if ($savedData.is(':visible')) {
$button.html('visible');
} else {
$button.html('not visible');
}
});
});
});​

replaceWith & fadeIn/fadeOut - hover not working afterwards

I have a task here that requires heavy DOM manipulation. Because this can have a bad impact on the performance, I clone the element, make the changes there and replace the clone with the original.
After replacement, the elements have a hover function.
Because I want faded transition, I do the change like this:
myElement.fadeOut(500, function(){
myClone.hide();
myElement.replaceWith(myClone);
myClone.fadeIn(500);
});
This is working, but after that the hover functionality does not work anymore. When I remove the callback from fadeOut, I can hover again but the timed transitions does not look good anymore.
What can I do about it? Why do the elements lose their hover-functionality when using the callback?
i have a different solution for you. CSS approach:
You can set one of your element's position;
#myElement { top:100px; left:200px; }
#myElement, #myClone { position:absolute; }
jQuery:
$(document).ready(function() {
var myElement = $('#myElement');
var myClone = $('#myClone');
var myEleTop = parseInt(myElement.css('top'));
var myEleLeft = parseInt(myElement.css('left'));
myClone.hide();
myClone.css({'top':myEleTop+'px','left':myEleLeft+'px'});//sets position here
myElement.mouseenter(function() {
myElement.fadeOut(500, function(){
myClone.fadeIn(500);
}
});
myElement.mouseleave(function() {
myClone.fadeOut(500, function(){
myElement.fadeIn(500);
}
});
});
or you can just use appendTo() and remove() methods, i am not really experienced with these methods but try this:
myElement.mouseenter(function() {
myElement.fadeOut(500, function(){
myElement.remove();
myClone.appendTo($('.container'));
myClone.fadeIn(500);
}
});
myElement.mouseleave(function() {
myClone.fadeOut(500, function(){
myClone.remove();
myElement.appendTo($('.container'));
myElement.fadeIn(500);
}
});
When an object is cloned, the clone will no longer have event listeners attached to it. One way to fix it is to attach the event handlers using "on":
$("my-clone-container").on("hover", "my-clone-selector", myHoverHandler);
This way, whenever you add a clone, it will automagically handle hover events as you want it to. See the docs for 'on'.

Changing a specific Instance without ID

Ok, let's say that I have multiple links on a page and I want links to change background color when you roll over them. I would use this code:
$(function() {
$('a').mouseover(function() {
$('a').css('background-color', 'black');
});
});
$(function() {
$('a').mouseleave(function() {
$('a').css('background-color', 'white');
});
});
the problem with this code is that when you roll over one a, all of the links change color. I could give each a a specific ID and make a specific function for each, but is there a more efficient way to do this?
Edit: Additionally, what could I do to set the original background color back to the way it was. If I turn the background back to white, It might not have been white in the first place. How could I fix this?
In your version you use $('a') to call the .css() function on. The Problem is that $('a') selects ALL the a nodes on the page and not only the one that you moved your mouse over. Within the mouseover callback function the this keyword references the node that was the originator of the event. So when you do $(this) within that function you'll create a jQuery object (called a wrapped set) of that node. Now you can call all jquery functions on it, uncluding the .css() function. So here you go:
$(function() {
$('a').mouseover(function() {
$(this).css('background-color', 'black');
});
});
$(function() {
$('a').mouseleave(function() {
$(this).css('background-color', 'white');
});
});
Just so you know, you're all going about it the long and hard way.
// this is like document.onload = function,
// this only needs to be called once, you can put
// all your jQuery in this one function
$(function() {
// the following is a call to all `a` links to add jQuery's own .hover function
// see -> http://api.jquery.com/hover/
$("a").hover(function(eIn) { // this first function is the action taken when
// user hovers over the link
$(this).css({ 'background-color': '#000', 'color': '#fff' });
}, function(eOut) { // this second function is what happens
// when user hover away from the link
$(this).css({ 'background-color': '', 'color': '' });
});
});
​See WORKING Fiddle
ALSO, YOU DONT NEED JQUERY FOR THIS, USE CSS
In CSS:
a:hover {
background-color: #000;
color: #fff;
}​
See it in CSS ONLY HERE

Jquery Tooltip plugin, don't repeat div append?

Ok, I can't see to get this.
I'm making a tooltip plugin that can be applied to multiple items.
I have multiple anchors on a page when mousedover they act as tooltips. I use the variable c_ttip to act as an identifier for the div because I don't want to set an ID on it.
I want to keep from appending the tooltip and applying the class and css over and over if the same anchor is remoused over before the tooltip mouseout activates the timeout that removes it.
script dev page, http://kalluna.com/_dev-js.do
var c_ttip = $('<div>');
return this.each(function() {
$(this).mouseover(function() {
c_ttip.appendTo(document.body).hide();
c_ttip.html('inside my tooltip').addClass('c_ttip_box').css({'top' : obj.position().top + 20, 'left' : obj.position().left}).show();
}).mouseout(function() {
timer = setTimeout(function() {
c_ttip.fadeOut(200, function() { c_ttip.remove();});
}, 2000);
});
});
You can store the object that triggered the tooltip and verify that the object is different before adding the div. Something like:
var c_ttip = $('<div>');
var currobject;
...
$(this).mouseover(function() {
if(this == currobject) return;
currobject = this;
...
You need some form of mutex/flag/semaphore to indicate that you are currently in a timeout/fade situation and that the mouseover() event should not fire.
The timer variable you created for the timeout ID could be used for this purpose. Create it above as a variable (initially false), like you have for c_ttip. Then set it to false in the fadeOut() callback. The mouseover() routine should check to see if timer != false when it starts, and exit straight away if it is.
Alternatively, you can add a class to the tooltip when the timer is active, and remove it when the fade has completed.

Categories