I have a bootstrap popover that becomes active on focus of an input. The popover contains a button in it to perform an ajax request.
I have a blur function that closes the popover if the user clicks away from the input:
$(document).on('blur','.open-popover',function(){
$(".popover").attr("style","");
//and do other things too
});
I am trying to prevent the blur function above from running if the user presses the button in the popover:
$(document).on('click','button',function(){
//prevent the blur actions and
//do ajax stuff
});
Have you looked at stopImmediatePropagation? If using jQuery, then event handlers are fired in the order that they are bound. Just bind the click before the blur, and run stopImmediatePropagation within the click event.
// bind click event first
$(document).on('click','button',function(event){
// keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree.
event.stopImmediatePropagation();
});
// then attach blur
$(document).on('blur','.open-popover',function(){
$(".popover").attr("style","");
//and do other things too
});
Related
I have an event listener on page 1
window.addEventListener("keydown")
It's causing me issues where another event listener "keydown" in a dialog on that page 1 is conflicting with the window event listener.
There are two event listeners:
dialog event listener
Page event listener
When I add text to the dialog, the page picks up that keydown. I don't want that. I can't add stopPropagation to the page then the dialog won't get the backspace.
What should I do? Can I replace the window. part to something more specific?
In your event handler for the text input, call event.stopPropagation() to prevent the event from being propagated further to other listeners.
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
If I have the following event handler bound to my form:
form.addEventListener('submit', function(evt) {
evt.preventDefault();
console.log('submitted');
this.submit();
});
When the form is submitted by the client, the event handler is executed and the form is submitted without the event handler being executed again.
However, the same logic doesn't apply when attaching click handlers to anchor elements:
a.addEventListener('click', function(evt) {
evt.preventDefault();
console.log('clicked');
this.click();
});
The event handler is executed twice and the link is never followed.
I have two questions:
Why does it appear to work differently for submit vs click?
Why does the anchor's click handler only get executed twice and not indefinitely, if the event handler is being executed each time it's called?
Form submission and element click are different actions, they don't have to behave in the same way.
When using the submit method of the form, the standard says:
Submits the form, bypassing interactive constraint validation and without firing a submit event.
This can be seen also in the submission algorithm. Item 6 checks, whether the action comes from the submit method of the form, and skips the validation and event firing if the "submit()" flag is set.
element.click sets "click in progress flag", which is checked internally before creating a syntehtic click event which calls the hander function. This prevents a click on an element to lead to infinite recursive click event handler calls.
I've got some nested elements, each with an onclick event. In most cases, I want both events to fire when the user clicks the child (both parent and child events are triggered - default behavior). However, there is at least one case where I want to trigger the child's onclick event (from javascript, not a user's click), but not the parent's. How can I prevent this from triggering the parent event?
What I was is:
User clicks A: A's onclick fires.
User clicks B: B's onclick fires, A's onclick also fires
Manually trigger B's click: B fires, A does not (this one is the problem)
Use triggerHandler on the child; this will not let the event propagate through the DOM:
Events created with .triggerHandler() do not bubble up the DOM
hierarchy; if they are not handled by the target element directly,
they do nothing.
Method 1:
You can use stopPropagation() method to prevent event bubbling.
$('.element').on('click', function(e){
e.stopPropagation();
});
Check out thisDEMO
Method 2:
You can use return false to prevent event bubbling and this will also prevent the default action.
$('.element').on('click', function(e){
//--do your stuff----
return false;
});
I have where I use an onfocus event handler to do several things. It works great after initial page load. However, after I click on a link that opens a modal popup the onfocus event stops working. Focus still works fine... but the onfocus event is never fired again until the page is reloaded. How can focus happen without the onfocus event firing?
jQuery(":input").on("focus", function(e)
{
console.log("Debug 1");
});
Before the modal popup this call fires the event handler above...
pTR.find("td:eq(13)").children(":first").focus();
After closing the popup that same call does give that element focus, but the event handler isnt fired.
How is this possible?
I didn't understand very well the question, but I think putting
e.preventDefault();
or
e.stopPropagation();
at the beginning of your onfocus event might help...
Try both depending of your situation.
I have an <input> element that can either have the focus set via code, or as the result of a mouse click.
If the user clicks on the input, then the click event handler will fire - all well and good. If the element receives the focus via some other way (e.g. via code) then I want to manually trigger the click event so that the handler will also fire.
I could do this:
$elem = $('input');
$elem
.on('focus', function() { $(this).trigger('click') })
.on('click', function() { alert('Clicked!') });
However, this will result in click handler being fired twice; once for the click event and once for the focus event.
Is there any way to selectively trigger the click handler only if the focus was not received as the result of a click event?
UPDATE
This is a very simplified version of my problem, so I can't do things like bind both handlers to the focus event etc. I'm trying to merge two third-party pieces of code.
The .trigger() function adds a property isTrigger in the event object to identify that the event was triggered by its usage. Although, it is not documented the property is still present in jQuery 1.8.3 but it seems to only be used internally.
Anyways, you can make use of the extraParameters parameter to add a custom property to the event object. For instance,
$(this).trigger('click', {
isTrigger: true
});
It will keep the compatibility with isTrigger even if it is gone in a future release.
After doing some more research it appears that there is no way of guaranteeing which event will fire first: click or focus. (There doesn't seem to be a standard that dictates the order of events.)
This means that when the focus event fires there's no way to determine if a click event will or will not be triggered by the browser shortly afterwards.
I managed to solve the issue by using setTimeout() to run a test about 100ms after the focus event fired to check if the click event had fired. The third-party code that I was using (bound to the click event) added an extra class to the <input>, so I was able to check for that.
You can tap into the mousedown event which fires before the focus event. When you click a focusable object the order of events is as follows... mousedown, focus, mouseup, click.
You could set a flag in the mousedown event and then check for it in the focus event to see if the focus came from a mouse click. Obviously make sure to clear the flag in the focus event handler. Every application is different, but tapping into the mousedown event allows you to figure out a solution.
Here is a JSFiddle demonstrating the order of events... http://jsfiddle.net/ek7v7/
$elem = $('input');
$elem
.on('focus', function() { alert("Focused!") })
Focus can be fired by focusing the input by using tab, clicking it, or by using .focus()
Is there a reason for on('click', ...)?