Check if on event is handled - javascript

How can I check, if a event is handled with .on in jquery?
For example I have added an event handler to the button click event:
$(document).on("click", "#button", function(event) {
alert("Handled buttonclick event!");
});
Now I want to check if the event is handled to prevent assigning the same event handler a second time.

Since you are delegating to the document - you need to check the document's event handlers
$._data(document,'events') // will return all event handlers bound to the document
Then you can do check the events you want.. for example click
var events = $._data(document,'events').click; // all click events
$.each(events,function(i,v){ // loop through
v.selector; // will give you all the selectors used in each delegated event
});
http://jsfiddle.net/B7zS6/
each object will contain the following
Object {type: "click", origType: "click", data: undefined, handler: function, guid: 2…}
data: undefined
guid: 2
handler: function (event) {
namespace: ""
needsContext: false
origType: "click"
selector: "#button"
type: "click"
__proto__: Object
This is assuming your delegated events are bound to the document object though. So in this case you "MUST" know which element the event handler is actually bound to. The other answers will probably work a lot better
so this method would not know about
$('body').on("click", "#button", function(event) {
alert("Handled buttonclick event!");
});
or
$('parentelement').on("click", "#button", function(event) {
alert("Handled buttonclick event!");
});

If you want to add a button click once only the you can use one() like,
$("#button").one("click",function(event) {
alert("Handled buttonclick event!");
});
or manually you can check by setting a variable like
var countClicked=0;
$(document).on("click", "#button", function(event) {
alert("You clicked button "+ (++countClicked) + " times");
});

Related

Allowing child element to continue/trigger an event using jQuery

I have this code against the document object:
$(document).on('keydown', function(event) {
event.preventDefault();
});
Is it possible to put an exception on a child <textarea> element for example and allow the keydown to proceed as normal on that child?
As per CBroe's input, the solution was to call stopPropagation() when the element to have an exception calls the keydown event:
$('textarea').on('keydown', function(event) {
event.stopPropagation();
});

Add event listener to a child object of the window

Is it possible to add an event to a child object on the window, one that will accept events from anywhere (like the window)?
So, for example:
window.myVariable.addEventListener('keydown', doKeyDown);
This way I can remove this particular key down event, without removing other keydown events that are attached to the window.
How is something like this done?
You could create a simple registry that operates on a "namespace".
(function() {
var register = {};
function addNamedListener(namespace, eventType, callback) {
register[namespace] = register[namespace] || [];
register[namespace].push({
eventType: eventType,
callback: callback
});
window.addEventListener(eventType, callback);
}
function removeNamedListener(namespace) {
register[namespace].forEach(function(event) {
window.removeEventListener(event.eventType, event.callback);
});
}
window.WindowEvents = {
addNamedListener: addNamedListener,
removeNamedListener: removeNamedListener
}
})();
// Attach a general window event to the actual window
window.addEventListener('click', function(e) {
console.log(e.target);
});
// Attach a namedspaced event
WindowEvents.addNamedListener('windowClicks', 'click', function(e) {
console.log(e.target);
});
// Attach another event to the same namespace
WindowEvents.addNamedListener('windowClicks', 'click', function(e) {
console.log(e.clientX);
});
// Attach a new event to a different namespace
WindowEvents.addNamedListener('down', 'mousedown', function(e) {
console.log('Mouse down occurred');
});
<div>Click Me</div>
Then, when you are ready to get rid of the events in that "namespace", you would just do this:
WindowEvents.removeNamedListener('windowClicks');
This will leave the original window events, as well as the other namespace event that was created (down).
This should at least get you started.
Not really, although you could assign the handler to, for example, the body element.
This way I can remove this particular key down event, without removing other keydown events that are attached to the window.
This sounds like an X-Y problem though.
removeEventListener requires that you specify which event listener you are going to remove.
removeEventListener('keydown', doKeyDown);
… so the default behaviour is "without removing other keydown events".

why does stopPropagation take an event parameter in the callback instead of using 'this'?

I don't understand why, when using stopPropagation() or stopDefault() with jQuery, you have to introduce a param to the callback in the event handler function. How does the browser know what to pass in to that function? Also, why doesn't using this work?
Here's the code that works. I've bolded/asterisked the part that is confusing:
$(document).ready(function() {
$(".see-photos").on("click", function(**event**) {
event.stopPropagation();
$(this).closest(".tour").find(".photos").slideToggle();
});
$(".tour").on("click", function() {
alert("This should not be called");
});
});
To me, it would make more sense this way. Note there is no event param for the callback in the handler function.
$(document).ready(function() {
$(".see-photos").on("click", function() {
$(this).stopPropagation();
$(this).closest(".tour").find(".photos").slideToggle();
});
$(".tour").on("click", function() {
alert("This should not be called");
});
});
That's because jQuerys' .on() function passes the element who the event was fired from as this, not the event itself.
If you try to do the following:
$('a').on('click', function () {
console.log(this);
});
You will see in your console the <a> tag that got clicked on. This is applicable to both the DOM click event as well as jQuery's. You can also see this <a> tag from event.target.*
If you want information about the event, then you need to inject it into your function as you've done so in your question:
$('a').on('click', function (event) {
console.log(event);
});
This way, all of your event information is found in event. Likewise, it is only logical that you would stop propagating the event itself, as the element isn't propagating anywhere.
That being said, this and event.target are not the same

jQuery - multiple event listeners for same button

Say I have an button with an id:
<input id='someButton' />
I want to attach an event listener on this button:
$('#form').on('click', '#someButton', function() {
alert("My listener called");
});
However, unbeknownst to me, someone previously wrote an event listener for this very same button:
$('#form').on('click', '#someButton', function() {
alert("Some other listener called");
});
I encountered some code that effectively does the same thing as above, and it seems like the first listener registered is the one that is used. Am I correct in assuming jQuery will always call the first event listener registered on a specific id (and only that listener)?
Incorrect. jQuery will call ALL event listeners bound to an element, in the order they were bound.
To remove an existing event handler, use .off():
$('#form').off('click'); // click event handler(s) removed
$('#form').off(); // all event handler(s) removed
Be aware that events delegated from ancestor DOM elements won't be removed this way, though.
you could use mousedown:
$('#form').on('mousedown', '#someButton', function() {
alert("My listener called");
});
Hope this help.

why does this on() trigger right away instead of just binding?

Im having some problems with .on() and how to use it instead of .bind() in this situation.
What im trying to do here is i click a link and that is supose to bind another click event, but instead it triggers that event right away. I looked in the documentation/jquery.js file and this is how im suppose to do it.
Demo: http://jsfiddle.net/bNaFV/
$('#click_me').on('click', function(){
$('#show_me').addClass('remain');
//this is only suppose to bind that next time i click anywhere on the document it should hide
// not right away
$(document).on('click', 'html', function(){
$('#show_me').hide();
});
});
$("#click_me").hover(
function () {
$('#show_me').show();
},
function () {
if ($('#show_me').hasClass('remain')){
return;
} else {
$('#show_me').hide();
}
}
);
click me<br /><br />
<div id="show_me"></div>​
You need to stop the propagation of the event:
$('#click_me').on('click', function(e){
e.stopPropagation(); //Stop the event from bubbling further
$('#show_me').addClass('remain');
$(document).on('click', 'html', function(){
$('#show_me').hide();
});
});
This is because the event has been captured at the #click_me element. You then bind an event handler for that same event type somewhere higher up the DOM tree. The event then continues bubbling up the tree and reaches the document, where it triggers the new event handler.
Here's a working example.
Update (see comments)
As noted by #zerkms in the comments, I think you probably only want to bind the event handler to document once. You could use the one method to do so, which unbinds the event handler after it's been executed once:
$(document).one('click', 'html', function(){
$('#show_me').hide();
});

Categories

Resources