There's this piece in the codebase I'm working on:
this.element.addEvent('click', this.clickEvent.bindWithEvent(this));
I want to change it so that the click event makes sure the window is loaded first. So I tried:
var t = this;
this.element.addEvent('click', function() {
window.addEvent('load', function() {
t.clickEvent.bindWithEvent(t));
});
});
That doesn't seem to get it to work though. What am I missing?
You're adding a handler to the load event when the user clicks something, _aftertheload` event has already fired. Therefore, nothing happens.
You should probably add the click handler inside of an event handler for the load event. (swap the two addEvent lines)
in mootools you tend to use domready and not load but essentially, doing it as suggested will not work as it lacks the context here:
this.element.addEvent('click', this.clickEvent.bindWithEvent(this));
so you are working within a class here - therefore, make sure you instantiate it on the domready event instead, something like...
window.addEvent("domready", function() {
// whatever you need to do...
var foo = new myClass($("someElement"), {option: value}); // example instantiation
// if the binding is not in the .initialize, then call the right method...
// foo.bindMyEvents();
});
as long as the class instance is within domready, you're fine. if that's not an option, see which method binds the events and call that on the domready instead.
Related
I have a site that uses AJAX to navigate. I have two pages that I use a click and drag feature using:
$(".myDragArea").mousedown(function(){
do stuff...
mouseDrag = true; // mouseDrag is global.
});
$("body").mousemove(function(){
if (mouseDrag) {
do stuff...
}
});
$("body").mouseup(function(){
if (mouseDrag) {
do stuff...
mouseDrag = false;
}
});
I just type that out, so excuse any incidental syntax errors. Two parts of the site use almost identical code, with the only difference being what is inside the $("body").mouseup() function. However, if I access the first part, then navigate to the second part, the code that runs on mouseup doesn't change. I have stepped through the code with Firebug, and no errors or thrown when $("body").mouseup() is run when the second part loads.
So, why doesn't the event handler change when I run $("body").mouseup() the second time?
Using $("body").mouseup( ... ) will add an event handler for the body that is triggered at mouseup.
If you want to add another event handler that would conflict with current event handler(s) then you must first remove the current conflicting event handler(s).
You have 4 options to do this with .unbind(). I'll list them from the least precise to the most precise options:
Nuclear option - Remove all event handlers from the body
$("body").unbind();
This is pretty crude. Let's try to improve.
The elephant gun - Remove all mouseup event handlers from the body
$("body").unbind('mouseup');
This is a little better, but we can still be more precise.
The surgeon's scalpel - Remove one specific event handler from the body
$("body").unbind('mouseup', myMouseUpV1);
Of course for this version you must set a variable to your event handler. In your case this would look something like:
myMouseUpV1 = function(){
if (mouseDrag) {
do stuff...
mouseDrag = false;
}
}
$("body").mouseup(myMouseUpV1);
$("body").unbind('mouseup', myMouseUpV1);
$("body").mouseup(myMouseUpV2); // where you've defined V2 somewhere
Scalpel with anesthesia (ok, the analogy's wearing thin) - You can create namespaces for the event handlers you bind and unbind. You can use this technique to bind and unbind either anonymous functions or references to functions. For namespaces, you have to use the .bind() method directly instead of one of the shortcuts ( like .mouseover() ).
To create a namespace:
$("body").bind('mouseup.mySpace', function() { ... });
or
$("body").bind('mouseup.mySpace', myHandler);
Then to unbind either of the previous examples, you would use:
$("body").unbind('mouseup.mySpace');
You can unbind multiple namespaced handlers at once by chaining them:
$("body").unbind('mouseup.mySpace1.mySpace2.yourSpace');
Finally, you can unbind all event handlers in a namespace irrespective of the event type!
$("body").unbind('.mySpace')
You cannot do this with a simple reference to a handler. $("body").unbind(myHandler) will not work, since with a simple reference to a handler you must specify the event type ( $("body").unbind('mouseup', myHandler) )!
PS: You can also unbind an event from within itself using .unbind(event). This could be useful if you want to trigger an event handler only a limited number of times.
var timesClicked = 0;
$('input').bind('click', function(event) {
alert('Moar Cheezburgerz!');
timesClicked++;
if (timesClicked >= 2) {
$('input').unbind(event);
$('input').val("NO MOAR!");
}
});
Calling $("body").mouseup(function) will add an event handler.
You need to remove the existing handler by writing $("body").unbind('mouseup');.
jQUery doesn't "replace" event handlers when you wire up handlers.
If you're using Ajax to navigate, and not refreshing the overall DOM (i.e. not creating an entirely new body element on each request), then executing a new line like:
$("body").mouseup(function(){
is just going to add an additional handler. Your first handler will still exist.
You'll need to specifically remove any handlers by calling
$("body").unbind("mouseUp");
I have an element #div_1 which has inside the same document (not extern file) a plain JS function:
var trigger = false;
var div_1 = document.getElementById('div_1')
div_1.onclick = function() { trigger = true; };
and in an extern JS file I have a jQuery button click on the same element:
$(document).ready(function() {
$('#div_1').click(function() {
// some actions here
});
});
The problem is that it does ignore the jQuery clickhandler completely. Is there no way to have two seperate click handler which work both?
There must be something else going on in your code because you can certainly have multiple event handlers on an object.
You can only have one handler assigned via onclick, but that should, in no way, interfere with the jQuery event handler. Please show us a reproducible demo in a jsFiddle because there is likely some other problem with your code causing this.
FYI, I'd strong suggest you not use the onclick attribute for event handlers because there is danger of one event handler overwriting another, something that does not happen when using .addEventListener() or jQuery's .click(). But, neither .addEventListener() or jQuery's .click() will overwrite the onlick.
Here's a working demo that shows both event handlers working just fine: http://jsfiddle.net/jfriend00/4Ge52/
I've got a bunch divs which each contain a remove link attached with the click event below:
var observeRemoveRoom = function
$('.remove_room').click(function(){
$(this).parent().removeClass('active');
});
}
Clicking it removes the 'active' class of the parent (the div). I call this observeRemoveRoom function on window load which works fine.
The thing is, I have another function which adds more of the same divs. Since the a.remove_room links contained within the new divs weren't around on window.load I need to call observeRemoveRoom.
Am I somehow duplicating the event handlers? Does jQuery overwrite them? If so should I unbind the handlers?
Each time you call observeRemoveRoom jQuery will add a new unique event handler function for a click event.
So yes, you need to .unbind() either all currently bound handlers by just calling .unbind() without arguments, or be specific and pass in a function reference.
You can try a live query to keep them updated: http://docs.jquery.com/Plugins/livequery
Yes, you will be duplicating the event-handlers if you call observeRemoveRoom again, but it might not be noticeable since you are only calling the removeClass method which does nothing if the class is not found, which would be the case after the first listener is triggered.
Instead you can un-bind and re-bind the click event each time, like:
var observeRemoveRoom = function(){
var remove_class = function(){
$(this).parent().removeClass('active');
};
$('.remove_room').off('click', remove_class).on('click', remove_class);
}
But that said, it is recommended that you do this outside this function`, rather than binding and unbinding the event every time, like:
$(document).ready(function(){
var remove_class = function(){
$(this).parent().removeClass('active');
};
// If the element exists at dom ready, you can bind the event directly
$('.remove_room').on("click", remove_class);
// If the element is added in dynamically, you can [delegate][1] the event
$('body').on("click", '.remove_room', remove_class);
// Note: Although I've delegated the event to the body tag in this case
// I recommend that you use the closest available parent instead
});
http://api.jquery.com/on/#direct-and-delegated-events : [1]
So, there are two important details to this question:
its inside the scope of document ready's callback function
the element that the event is attached to does not actually exist in the DOM
Here's a visual representation of the scenario
$(document).ready(function() {
$('#myNonExistentElement').on('click', function() {
//do something
});
});
Is it possible to programatically trigger that click event (via console or something else) under those circumstances?
I think the simple answer is no.
There are two cases which might, however, fit with your question:
1) If you just want to execute the event handler code, use a named function (instead of an anonymous function) and call it whenever you need to.
2) If you want to bind a click handler to an object that does not yet exist in the DOM but you know will in the future, you can use code like:
$(document).ready(function() {
$('body').on('click', '#myNonExistentElement', function() {
//do something
});
});
See the section about delegated events at http://api.jquery.com/on/
If you try to bind an event to an element that doesn't exist via jQuery (or at the very least, .on) no new event will be bound.
Sample case here.
*event code stolen from here because I'm lazy.
I have an issue which is driving me crazy and as a last resort I am placing a question here.
I want to move the onclick event from an element to the onfocus event of the same element and I am using the following code:
$("#theElement").bind("focus", {}, $("#theElement").data("events").click);
$("#theElement").unbind("click");
Maybe you have guess it. IT DOES NOT WORK.
How do I make this work? I am getting a "fn.apply is not a function" message in the following piece of code from jquery 1.3.2:
proxy: function( fn, proxy ){
proxy = proxy || function(){ return fn.apply(this, arguments); };
// Set the guid of unique handler to the same of original handler, so it can be removed
proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
// So proxy can be declared as an argument
return proxy;
}
EDIT: I'm sorry, I should have mentioned. This comes from a plugin which does some stuff when clicking an element. I want to make the same thing when the element gets focus not when it is cliked so the simplest solution I thought off was this since I can't modify the code for the plugin.
EDIT: Found the problem. It is similar to what #sje397 posted in his answer, not
$('#theElement').data('events').click[0]
but
$('#theElement').data('events').click[3]
For some reason, even if only one event is registered the thing ends up as 3 (the guid in that piece of code from jquery).
I would suggest naming the event handler in the first place, like
$('#theElement').click(function myHandler() {
//...
});
Then, you can do
$("#theElement").bind("focus", {}, myHandler);
$("#theElement").unbind("click");
This should make it more readable, as well as fixing the bug.
If you can't, then you can do:
// assuming yours is the first handler
var myHandler = $('#theElement').data('events').click[0];
$("#theElement").bind("focus", {}, myHandler);
$("#theElement").unbind("click");
Also not that in jQuery 1.4.3+, the key was changed to __events__. See this answer.
I found out that jQuery adds the event to an element by using .data(), so you could do something like this to retrieve the event handler:
$(el).data().events.click[0].handler
This is not an elegant solution, but if you cannot change anything to the click handler itself, this would be the only solution.
I'm not 100% clear what it is exactly that you want to do. Do you want to bind a focus AND a click event to the same element?
$("#theElement").bind("focus click", function(){
//do stuff
$(this).unbind('focus click');
});
edit: given your clarification - you want to fake the 'click' event on focus...
$("#theElement").bind("focus", function(){
$(this).trigger('click');
});
http://api.jquery.com/trigger/