Function stops after click() - javascript

I'm trying to simulate two click to open a menu. The first one opens the menu and the second the submenu but after the first click() the function stops.
This is my JS code:
function open_menu(id_menu, id_sub_menu) {
$('.sous-domaines a#lien-domaine-'+id_menu).click();
$('a#lien-menu-'+id_sub_menu).click();
}
I call my function in HTML with this code:
<span onClick="open_menu('0', '116')">Open sub-menu</span>

You're doing it too fast maybe.
Wrap the second one in a window.setTimeout()

can you do something like this ? set a bool after first click
var IsClick = false;
function open_menu(id_menu, id_sub_menu) {
$('.sous-domaines a#lien-domaine-'+id_menu).click();
if (IsClick){ fnSecondClick();}
}
function fnSecondClick() {
//open submenu
}
or something like this - on click check if menu is visible:
function open_menu(id_menu, id_sub_menu) {
$('.sous-domaines a#lien-domaine-'+id_menu).click();
if ($(element).is(":visible")){ fnSecondClick();}
}

Well you can give this a try, it is pretty much waht you had, other than the fact i don't have menu open somewhere
http://jsfiddle.net/tRg3e/2/
I think the .click() only works if you have a handler attached, it does not trigger the native click on the element.. I tried it without handler and the link does not go

You should stray away from 'onClick' declared in elements like that, it's bad practice if I do recall. Nonetheless, it still works.
If you could provide some HTML code it would help clarify the idea but you could set a trigger event for example:
http://jsfiddle.net/wrN2u/3/
EDIT: With a toggle - http://jsfiddle.net/wrN2u/18/

Related

Stop propagation for a specific handler

Let's say I have custom dropdown(). When the button is clicked I want to bring up the menu, and when the user clicks outside of the menu I want it to close. So I do something like this:
$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(htmlMouseDown,myDropDown);
function dropDownMouseDown(event) {
event.target.open();
event.stopPropagation();//I need this line or else htmlMouseDown will be called immediately causing the dropDown-menu to close right before its opened
}
function htmlMouseDown() {
this.close();
}
Well, this works. But what if I add two of these? If I click to open the first, then the same on the second then both will be open because dropDownMouseDown stops the propagation so that htmlMouseDown never gets called for the first.
How do I get around this?
If I only had these two then adding some logic for that would of course be easy, but if the quantity is dynamic? Also I might not want to call event.stopPropagation() because it will do strange stuff to other libraries I'm using which listen for that event too?
I also tried putting this line:
$("html").mousedown(htmlMouseDown,myDropDown)
inside the dropDownMouseDown-handler but it will be called immediately anyway once the bubbling reaches the html-element.
Assuming you have a selector for your dropdows, (let's say ".dropdown"), I would try to use '.not()'
$('.dropdown').mousedown(dropDownMouseDown);
$("html").on('mousedown', htmlMouseDown);
function dropDownMouseDown(event) {
event.target.open();
}
function htmlMouseDown(event) {
$('.dropdown').not($(event.target)).close();
}
Here is a fiddle in the same idea with css classes :
http://jsfiddle.net/eFEL6/4/
What about using a variable that contains the last openened one ? There are probably many other ways of doing this, but here is a way I could think of:
var lastOpened = null; // initially nothing is open (unless something is)
Then:
function dropDownMouseDown(event) {
if (lastOpened != null) { // if one is still open
lastOpened.close(); // close it
lastOpened = null; // nothing is open anymore
}
event.target.open();
lastOpened = event.target; // now this one is open
event.stopPropagation();
}
function htmlMouseDown() {
this.close();
lastOpened = null; // nothing is open
}
That should work in a way that the last opened one always close itself before opening a new one.
Thanks for the answers. They're really appreciated. I did figure out a way of doing it that I'm satisfied with. Here's how:
$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler
function dropDownMouseDown(event) {
event.target.open();
}
function htmlMouseDown(event) {
if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can...
event.data.close();///close the dropdown this handler was added for
}
Can't believe I didn't think of that. In my case though the element that opens/closes has child-elements so event.target could be one of the child elements instead of the element that the handler was attached to. So I changed my html-element-handler to this:
function htmlMouseDown(event) {
var element=event.target;
while (element) {
if (element==event.data)
return;
element=element.parentElement;
}
event.data.hide();
}

Can anyone think of a better way of stopping a user from clicking on anything?

Currenlty when a page is posting back or something else is going on I display a big grey div over the top of the whole page so that the user can't click the same button multiple times. This works fine 99% of the time, the other 1% is on certain mobile devices where the user can scroll/zoom away from the div.
Instead of trying to perfect the CSS so that it works correctly (this will be an on going battle with new devices) I've decided to just stop the user from being able to click anything. Something like $('a').click(function(e){e.preventDefault();}); would stop people from clicking anchor tags and navigating to the link but it wouldn't stop an onclick event in the link from firing.
I want to try to avoid changing the page too radically (like removing every onclick attribute) since the page will eventually have to be changed back to its original state. What I would like to do is intercept clicks before the onclick event is executed but I don't think that this is possible. What I do instead is hide the clicked element on mouse down and show it on mouseup of the document, this stops the click event firing but doesn't look very nice. Can anyone think of a better solution? If not then will this work on every device/browser?
var catchClickHandler = function(){
var $this = $(this);
$this.attr('data-orig-display', $this.css('display'));
$this.css({display:'none'});
};
var resetClickedElems = function(){
$('[data-orig-display]').each(function(){
$(this).css({display:$(this).attr('data-orig-display')}).removeAttr('data-orig-display');
});
};
$('#btn').click(function(){
$('a,input').on('mousedown',catchClickHandler);
$(document).on('mouseup', resetClickedElems);
setTimeout(function(){
$('a,input').off('mousedown',catchClickHandler);
$(document).off('mouseup', resetClickedElems);
}, 5000);
});
JSFiddle: http://jsfiddle.net/d4wzK/2/
You could use the jQuery BlockUI Plugin
http://www.malsup.com/jquery/block/
You can do something like this to prevent all actions of the anchor tags:
jQuery('#btn').click(function(){
jQuery('a').each(function() {
jQuery(this).attr('stopClick', jQuery(this).attr('onclick'))
.removeAttr('onclick')
.click(function(e) {
e.preventDefault();
});
});
});
That renames the onclick to stopclick if you need to revert later and also stops the default behavior of following the href.
document.addListener('click',function(e){e.preventDefault()})
Modified-
Its your duty to remove the click event from the document after you are done accomplishing with your task.
Eg -
function prevent(e){
e.preventDefault()
}
//add
document.addListener('click',prevent)
//remove
document.removeListener('click',prevent)

How defined in jQuery was it a regular click on the same element or double-click?

How can I define in jQuery was it a regular click on the same element or double-click?
For example we have element like this:
<div id="here">Click me once or twice</div>
And we need to perform different actions after regular click and double-click.
I tried something like this:
$("#here").dblclick(function(){
alert('Double click');
});
$("#here").click(function(){
alert('Click');
});
But, of course, it doesn't work, everytime works only 'click'.
Then, some people showed me this:
var clickCounter = new Array();
$('#here').click(function () {
clickCounter.push('true');
setTimeout('clickCounter.pop()', 50);
if (clickCounter.length > 2) {
//double click
clickCounter = new Array(); //drop array
} else {
//click
clickCounter = new Array(); //drop array !bug ovethere
}
});
Here we tried to set the interval between clicks, and then keep track of two consecutive events, but this have one problem.. it doesn't work too.
So, someone knows how to do this? or can someone share a link to the material, where I can read about it?
From QuirksMode:
Dblclick
The dblclick event is rarely used. Even when you use it, you should be
sure never to register both an onclick and an ondblclick event handler
on the same HTML element. Finding out what the user has actually done
is nearly impossible if you register both.
After all, when the user double–clicks on an element one click event
takes place before the dblclick. Besides, in Netscape the second click
event is also separately handled before the dblclick. Finally, alerts
are dangerous here, too.
So keep your clicks and dblclicks well separated to avoid
complications.
(emphasis mine)
What you are doing in your question, is exactly how it should be done.
$(".test").click(function() {
$("body").append("you clicked me<br />");
});
$(".test").dblclick(function() {
$("body").append("you doubleclicked me<br />");
});
It works and here is an demo for that.
Since, you want to detect separate single double click. There is a git project for this.
$("button").single_double_click(function () {
alert("Try double-clicking me!")
}, function () {
alert("Double click detected, I'm hiding")
$(this).hide()
})
It adds up events to detect single double clicks.
Hope it helps you now.

Closing form on "blur" -- Is there a better way?

So, i'm trying to close a form on blur, e.g. Facebook comments. The issue is, I had a:
$(window).click(function(){ $('.comment_form').hide(); });
$('.comment_form').click(function(){ return false; });
Which worked fine, however, by adding that return false, it cancels out the submit button when clicked when i actually went to make it live.
I thought this would work logically instead:
$('*:not(.comment_form,.comment_form *)').click(function(eve)
{
$('.comment_form').hide();
});
But, unfortunatly, it doesn't and i assume it's because when i click on, let's say, .comment_form i actually am clicking on body, div, div... etc so it actually hides it multiple times.
My work around was finally
$('*').click(function(eve)
{
if(!$(eve.target).is('.comment_form,.comment_form *'))
{
$('.comment_form').hide();
}
});
However, i'm not so sure i like this and this is why im asking. This is going to fire this click event every single click.
Does anyone have any suggestions?
Your solution is on the right track, but it might be saner to attach the event to document, instead of all elements (*):
$(document).click(function(eve) {
if (!$(eve.target).is('.comment_form, .comment_form *')) {
$('.comment_form').hide();
}
});

Trying to toggle a panel whilst changing the icon to 'view more' and 'view less'

I've just started learning jQuery/javascript, so this might seem like a really basic question, but it's annoying me nevertheless.
I have a panel of 6 <li>s, 3 of which are hidden until clicking on the 'view more' link at which point the panel toggles to reveal the other 3. The icon is changing from 'more' to 'less', but then not changing back to 'more'. Can anyone see the problem in the code?
Any help would be greatly appreciated :)
Thanks,
David
$(document).ready(function() {
$('.allApps').hide();
$('.moreAppsIcon').click(function() {
$('.moreAppsIcon').removeClass("moreAppsIcon").addClass("lessAppsIcon");
$(this).toggleClass("active");
$('.allApps').slideToggle("slow");
return false;
});
$('.lessAppsIcon').click(function() {
$('.appsMore').slideToggle("slow", function () {
$('.appsMore').removeClass("appsMore").addClass("moreAppsIcon");
$(this).toggleClass("active");
return false;
});
});
});
It's easier to use .live() here, like this:
$('.moreAppsIcon').live('click', function() {
//and...
$('.lessAppsIcon').live('click', function() {
Otherwise your functions aren't being bound correctly. For example $('.lessAppsIcon') finds elements with that class at that time and binds a click handler to them...elements getting that class later don't get that click handler, whereas .live() works on the selector of the element at the time of the event, having the result you want.
So basically you're attaching n event handlers, one for each element matching initially...when you do .addClass() the other elements don't get that event handler all the sudden, it's on the DOM elements you initially found, not dynamically added to others when they change class. For the same reason .removeClass() doesn't remove the event handler. However, if you use .live() like above, it'll have the effect of changing event handlers like you're after.
I figured it out. It was pretty much what Nick was saying actually to do with the time of the event. I added an id to the <li> to handle the click event. This is what it looks like:
$(document).ready(function() {
$('.allApps').hide();
$('#moreOrLess').click(function() {
$('.allApps').slideToggle("slow", function() {
$('#moreOrLess').toggleClass("moreAppsIcon").toggleClass("lessAppsIcon");
$(this).toggleClass("active");
});
return false;
});
});
Cheers for the help though Nick :)

Categories