I have two overlapping div elements in my web app.
On the underlying div an event is registered on double click.
On the div that lies above the other div a event is registered on click that hides the div.
The problem is that if I double click on the above div element it is hidden after the first click BUT the second click causes the double click event on the underlying div to fire - how can I prevent that?
Mixing "click" and "double-click" is going to be problematic at best. However, in this case things might get better if you just ensure that your handler for the "click" event (the event that hides the element) returns false to the browser.
How to do that depends on how your handler is registered. If it's like this:
<div onclick='hideMe();'>
then you'd change that to
<div onclick='hideMe(); return false'>
If you're using some framework or some other means of attaching the handler, then just having the handler function return false should do it.
Related
I have a webapp problem.
double-touching specific button in an iOS device (iPad)
triggers a click event which triggers some iOS default behaviour, which scales the page.
I want to prevent this from happening.
So I added an eventListener to the click event, at a top-element elementId1.
elementId1
elementId2
elementId3
elementId4
I choose the top-element elementId1 because this side effect happens on various nested elements, and I want to have a single catch-all click eventListener, at the top of the html element hierarchy, that will prevent this from happening in multiple places.
The eventListener triggers a function onClickTopElement that calls event.preventDefault()
The eventListener is set with attributes:
capture: false - this cause the event to trigger in the bubbling phase, i.e. on the way up and not on the way down
This means that:
the event first fires on the element which may have a function to trigger on click and do what it was designed to do.
as the event bubbles up, it gets to the elementId1 element, which fires the function onClickTopElement which calls event.preventDefault(), which disables the iOS default behaviour of scaling up the page.
// add catch-all 'click' eventListener, at the top of the html elements so that on iOS the side-effect of scaling-the-page when double-touching never happens
let element1 = document.getElementById('elementId1');
element1.addEventListener( 'click', onClickTopElement, {capture: false, passive: false} );
function onClickTopElement(event) {
// prevent from trickling the event, when touching, which causes, in iOS to zoom the entire page
event.preventDefault();
}
The end result is that double-touching the buttons does not cause the page to scale up. Good!
This is good but creates another side-effect.
There is a button (elementId4) with href tag that when clicked, takes to another page.
This is done by the browser's default behaviour.
But since elementId4 is nested within elementId1, the default onClick behaviour is now prevented.
One solution is to add specific onClick eventListener to elementId4 and do what the default behaviour does, i.e. navigate to the href.
What would be the command to navigate to the href within an onClick eventListener function.
Thanks
I have a link within a link, both with an onClick event.
The outer link works as desired. However, the inner link triggers both onClick events. I would like it so that the outer event is not triggered when the inner link is clicked.
<div onClick="console.log(1)">
Inner
</div>
JSFiddle
Javascript events will propagate up through the tree.
So when you click on the inner anchor it will also emit any click events for elements higher up, so the div element.
To stop this the inner click handler has to prevent the event from propagating with e.stopPropagation();.
However this gets a little messy when you don't register handlers with .addEventListener() in JavaScript.
If you add events this way you can do it like this (first give your anchor an id, say inner) which is nice and easy:
document.getElementById('inner').addEventListener('click', function (e) {
e.stopPropagation();
console.log(2);
});
You can however pass the event into your click handler if you do wish to use the attribute, so:
Inner
//JS
function innerHandler(e) {
e.stopPropagation();
console.log(2);
}
Generally speaking (this is my opinion) i would avoid the latter. Events registered like this are difficult to remove and modify. You can't also easily register multiple handlers to the same element for the same event.
stopPropagation docs
I'm trying to append some html to a page when a div is clicked on, then when any other part of the page is clicked on (except the newly attached div and the div that was clicked that attached it) remove the attached div. For some reason my :not() selector isn't working as I'd expect it to.
$("*").on("click", "body:not(._tlh_dropdown, ._tlh_dropdown_content)", function () {
// ... remove previously attached div
});
http://jsfiddle.net/qUHAB/5/
How can I remove this div when anything is clicked on except for the two classes _tlh_dropdown and _tlh_dropdown_content?
Well:
$("*").on("click", "body:not(._tlh_dropdown, ._tlh_dropdown_content)", function () {
is almost certainly not what you want. That adds an event handler for every element on the page, asking it to check for events from the <body> to have bubbled up. It kind-of makes no sense.
And
$("body").on("click", "*:not(._tlh_dropdown, ._tlh_dropdown_content)", function () {
will have problems with your test page because there's nothing else in the <body> but your header.
Change it to the second thing above (like it was in your original question), and then add a <div> with some text in it after the content that's there, and then click in that. Alternatively, change it to:
$(document).on("click", "*:not(._tlh_dropdown, ._tlh_dropdown_content)", function () {
and that'll catch events bubbling up from the <body>.
edit — if you go with $(document), it'd also be a good idea (especially if you want it to work :-) to add an "event" parameter to the handler functions and, in each, to call
event.stopPropagation();
In the first event handler (the one that opens up the extra content), that will prevent the second handler from running when the "click" on the header bubbles up to the body. For the second handler, stopping propagation isn't as important but it'll avoid redundant attempts to close the added content.
edit some more — see the comments below; the "close" handler has some subtleties that make implementing it with the "on" selector approach kind-of problematic.
It appears that the Blur event stops the click event handler from working? I have a combo box where the options only appear when the text field has focus. Choosing an option link should cause an event to occur.
I have a fiddle example here: http://jsfiddle.net/uXq5p/6/
To reproduce:
Select the text box
Links appear
Click a link
The blur even occurs and the links disappear
Nothing else happens.
Expected behavior:
On step 5, after blur occurs, the click even should also then fire. How do I make that happen?
UPDATE:
After playing with this for a while, it seems that someone has gone to great lengths to prevent an already-occurred click event from being handled if a blur event makes the clicked element Un-clickable.
For example:
$('#ShippingGroupListWrapper').css('left','-20px');
works just fine, but
$('#ShippingGroupListWrapper').css('left','-2000px');
prevents the click event.
This appears to be a bug in Firefox, since making an element un-clickable should prevent future clicks, but not cancel ones that have already occurred when it could be clicked.
Other things that prevent the click event from processing:
$('#ShippingGroupListWrapper').css('z-index','-20');
$('#ShippingGroupListWrapper').css('display','none');
$('#ShippingGroupListWrapper').css('visibility','hidden');
$('#ShippingGroupListWrapper').css('opacity','.5');
I've found a few other questions on this site that are having similar problems. There seem to be two solutions floating around:
Use a delay. This is bad because it creates a race condition between the hiding and the click event handler. Its also sloppy.
Use the mousedown event. But this isn't a great solution either since click is the correct event for a link. The behavior of mousedown is counter-intuitive from a UX perspective, particularly since you can't cancel the click by moving the mouse off the element before releasing the button.
I can think of a few more.
3.Use mouseover and mouseout on the link to enable/disable the blur event for the field. This doesn't work with keyboard tabing since the mouse is not involved.
4.The best solution would be something like:
$('#ShippingGroup').blur(function()
{
if($(document.activeElement) == $('.ShippingGroupLinkList'))
return; // The element that now has focus is a link, do nothing
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
Unfortunately, $(document.activeElement) seems to always return the body element, not the one that was clicked. But maybe if there was a reliable way to know either 1. which element now has focus or two, which element caused the blur (not which element is blurring) from within the blur handler. Also, is there any other event (besides mousedown) that fires before blur?
click event triggers after the blur so the link gets hidden. Instead of click use mousedown it will work.
$('.ShippingGroupLinkList').live("mousedown", function(e) {
alert('You wont see me if your cursor was in the text box');
});
Other alternative is to have some delay before you hide the links on blur event. Its upto you which approach to go for.
Demo
You could try the mousedown event instead of click.
$('.ShippingGroupLinkList').live("mousedown", function(e) {
alert('You wont see me if your cursor was in the text box');
});
This is clearly not the best solution as a mousedown event is not achieved the same way for the user than a click event. Unfortunately, the blur event will cancel out mouseup events as well.
Performing an action that should happen on a click on a mousedown is bad UX. Instead, what's a click effectively made up of? A mousedown and a mouseup.
Therefore, stop the propagation of the mousedown event in the mousedown handler, and perform the action in the mouseup handler.
An example in ReactJS:
<a onMouseDown={e => e.preventDefault()}
onMouseUp={() => alert("CLICK")}>
Click me!
</a>
4.The best solution would be something like:
$('#ShippingGroup').blur(function()
{
if($(document.activeElement) == $('.ShippingGroupLinkList'))
return; // The element that now has focus is a link, do nothing
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
Unfortunately, $(document.activeElement) seems to always return the
body element, not the one that was clicked. But maybe if there was a
reliable way to know either 1. which element now has focus or two,
which element caused the blur (not which element is blurring) from
within the blur handler.
What you may be looking for is e.relatedTarget. So when clicking the link, e.relatedTarget should get populated with the link element, so in your blur handler, you can choose not to hide the container if the element clicked is within the container (or compare it directly with the link):
$('#ShippingGroup').blur(function(e)
{
if(!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget)) {
// Alt: (!e.relatedTarget || $(e.relatedTarget) == $('.ShippingGroupLinkList'))
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
}
(relatedTarget may not be supported in older browsers for blur events, but it appears to work in latest Chrome, Firefox, and Safari)
If this.menuTarget.classList.add("hidden") is the blur behavior that hides the clickable menu, then I succeeded by waiting 100ms before invoking it.
setTimeout(() => {
this.menuTarget.classList.add()
}, 100)
This allowed the click event to be processed upon the menuTarget DOM before it was hidden.
I know this is a later reply, but I had this same issue, and a lot of these solutions didn't really work in my scenario. mousedown is not functional with forms, it can cause the enter key functionality to change on the submit button. Instead, you can set a variable _mouseclick true in the mousedown, check it in the blur, and preventDefault() if it's true. Then, in the mouseup set the variable false. I did not see issues with this, unless someone can think of any.
I have faced a similar issue while using jQuery blur, click handlers where I had an input name field and a Save button. Used blur event to populate name into a title placeholder. But when we click save immediately after typing the name, only the blur event gets fired and the save btn click event is disregarded.
The hack I used was to tap into the event object we get from blur event and check for event.relatedTarget.
PFB the code that worked for me:
$("#inputName").blur(function (event) {
title = event.target.value;
//since blur stops an immediate click event from firing - Firing click event here
if (event.relatedTarget ? event.relatedTarget.id == "btnSave" : false) {
saveBtn();
}
});
$("#btnSave").click(SaveBtn)
As already discussed in this thread - this is due to blur event blocking click event when fired simultaneously. So I have a click event registered for Save Btn calling a function which is also called when blur event's related Target is the Save button to compensate for the click event not firing.
Note: Didnt notice this issue while using native onclick and onblur handlers - tested in html.
Assume I get a table element with ID="emTab", how do I call JS to click it?
Thanks.
document.getElementById("emTab").onclick = function() {
// your code goes here
};
See element.onclick
To trigger click event
document.getElementById("emTab").click();
See element.click
The click method is intended to be
used with INPUT elements of type
button, checkbox, radio, reset or
submit. Gecko does not implement the
click method on other elements that
might be expected to respond to
mouse–clicks such as links (A
elements), nor will it necessarily
fire the click event of other
elements.
Non–Gecko DOMs may behave differently.
When a click is used with elements
that support it (e.g. one of the INPUT
types listed above), it also fires the
element's click event which will
bubble up to elements higher up the
document tree (or event chain) and
fire their click events too. However,
bubbling of a click event will not
cause an A element to initiate
navigation as if a real mouse-click
had been received.
Cross browser way
If you can use jQuery then it would be
$("#emTab").trigger("click");
Firing events cross-browser - http://jehiah.cz/archive/firing-javascript-events-properly
its simple using JQuery
$('#emTab').click(functionToCall);
while in JS
document.getElementById('emTab').onclick = function() {};
for details on DOM events:
http://www.howtocreate.co.uk/tutorials/javascript/domevents