I have a script that I am developing that creates a sliding button type effect. Five div's are situated next to eachother each with a link. When one of those DIVS are clicked on the associated content is expanded and the rest of the Div's are closed.
The problem is, if a user clicks the Div twice while it loads or clicks another Div in rapid succession, cracks start to show.
I am wondering if it would be possible to only allow the query to be executed once and wait until completion rather than queuing it.
Here is my current code, if it is crap feel free to comment on how I could better it... I am not the best at Javascript/jQuery :P
function mnuClick(x){
//Reset all elements
if($('#'+x).width()!=369){
$('.menu .menu_Graphic').fadeOut(300);
$('.menu_left .menu_Graphic').fadeOut(300);
$('.menu_right .menu_Graphic').fadeOut(300);
$('.menu').animate({width: "76px"},500);
$('.menu_left').animate({width: "76px"},500);
$('.menu_right').animate({width: "76px"},500);
}
var ElementId = '#' + x;
$(ElementId).animate({
width: 369 + "px"
},500, function(){
$(ElementId + ' .menu_Graphic').fadeIn(300);
});
}
Thanks in advance,
Chris.
You need a "isRunning" flag. Check for it before you start. Set it when you start the sequence, clear it when it ends.
(function() {
var mutex = false;
function mnuClick(x){
if (!mutex) {
mutex = !mutex;
/* all code here ... */
mutex = !mutex; /* this statement should go into animation callback */
}
}
})();
mantain a state through a variable so you cannot click more than once until code has fully executed
you can unplug the onClick event handler (mnuClick) when the event starts, to effectively disable invoking the mnuClick twice, but be sure to restore it when the event ends.
Quick answer: use .addClass and .removeClass and test for the existence of the class at execution time. Test if it's set and return, or add it, execute the code, then remove it.
you can create an invisible maskin and maskout ( like the background in lightbox etc ) or disable clicks until the animation finishes.
Related
I am a genuine javascript novice and looking some pointers in my learning - not homework nor is it anything commercial.
I have a function here which shows an element which is hidden due to the first 2 lines of the function. I start by clicking the heading and the 2 hidden divs appear, which is exactly what I wanted to happen. However, now when I use this second function, it won't return to it's windown onload state. Why is this? Is there a better way to achieve this?
1st Function
$(window).ready(function(){
$('.miniC').css("display", "none");
$('.miniI').css("display", "none");
$(".heading").click(function(){
$('.miniC').slideDown();
$('.miniI').slideDown();
$('.miniC').show();
$('.miniI').show();
});
});
2nd Function (Reverse)
$(window).ready(function(){
$(".hideOut").click(function(){
$('.miniC').slideUp();
$('.miniI').slideUp();
$('.miniC').hide();
$('.miniI').hide();
});
});
Thanks in advance and any reference to good reading material is appreciated.
* Corrected Missing closing quote - this was a mistake of me typing it into Stack Overflow - Sorry! *
It seems like you want to toggle the visibility of an element, and since you're already sliding it, why not just use slideToggle:
$(".miniC").css("display", "none");
$(".miniI").css("display", "none");
$(".heading").click(function () {
$(".miniC").slideToggle();
$(".miniI").slideToggle();
});
Example
You shouldn't need to call .hide() and .show() - they will be dealt with as part of the slide functions. However, you're calling them immediately after the slide, but that takes a while to complete (400ms by default) meaning that .hide() fires before .slideUp() completes.
Outside the question scope, but still applicable.
$('.miniC').css("display", "none");
$('.miniI').css("display", "none");
This part of the page functionality should probably in CSS, which will result in the browser rendering the initial paint of the page correctly. In your case the browser paints the "miniC" and "miniI" elements, then your jQuery code updates the CSS display property to "none" for both individually. Triggering two additional repaints of the page. So, basically with the jQuery code you are drawing the page three times for an effect that could achieved with a single paint.
Then like Charlie said add a listener for the click.
$(".heading").click(function () {
$(".miniC").slideToggle();
$(".miniI").slideToggle();
});
Because slideUp() and hide() are written inside the click event. So, it wont fire on window ready, but only onclick of $(".hideOut").
There is a typo in your first function.
a single quote is missing in the line:
$('.miniC).show();
i have coded a simple javascipt that when the user clicks sth, to do some stuff. I also want that the cursor to be changed, so i added this
<script>
$(document).ready(function() {
$(".targetClass").click(function () {
$('#loaderImage').show();
//this is the line i add
$('.container').css('cursor','wait');
});
});
</script>
And it works. But if i take the cursor on a link the cursor will change again to "pointer" value. What i have to do so the cursor, after the click remain to wait value (even i put it on any element of the page)? Thx!!
here is the solution to your problem.
create a class with pointer wait and add it to button/link also while clicking on it.
$(document).ready(function() {
$(".targetClass").click(function () {
//$('#loaderImage').show();
//this is the line i add
$('.container').css('cursor','wait');
$(this).addClass('cursor');
});
});
.cursor{
cursor:wait;
}
Just ADD this below CODE EXAMPLE HERE.
(1) If all a links shows busy.
$('.container, a').css('cursor','wait');
(2) If all a links within CONTAINER shows busy.
$('.container, .container a').css('cursor','wait');
(3) If all a links within whole(DOM) page shows busy.
$('*').css('cursor','wait');
EXAMPLE HERE.
Every element within the container will overwrite the cursor wait with it's default behaviour. You would have to set cursor wait to all elements.
$('*').css('cursor','wait');
You can use:
$('*').css('cursor','auto');
to set everything to default again.
Or possibly better:
$('*').css('cursor','');
to reset to the previous cursor state, therefore not overriding other cursor changes.
add the following to the function:
$(document).css('cursor','wait');
I've been experimenting with jquery and have come upon a problem. http://javascript.nicklewers.co.uk/nav/
On the 'Android' tab I've set it so that if you click once, the sub menu will appear, however when doubleclicking, the main content will appear.
Now the problem is: a double click involves two single clicks which involves the sub menu opening and closing very quickly and this looks bad. How do I prevent this?
try this (using a timer to know if single click or double):
alreadyclicked=false;
$('#android').bind('click',function(){
var el=$(this);
if (alreadyclicked)
{
alreadyclicked=false; // reset
clearTimeout(alreadyclickedTimeout); // prevent this from happening
// do what needs to happen on double click.
}
else
{
alreadyclicked=true;
alreadyclickedTimeout=setTimeout(function(){
alreadyclicked=false; // reset when it happens
// do what needs to happen on single click.
// use el instead of $(this) because $(this) is
// no longer the element
},300); // <-- dblclick tolerance here
}
return false;
});
Try a delay before showing/hiding the submenu. With JS this can be done using the setTimeout() function.
$('#android').dblclick(function(){
$('.content, #subnav').toggle();
});
why do you toggle both the content and the submenu? Removing it is not going to solve the problem, but I think it should not be there.
my problem is following:
I got a trigger(a) and a popup(div). The div doesn't lie nested inside the anchor.
When I hover over a, I want the div to show up.
When I go from a to the div, I want it to stay visible.
When I leave the div, I want it to close.
When I hover over a and leave without entering the div, I want the div to close.
I got most of that figured out, but now I'm struggeling with requierement no. 2.
When checking for mouseleave on a, I check if there is a mouseenter on the div. If it is, I want to abort the mouseleave. If not, I want to close the div.
What am I doing wrong? Is this even the right way to do this?
Here's the markup:
<a href="#" class="popup_toggle" style='display:block;width:50px;height:50px;border:1px solid red;position:relative;'>Toggle</a>
<div class="popup_div" style='position:absolute;top:50px;left:0px;border:1px solid blue;display:none;'>Popup</div>
Here's the jQuery:
$('.popup_toggle').mouseenter(function() {
var element = $(this).next('.popup_div');
$.data(this, 'timer', setTimeout(function() {
element.show(100);
}, 500));
});
$('.popup_toggle').mouseleave(function() {
clearTimeout($.data(this, 'timer'));
if($('.popup_div').mouseenter==true)
{
return false;
}
else
{
$('.popup_div').hide(100)
};
});
What you're trying to do is fairly simple. When entering the trigger, identify the panel (layer, popup, whatever), save reference to each other using .data() and have the event handlers check if the related targets are either the trigger (from the panel view) or the panel (from the trigger view). I threw something together. Have a look at the console log to see how this works… http://jsfiddle.net/rodneyrehm/X5uRD/
That will most likely not work...no. I would suggest that you add a mouseenter and mouseleave callback to you <div> element as well and have them set a global variable that tells your other callbacks how to handle their events, i.e. "if global variable is true, don't hide the popup on mouseleave, otherwise hide popup" or something like this.
The other approach would be to check whether the mouse is inside the popup when the mouseleave callback tries to hide the popup. That might be much more work than it is worth though.
I believe the problem with your implementation is that the mouseenter on the div will fire shortly after the mouseleave from the a.
This would give you something like:
$('.popup_toggle').mouseenter(function() {
// Clear any pending "hide" timer
// Set a show timer
});
$('.popup_toggle').mouseleave(function() {
// Clear any pending "show" timer
// Set a hide timer
});
$('.popup_div').mouseenter(function() {
// Clear any pending "hide" timer
});
Note that you'll have to make sure that you access the same timer from both the .popup_toggle event and the .popup_div event. You may want to consider using Ben Alman's doTimeout plugin to help with this. It (usually) results in much clearer code than manually working with setTimeout/clearTimeout.
I have the following jQuery code
$("#dropdown").hover(function() {
$(this).stop(true,true).fadeTo('fast',1);
$("#options").stop(true,true).slideDown();
}, function() {
$(this).delay(1000).stop(true,true).fadeTo('fast',0.1);
$("#options").delay(1000).stop(true,true).slideUp();
}
);
What I expect to happen is when the mouse leaves #dropdown it will wait 1 second before continuing. This is not happening.
What I am trying to achieve, in case there is a better way, is to leave the drop down menu visible for a second or two after moving your mouse and I would also like to prevent the events from happening again to prevent artifacts and "funnies" if you were to move the mouse over and out from the div very quickly
The problem is .stop(). If you take that out it works:
http://jsfiddle.net/LZ8yt/
Your calls to stop aren't placed on the animation queue - they run immediately. I'm not sure whether you really need them in the "hover out" routine.
edit removed dumbness
You can always go lo-tech with setTimeout.
var dropDownElement = $(this);
setTimeout(function()
{
dropDownElement.fadeTo('fast', 0.1);
// Other Code
}, 1000);