I have created a common click function in jquery which fires every time when clicked any where on document. If control has click event then that event fires first and document click fires after that but i want to fire document click event before control click event. please suggest how to fix this.
Two options for you:
You can do that on modern browsers by using the capturing phase of an event rather than the bubbling phase. This diagram from the DOM events specification helps with understanding the various phases of an event:
IE doesn't support event capture until IE9 in standards mode (IE8 and earlier simply do not have it).
jQuery doesn't provide an API for using event capture, so you'd have to use addEventListener instead:
document.querySelector("selector for the control").addEventListener("click", function(e) {
// Control code here
}, true);
document.addEventListener("click", function(e) {
// Document code here
}, true);
The true at the end means you want to use the capturing phase, rather than the bubbling phase.
Don't handle clicks on controls directly, use event delegation, handling clicks on the document and, if the click came through a control, calling your control-specific handling from the document click handler:
$(document).on("click", handleDocumentClick);
function handleDocumentClick(e) {
// On the next line, use whatever selector matches your controls
var input = $(e.target).closest("input")[0];
display("document click received");
if (input) {
handleControlClick.call(input, e);
}
}
function handleControlClick(e) {
display("control click received");
}
Live Example
You can use live(). live() binds the click event to the DOM's document element. As browser events bubble up through the DOM tree, the click event is triggered for any matching elements.
$(document).click(function() {
alert('document');
});
$(document).live('click', 'div', function() {
alert('div');
});
DEMO
Related
first i created navigation click event
$('#inner-navigation li a')
.on('click', function (e) {
e.preventDefault();
AjaxNavUrl.checkURL(this.hash);
});
then it conducts ajax call and response html data
based on navigation key
$(".panel-body").html(data);
first ajax click working nicely..
then whithin that responese html data there is rest of click event and ajax call like
$(document.body).on('click', '.page-demos .page-wrapper', function (e) {
e.preventDefault();
and this
$(document.body).on('click', '.button-next', function (e) {
e.preventDefault();
but it seems like click event or e.preventDeafult() function is not working
I got the answer from jQuery doc here is what I learned,
Event Propagation
Understanding how events propagate is an important factor in being able to leverage Event Delegation. Any time one of our anchor tags is clicked, a click event is fired for that anchor, and then bubbles up the DOM tree, triggering each of its parent click event handlers:
<a>
<li>
<ul #list>
<div #container>
<body>
<html>
document root
This means that anytime you click one of our bound anchor tags, you are effectively clicking the entire document body! This is called event bubbling or event propagation.
Since we know how events bubble, we can create a delegated event:
$("#list").on("click", "a", function(event) {
event.preventDefault();
console.log($(this).text());
});
Notice how we have moved the a part from the selector to the second parameter position of the .on() method. This second, selector parameter tells the handler to listen for the specified event, and when it hears it, check to see if the triggering element for that event matches the second parameter. In this case, the triggering event is our anchor tag, which matches that parameter. Since it matches, our anonymous function will execute. We have now attached a single click event listener to our <ul> that will listen for clicks on its descendant anchors, instead of attaching an unknown number of directly bound events to the existing anchor tags only.
linkUsing the Triggering Element
What if we wanted to open the link in a new window if that link is an external one (as denoted here by beginning with "http")?
// Attach a delegated event handler
$("#list").on("click", "a", function(event) {
var elem = $(this);
if (elem.is("[href^='http']")) {
elem.attr("target", "_blank");
}
});
This simply passes the .is() method a selector to see if the href attribute of the element starts with "http". We have also removed the event.preventDefault(); statement as we want the default action to happen (which is to follow the href).
We can actually simplify our code by allowing the selector parameter of .on() do our logic for us:
// Attach a delegated event handler with a more refined selector
$("#list").on( "click", "a[href^='http']", function(event) {
$(this).attr("target", "_blank");
});
The click binding adds an event handler so that your chosen JavaScript function will be invoked when the associated DOM element is clicked. This is most commonly used with elements like button, input, and a, but actually works with any visible DOM element.
Example
<div>
You've clicked <span data-bind="text: numberOfClicks"></span> times
<button data-bind="click: incrementClickCounter">Click me</button>
</div>
<script type="text/javascript">
var viewModel = {
numberOfClicks : ko.observable(0),
incrementClickCounter : function() {
var previousCount = this.numberOfClicks();
this.numberOfClicks(previousCount + 1);
}
};
</script>
Each time you click the button, this will invoke incrementClickCounter() on the view model, which in turn changes the view model state, which causes the UI to update.
I would like to implement a confirmation logic for links or buttons, where I can annotate the related element with a special data-confirm attribute. If this attribute exists on the element, I would like to attach a click handler which has the power to prevent any other handler including default event, and other jQuery handlers added before or after my confirm handler was added.
Here is my code:
$(document).on("click", "a[data-confirm], button[data-confirm]", function(e) {
var confirmData = $(this).data("confirm");
if (confirmData === "true")
confirmData = $(this).prop("title");
if (confirmData && !confirm(confirmData)) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
return false;
}
return true;
});
The problem is that I'm not sure about where this handler will go into the handlers list, so I guess there is a good probability that other handlers could execute before it. Also, I'm not sure if this handler will precede for example knockoutjs' click binding.
To prevent other handlers from being called use stopImmediatePropagation() and to prevent default behavior use preventDefault().
Like so:
$("body").on("click", ".elementClass[attributeName]", function(event){
event.stopImmediatePropagation();
event.preventDefault();
});
By adding the [attributeName] in the selector, the selector will only apply to elements with the attribute "attributeName"
In the example above this will be executed before your $(document) handler as the event bubbles up the DOM and gets to the body before it gets to the document. To ensure that this event is attached sooner, you can attach the handler to the element like so:
$(".elementClass[attributeName]").on("click", function(event){
event.stopImmediatePropagation();
event.preventDefault();
});
The downside to this, is that this handler must be attached after the element has the attribute.
Another technique you can use with just vanilla JavaScript, however, is event capturing: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener.
If true, useCapture indicates that the user wishes to initiate capture. After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. Events which are bubbling upward through the tree will not trigger a listener designated to use capture
You can do something like this:
document.addEventListener("click", function(event){
if(event.target.hasAttribute("attributeName")){ // jQuery: if($(event.target).attr("attributeName")){...
event.stopPropagation();
event.preventDefault();
//Do stuff
}
}, true);
By adding true at the end the event is captured, meaning this will be run before other handlers.
If an element has more than one click handlers, the execution order of those is unspecified. So you can't reliably make one always execute first.
Although all EventListeners on the EventTarget are guaranteed to be triggered by any event which is received by that EventTarget, no specification is made as to the order in which they will receive the event with regards to the other EventListeners on the EventTarget.
W3C-Events-flow-basics
So I'd like some JavaScript which listens for all potential focus/blur events on the page. I can do this for click events quite easily:
document.addEventListener('click', function (e) { console.log('click!') })
Any time any element is clicked, the event will trigger, even if the node was inserted after the event listener was added.
I'd like to do the same for focus events, but they are only triggered on individual elements, and never bubble up to the document.
How can I accomplish this? Is the only way to walk the DOM every few seconds and re-listen in case a new input element has been added?
You can use the focusin and focusout events which bubbles up.
document.addEventListener('focusin', function(e) { console.log('focusin!')})
Demo: Fiddle
I'm trying to make an extension with 'pick' functionality: letting the user click on any element on the page and see the xpath for it.
However, to make it usable I have to prevent the element from reacting on clicking: I don't want clicking on hyperlinks to forward me to another page, buttons to submit forms, etc., etc.
How would I do that?
UPD: I need it only for Chrome
The cleanest way in my opinion would be to bind one event handler to body in the capturing phase and prevent the event from propagating/the default behavior.
You can get a reference to the clicked element with event.target:
document.body.addEventListener('click', function(event) {
event.preventDefault();
event.stopPropagation();
console.log(event.target);
}, true);
The advantage is that this event handler will be the very first that is triggered, no matter which other event handlers are bound to elements in the page (unless of course the page binds a similar event handler to body, but usually event handlers are bound in the bubbling phase).
For more information see quirksmode.org - Event order and MDN - addEventListener.
DEMO
For a CSS only solution:
* {
pointer-events: none;
}
Try this
$('body *').on('click',function(e){
return false;
});
In your click event handler make sure you either call preventDefault() in the event object, or return false from your function. For example:
function myClickHandler(e) {
e.preventDefault() // e is the event object
// Do your click stuff here
.
.
.
return false; // not required if you've called e.preventDefault()
}
I have an onclick event attached to a region in my page that causes a certain action to fire when the user clicks in it (naturally). I recently added an image to that region. When the user clicks on that image, I want another action to occur, and I do NOT want the action associated with the entire region to occur. However, I find that both events are, in fact fired when one clicks the image. How do I suppress the region-wide action when the image is clicked?
The issue you are running into is known as event bubbling. The click event of the image bubbles up to all parent elements of that node. You want to cancel bubbling.
The best way to do this that works across all browsers is by using a JavaScript framework. jQuery has a very simple way to do this. Other frameworks have similar mechanisms to cancel bubbling, I just happen to be most familiar with jQuery.
For example, you could do something like this in jQuery:
$('img').click(function () {
// Do some stuff
return false;// <- Cancels bubbling to parent elements.
});
Darit is correct, you need to stop the event from bubbling (propagating):
function imgEventHandler(e) {
// ^notice: pass 'e' (W3C event)
// W3C:
e.stopPropagation();
// IE:
if (window.event) {
window.event.cancelBubble = true;
}
}
In the event handler for the image do
event.cancelBubble = true;
and then at the end do
return false;