jquery: name timeout of anchor dynamic using its id - javascript

Hej!
I might be a blockhead here, but I can't figure this out;
I'm building a horizontal menu with the basic hover() function in javascript. When you leave an anchor, there's a short timout before the hover effect disappears.
So what I want to do: Name the Timeout after the ID of the anchor, where the mouseleave is triggered in order to stop the right Timeout again on mouseenter.
On Mouseenter i check which anchor is hovered by getting the id, i cancel the timeout for this id and i add the hvr-Class to the hovered anchor:
var t = $(this).attr('id');
clearTimeout(t);
$(this).addClass('hvr');
and on Mouseleave I want to do basically this:
$(this).attr('id') = setTimeout('doSoemthing()',66);
But that causes an error, because the expression isn't allowed on the left side of the =. I thought about something like this:
var ts = $(this).attr('id');
ts = setTimeout('doSoemthing()',66);
but that doesn't work either, because it just overwrites the variable t. Instead I want to kind of 'print' the value of the variable for the Timeout-Name. If i used fixed Timeout-Names, everything works like a charm, but than there's only one (the same) timeout for every link, which doesn't do it.
Is there a way to do this? Or am I off the track?
That's the complete function:
$("nav a").hover(
function(){
// On MouseEnter
var t = $(this).attr('id');
clearTimeout(t);
$(this).addClass('hvr');
},function(){
// On MouseLeave
$(this).attr('id') = setTimeout(function(){doSomethingHere},66);
}
);
Thanks in advance, Best Regards.

From what I understood, you need to keep a reference to the timeout event based on the hovered element, you can use .data() to do that
I think what you are looking for is
$("nav a").hover(function () {
clearTimeout($(this).data('mltimer'));
$(this).addClass('hvr');
}, function () {
var timer = setTimeout('doSoemthing()', 66);
$(this).data('mltimer', timer)
});

Related

How to apply focused state to same element again when clicked?

For my Form input, I would like to re-do the animation of my focused state for an input like:
<input type="text" class="form-control">
You can see it in action here: https://jsfiddle.net/esg1dzy0/
With that said, I can't get it to do so with this:
$(document.activeElement).click(function(){
this.focus();
});
Is this possible? What am I doing wrong?
You need to blur the element first.
Before you do that, you need to make sure this is not the first click on the element.
Also, your original selector will only select the element that is active at the time that your snippet runs.
Finally, use mousedown to avoid flickering.
$('.form-control').mousedown(function(){
if(!$(this).is(':focus')) return;
$(this).blur().focus();
});
I hope this can help you:
$('.form-control').on('click', function(){
var $this = $(this);
var duration = 300;
var enableAgain = function(){
$this.blur().focus();
};
setTimeout(enableAgain, duration);
});
This trigger the the blur() and focus() event again after 300 milliseconds (in the best of the case), which is the same as transition-duration you maybe want a greater value like 350.
BTW I have editt your https://jsfiddle.net/esg1dzy0/ file.

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');
}
});
});
});​

slideToggle issue with stop()

$(document).ready(function() {
$("ul li").click(function() {
$(this).find("p").slideToggle("normal");
return false;
});
});
With this piece of jQuery code I can make elements slide in and out. But the problem is that when someone clicks real fast, the slide out will only go until the max height is reached of the latest reached height.
So, if someone would click real fast the element will only slide out a couple of pixels and slide back up. If they´d than click again to slide it out, it will only slide out to the max height it reached the last time.
Can anybody help me to fix this issue to make this work proper?
PS: The height of the p element is set to auto so it automaticly matches the height of the content inside (maybe this detail will help with your answer).
Instead of using the click function to attach the click event, use one instead:
$("ul li").one("click", doStuff);
function doStuff(){
// do your stuff here
$("ul li").one("click", doStuff); // Re-attach event
}
and then re-attach the event in the function.
Try this:
$(document).ready(function() {
$("ul li").click(function() {
if ( ! $(this).find('p:animated').length)
{
$(this).find("p").slideToggle("normal");
return false;
}
});
});
If you want to actually process the additional clicks (rather than ignore them), then you want to use .stop(true, true) to stop the previous animation and jump it to the conclusion so your next animation can run as you want:
$(document).ready(function() {
$("ul li").click(function() {
$(this).find("p").stop(true, true).slideToggle("normal");
return false;
});
});
Whenever you trigger an animation from a user click, you should know about .stop() and figure out which arguments you want to use with it for a given situation. Without it, the animations can pile up in the queue and run sequentially which is usually not what you want.
Here's the jQuery reference info on .stop() and it's arguments.

jQuery: Can't cache onclick handler?

I've got a step-by-step wizard kind of flow where after each step the information that the user entered for that step collapses down into a brief summary view, and a "Go back" link appears next to it, allowing the user to jump back to that step in the flow if they decide they want to change something.
The problem is, I don't want the "Go Back" links to be clickable while the wizard is animating. To accomplish this I am using a trick that I have used many times before; caching the onclick handler to a different property when I want it to be disabled, and then restoring it when I want it to become clickable again. This is the first time I have tried doing this with jQuery, and for some reason it is not working. My disabling code is:
jQuery.each($("a.goBackLink"), function() {
this._oldOnclick = this.onclick;
this.onclick = function() {alert("disabled!!!");};
$(this).css("color", "lightGray ! important");
});
...and my enabling code is:
jQuery.each($("a.goBackLink"), function() {
this.onclick = this._oldOnclick;
$(this).css("color", "#0000CC ! important");
});
I'm not sure why it's not working (these are good, old-fashioned onclick handlers defined using the onclick attribute on the corresponding link tags). After disabling the links I always get the "disabled!!!" message when clicking them, even after I run the code that should re-enable them. Any ideas?
One other minor issue with this code is that the css() call to change the link color also doesn't appear to be working.
I wouldn't bother swapping around your click handlers. Instead, try adding a conditional check inside of the click handler to see if some target element is currently animating.
if ($('#someElement:animated').length == 0)
{
// nothing is animating, go ahead and do stuff
}
You could probably make this a bit more concise but it should give you an idea... Havent tested it so watch your console for typeos :-)
function initBack(sel){
var s = sel||'a.goBackLink';
jQuery(s).each(function(){
var click = function(e){
// implementation for click
}
$(this).data('handler.click', click);
});
}
function enableBack(sel){
var s = sel||'a.goBackLink';
jQuery(this).each(function(){
var $this = jQuery(this);
if(typeof $this.data('handler.click') == 'function'){
$this.bind('goBack.click', $this.data('handler.click'));
$this.css("color", "lightGray ! important");
}
});
}
function disableBack(sel){
var s = sel||'a.goBackLink';
jQuery(s).each(function(){
var $this = jQuery(this);
$this.unbind('goBack.click');
$this.css("color", "#0000CC ! important");
});
}
jQuery(document).ready(function(){
initBack();
jQuery('#triggerElement').click(function(){
disableBack();
jQuery('#animatedElement').animate({/* ... */ }, function(){
enableBack();
});
});
});

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