What is “jQuery.event.special”? - javascript

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.

Related

How does JQuery create it's Custom Events and can I recreate in Javascript?

I am looking to create events in Javascript using the same methodology as JQuery- Does anyone know how JQuery does it?
My reasoning is that using raw Javascript such this:
var myEvent = new CustomEvent("userLogin", eventProperties);
...does not actually work on Android native browser, as it does not support DOM Level 3 like Chrome and other browsers do.
However, JQuery does work on Android's stock browser, and simply uses:
$.event.trigger('MyEvent');
My question is, what is the code behind this? I tried to find it by going through JQuery's source code, but cannot get my head around it!
The fundamental thing here is this: When you hook an event handler up with jQuery, jQuery doesn't directly add that handler to the DOM element. Instead, jQuery hooks up a handler of its own on the DOM element (if it doesn't already have one on it). When the event occurs, jQuery looks at the list of jQuery-registered handlers for the event and fires them in order. (There are several reasons for this; initially it was primarily around IE memory leaks and the fact that IE fired handlers in one order, and everyone else in a different order; so jQuery took over and ensured the order.)
(You might be able to see where I'm going with this...)
So when you use trigger, jQuery sends the synthetic event to the DOM element, but it doesn't rely on that synthetic event to work; it calls the handlers you've registered through jQuery directly. In fact, it sets a flag so that it knows that it's done that, so if the browser does send the event to jQuery's handler for it, jQuery knows to ignore it (since it's already done its work).
You can see this in all its glory starting with line 4,464 of the current uncompressed jQuery file.
So basically jQuery's build its own pub/sub system, and only uses the browser event system as an input to it. So custom events don't usually have to talk to the browser at all.

Invoke the default action of a specific event on an object

I want a generic (cross browser) way to get the browser to execute the default action for an object for a specified event preferably without getting any attached listeners to fire.
This kind of question has been asked before but in the context of already being in an event, &/or strictly talking about synchronously holding off the default action before letting it happen later.
Basically, let's say you have an DOM element (you don't know which) variable, and you want to invoke a click, such that if it were an anchor, it'd follow its href, if it were an input[type="submit"] it would submit the form.
But without firing that element's listeners for the click event (which may be prone preventDefault()s in the listeners).
For those that need a reason to answer questions; you may want to do it if you're implementing something like dispatchEvent() for browsers that only have fireEvent().
Both functions return true if the default wasn't 'prevented', but only dispatchEvent() actually follows through and invokes the default.
As a side question, jQuery's trigger() is meant to do this (although after firing the listeners) and be cross-browser, maybe the solution is there? As nice as jQuery is I'd like to know the vanilla methods it is calling (if it [this particular feature] indeed works on things like IE8).
It appears that, at least for the click event, you can call .click() on the element in these browsers.
This will have the element enact the default (as well as calling all listeners and the .onclick value, if defined).
I don't know of any other defaults on DOM elements, would scroll need to be accounted for? Keypress? Maybe those exist as functions too, but I haven't tested.
When I did test .click(), I noticed it obeyed any of the listeners returning false and did not fire the default, and the event did bubble (a listener I had on document fired too!).
There may be no other alternative (I.e. calling the default directly, avoiding the listeners). And as for passing it an event object, the browser in question has the single global event thing going on, so maybe you can manipulate that and it wont have changed when executing .click().
Adding as I find more information in my travels :)
Furthermore, there is an doScroll() function, but I think it would be really hard to translate a given event into the string accepted by this method

Detect if an Input has Changed dynamically

Other javascript is changing the value of an input and I was wondering if there was a way to detect the change.
This question has nothing to do with Keyup or Change. This is not being typed in by the user it is being changed by other javascript though various actions of the user.
When changing an event programatically, you can trigger a change event to make sure event handlers that are attached to the element are fired. jQuery has a trigger() method to do this:
$('#elementID').on('change', function() {
alert( this.value );
});
$('#elementID').val('some new value').trigger('change');
The quick run-down of what I am going to say is: there is no way other than to modify the third-party scripts to output stuff, or to use setInterval (costly).
The bottom line of this issue is a simple one, that does not appear to be so at first: How can you get your scrips to communicate with each other?
When a script modifies the value of an input through JS methods (i.e. not user input), they have to go through specific hoops to get the "change" event to fire (they can fire it manually by calling it, which most devs never do and is easily forgotten when writing code). In practice, people tend to rely on the observation events (user-defined ones) to track code changes. This is very similar to DOM events - you bind callbacks to your script, which allow you to tap callbacks in that will fire whenever your scripts do something interesting (like modifying inputs. This is just one example). You then teach your scripts and developers to fire events on useful stuff using the callbacks to notify other scripts.
A great library for this is Postal, which is originally a Node library. jQuery also has an event system you can tap into. However, if you want to roll your own, all you have to read into is the Observer design pattern. It is trivial: you bind a function to your object to pick up callbacks, and another to fire them. Whenever you change the thing, you fire the callback. Simples.
Failure to do so means setInterval. Sucks, but there you go :-(

Functional jQuery: Custom Events or Functions?

Being new to functional programming, I was working on my application's javascript (using jQuery exclusively), and wondering how jQuery's event system relates to it's functional programming paradigm.
I have a function setupAccountHeader that could easily be either a document-bound event like
$(document).bind('setupAccountHeader', function() {
blah, blah, blah;
});
OR
var setupAccountHeader = function() {
blah, blah, blah;
};
Then, either triggered or called when needed.
So I have two questions:
1) Which style is preferred for functional jQuery or is this purely a matter of taste/personal-style? What about implications for big-picture architecture?
2) Are there any good resources for functionally-styled jQuery? I feel like this is John Resig's intent, but I can't find much in the way of info or guides on what this means in implementation.
The nice thing about the second style is that it will show in the debugger call stack with its name, as opposed to "anonymous", which I find a bit more helpful.
You could achieve the above along with jQuery's added event mechanisms (as Elzo said) with the following:
$(document).bind('setupAccountHeader', setupAccountHeader);
The official method of binding an event in jQuery is the first version, this way you have similar methods for binding and unbinding events. I think is not that much of a personal preference as it helps code readability, getting support for your code and using other functions related and included in jQuery like preventing default event bubbling. The second example of the first question is correct from JavaScript, but this style is not used anywhere in jQuery documentation.
Update
If you to bind events and use the benefits of a normalized event system you'll use the first version for regular (blur, focus, load, resize, scroll, unload, beforeunload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, keyup, error) or your custom events.
They are actually not similar. In order to be similar in the second one you'll have to attach to document some events. Try to cancel them to get the idea.
// first version
$(document).unbind('setupAccountHeader'); // will cancel the binding of some action
// second version
setupAccountHeader = null; // will just cancel a variable
The other version is just a closure that you can use everywhere in JavaScript, and is used in this case as well. It doesn't have any specific meaning without a context.
I don't really understand the second question. Maybe you can detail what you mean. I'm not a native English speaker.

Trying to wrap my head around custom events

I'm trying to get my head around custom events. I understand how to register and trigger custom events. However, it seems like its not possible to register truly custom events. Everything has to trace back to a DOM event like click, onload, blur, etc. Or am I wrong?
For example, suppose I have an array. I want to register an event that fires when the length of the array changes. To my understanding, I would have to register the event and then create a setInterval timer that checks the current array length against the previously stored length. If the length has changed, I would then need to trigger my custom event from inside the setInterval.
Is there a way to register an event for my array and have it fire automatically when the length changes?
Custom events are in the W3C spec, but none of the major browsers support them. This is why several other users have suggested 3rd party libraries. Prototype, YUI, JQuery, and most others have these capabilities. You can also roll your own.
If you'd like to see what some custom event syntax might look like, you can take a look at this tutorial for Prototype custom events. Some important points:
Prototype custom events must be attached to DOM elements, so that they can bubble like native events.
They must be in a prefix:event syntax in order to fire
They can contain a highly-useful memo parameter that allows any arbitrary context or set of objects to bubble with the event.
why don't you write a method addElement for your array that you'll use whenever you want to insert elements,that way you will be able to write code in the event of array.length change.
same thing with removeElement.
Events are not meant to be used for this kind of thing.

Categories