I'm using smarty streets jquery.liveaddress plugin in an angular single page app. I need to unbind all of the event listeners from the liveaddress instance when I transition to next page. Right now, if I come back to the page, all events are fired twice, then the next time on page, three times.
I've tried everything i can think of. My last solution was to unbind all of the event names from the $(document) because it looks like that is where the plugin is attaching all of the events to. but even that didn't work.
jQuery(document).unbind("AddressChanged");
jQuery(document).unbind("AutocompleteUsed");
jQuery(document).unbind("VerificationInvoked");
jQuery(document).unbind("RequestSubmitted");
jQuery(document).unbind("ResponseReceived");
jQuery(document).unbind("RequestTimedOut");
jQuery(document).unbind("AddressWasValid");
jQuery(document).unbind("AddressWasAmbiguous");
jQuery(document).unbind("AddressWasInvalid");
jQuery(document).unbind("AddressWasMissingSecondary");
jQuery(document).unbind("OriginalInputSelected");
jQuery(document).unbind("UsedSuggestedAddress");
jQuery(document).unbind("InvalidAddressRejected");
jQuery(document).unbind("AddressAccepted");
jQuery(document).unbind("Completed");
Ok for anyone trying to implement SmartyStreets jquery.liveaddress plugin in an angular application.
The trick was to not register anonymous event handlers.
In my case I was instantiating SmartyStreets in a directive, so put all the eventHandlers on scope and call liveAddress.deactivate() upon $destroy. No more duplicate events.
In jQuery, event handler functions are stored in an array. Therefore, unbind() function looks just for the function in the aforementioned array. It further means that you can only unbind() event handlers which are already added with bind().
Check out jQuery documentation on .bind()
Related
I was reading through MaterializeCSS's js files, in its "cards.js" file, there are these lines:
$(document).on('click.card', '.card', function (e) {
//something
});
I am not unfamiliar with jQuery's .on() function, but I never used custom event as the first parameter. What I don't understand is there seems to be nowhere defining this custom event click.card(if it is a custom event), because I only load this card.js and another velocity.min.js file from the MaterializeCSS package besides jQuery, and I searched velocity.min.js there is nothing related to this event. It seems to me that the custom event is in this pattern:original event.classname, but I tried replacing card with other class name and it didn't work.
I tried to look for more information about how to define a custom event but couldn't find anything useful.
My question is how to find where this custom event is defined.
This is not a custom event, this is a DOM event with a namespace:
click is the DOM event, and card the event namespace.
If you have multiple handlers on the same element, this can help you discern them. You could remove only this listener (and leave all other click listeners):
$(document).off('click.card');
And you can trigger them manually using $('...').trigger:
$('.card').trigger('click.card'); // only triggers this specific click listener, not the others
You can find out more about event namespaces here.
I am new to jQuery and I have been trying to look up the Bootstrap transition.js (line 50) code and figure out how it works in there. I have stumbled across the following:
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
I have read the documentation, but couldn't really understand much except the following:
bindType: // the event you want to bind with
delegateType: // the event you want to delegate with
After some research I have found the following:
Those are the special attributes for the transition end event that are made available for later use in transition.js.
I am trying to figure out things by reading this article, but all I want to know is: what is $.event.special, what is the use of this line? What is it's common usage?
P.S.: I read this question but it has more external links than the answer itself. Is there a clear canonical Q&A about the most basic use of $.event.special?
WHAT is the use of this line?
I'm assuming you meant the first line of code in your question. It basically defines bsTransitionEnd as an alias for the transition end event (the transition end event may vary from browser to browser - that is what the function transitionEnd() does : determine the proper transition end event for the browser. I've used webkitTransitionEnd here on, but it could be something else depending on the browser)
Why use an alias? It insulates any handlers that Bootstrap attaches using this alias (e.g. $('myBootstrapDialog').on('bsTransitionEnd', Bootstrap's handler) from any $('myBootstrapDialog').off('webkitTransitionEnd') that other code (say, your code or maybe another library) does - so the Bootstrap transition end animations would still work!
Why would you or another library do that? The webkitTransitionEnd is a standard event, so let's say you decide to add a transition end animation to a bootstrap dialog - you'd probably do $('myBootstrapDialog').on('webkitTransitionEnd', your handler) and later on you decide to remove the handler you should be going $('myBootstrapDialog').off('webkitTransitionEnd', your handler), but you miscode it as $('myBootstrapDialog').off('webkitTransitionEnd') - this removes all transition end events :-(.
But since Bootstrap attached it's handlers using 'bsTransitionEnd', the only way you could mess up bootstrap would be to do $('myBootstrapDialog').off('bsTransitionEnd') - not something you would do accidentally :-). So voila! Gone be the bugs where Bootstrap inexplicably stops working because of some small miscoding on your part.
The bindType and delegateType basically state that bsTransitionEnd is an alias for transition events attached directly, and ones that are delegated (bubbles). The handle is basically a filter function - all the triggered events basically go through this before the attached Bootstrap event handlers are called (if at all they are)
what is $.event.special?
I'm sure you'd know most of it already - it's a way to hook into jQuery's event handling mechanism allowing you do large scale magic like do X on every attached click event on the page (imagine doing that one by one, at each and every place you've attached an onclick event), define your own events (with all the bubbly goodness and all which comes with it), hook in and spoof events by modifying the event object, etc.
WHAT is its common usage?
I assume this was rhetorical :-) - you already have a couple of really good examples in the Ben Alman blog post you linked to
(paraphrasing) - let's say you do an AJAX submit and want to disable all clicks on the page (you probably don't want the user clicking on and navigating off to some other page via a menu, or changing a checkbox, etc.) and $.event.special.click should help you (of course it might be just easier / traditional to just overlay a transparent / partially transparent div with a Submitting... animation or something or not doing anything - after all, most users wait around to make sure a submit was successful, at least the normal ones :-))
Another use case is the one you saw in the bootstrap code, but like you mentioned, you usually don't have to go in and use this unless you're writing a library or something that you intend to distribute publicly.
$.event.special
The jQuery special events API is a fairly flexible system by which you can specify bind and unbind hooks as well as default actions for custom events. In using this API, you can create custom events that do more than just execute bound event handlers when triggered--these "special" events can modify the event object passed to event handlers, trigger other entirely different events, or execute complex setup and teardown code when event handlers are bound to or unbound from elements.
The jQuery special event hooks are a set of per-event-name functions and properties that allow code to control the behavior of event processing within jQuery. The mechanism is similar to fixHooks in that the special event information is stored injQuery.event.special.NAME, where NAME is the name of the special event. Event names are case sensitive.
As with fixHooks, the special event hooks design assumes it will be very rare that two unrelated pieces of code want to process the same event name. Special event authors who need to modify events with existing hooks will need to take precautions to avoid introducing unwanted side-effects by clobbering those hooks
bindType: // the event you want to bind with
delegateType: // the event you want to delegate with
When defined bindType: String, delegateType: String, these string properties specify that a special event should be handled like another event type until the event is delivered. The bindType is used if the event is attached directly, and the delegateType is used for delegated events. These types are generally DOM event types, and should not be a special event themselves.
I have two functions hooked on the submit event of a form. Each function is in a different place, and one function can affect the other.
How can I force one of these functions to be hooked with the lowest priority (ie. be the last to be executed)?
There are four ways I can think of:
Manage the callbacks yourself, and only have one event handler that calls the functions in the desired order.
In the function that is supposed to fired last, do the actual work in a zero-millisecond timeout. If all other functions work synchronously (and you can live with the final one not happening during the event bubbling), this will achieve the same thing.
Bind the to-be-fired-last handler higher up in the DOM tree. You'll have to test if that works with submit events; bubbling of these events doesn't work in IE, but the jQuery docs mention that this has been normalized in jQuery. May be worth a try.
Somewhat similar to 1., when binding any other handler than the low-priority one, unbind the latter, bind the new one, and finally re-bind the last-to-be-run.
You could use custom events for the handlers and have the first handler capture the submit to prevent it, do its stuff, fire the event for the second handler and have the second do the submit
If you want to use / can use custom events, you can use https://github.com/fusion-events/fusion-framework
Is there a way to temporarily disable an event listener?
In my case, I have a third party library (not jQuery centric) that creates mouseover/mouseout events on an element using addEventListener/attachEvent.
Under certain circumstances another event fires on a different element and I need to disable those event listeners. My solution thus far has been to simply unbind the mouseover/mouseout. This usually works fine because that event generally causes the page to refresh.
However, every now and again an error can occur (think validation error) that results in the page not refreshing, and I need to re-attach the mouseover/mouseout event listeners.
Helpful information
It's probably worth mentioning that because the mouseover/mouseout event listeners are created and attached within a third party library I cannot simply assign the event to a variable and bind/unbind it in that manner (which AFIK is the best way to do this).
Update
I had originally asked
Is there a way in jQuery to get the event listeners already assigned to an object?
I have since found out it is impossible to access events assigned by addEventListener/attachEvent: Access events added with attachEvent() / addEventListener() in JavaScript
jQuery uses data to store events internally, so you can use it to get all of the event handlers for an object:
$("#foo").data("events")
You can then remove a specific handler by using unbind:
$("#foo").unbind('click', $("#foo").data("events").click[42]);
Unfortunately, you can't access them. At best, you can remove event listeners using W3C's removeEventListener (docs) and/or Microsofts detachEvent (docs). Once the listener is removed, however, it's gone for good.
There's one caveat with removeEventListener, in that if the event was registered twice, once indicating to capture, and once indicating not to capture, you must remove it twice; once for each case.
To learn more about capturing and not capturing, see the W3C spec.
If you want to temporarily disable an event handler being run, why not just add escape code to the function?
like so:
$('#button').click(function(){
var clicked_element = $(this);
if(elem.hasClass('event-click-disabled'))
{
// logging code so we know exactly what events are being skipped
console.info(
'The click event on following element was skipped',
clicked_element
);
return;
}
alert('Button clicked');
});
Then if you want to disable an event on a specific element, just call
element.addClass('event-click-disabled');
The event handler is still run, but it will return immediately.
When I'm writing some JavaScript I have a set of interface buttons that have their events assigned when the page is loaded. My problem is anything created dynamically wont receive these events.
For example, I'm making a URL checker, whose job is to make sure that any link that goes to another domain brings up an exit interface letting the user know they are leaving. Any links created after the page is loaded, post ajax (no pun intended) or whatever wont have that event naturally as those that existed when the page loaded.
In practice, what's the best way to ensure any newly created items get these sorts of global events?
I like to use jQuery, but this is really a conceptual question.
Should I create a function to re-apply any global link effects, or is there a smarter way besides doing it piecemeal?
If using jQuery, you can use the .live() method.
Normally when binding an event handler, the event handler is bound to a specific set of elements. Elements added in the future do not receive the event handler unless it is re-bound.
jQuery's .live() method works around this by binding its own special event handler to the root of the DOM tree (relying on event bubbling). When you click on an element, if it has no event handler directly attached, the event bubbles up the DOM tree. jQuery's special event handler catches the event, looks at its target and executes any user-specified event handlers that were assigned to the target through .live().
Look into jQuery's live function. It will allow you to attach to events when control are created during load, and whenever new ones are created. There is a performance penalty, but it is not significant unless you are loading a lot of elements.
You can use the .live() jQuery method to add listeners to elements that are created after the page is finished loading. Using your example of the exit link (if I understand it correctly):
$(function(){
$('a.exitLink').live('click',function(event){ /* do stuff when a link of class exitLink is clicked */);
});
This will respond to the click event on any link of class exitLink, regardless of when it was created (before or after onload fires).
Hope this helps :)
Yes put simply, where you might have had this before:
$('selector').click(function () {});
Replace it with:
$('selector').live('click', function() {});