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.
Related
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 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.
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 :-(
So I am just trying to add some functions to hover. the below does about the same thing except the one with the for loop i have the target stored in an array. I actually have a few questions.
is this the correct use of stopPropagation?
what's the best practice for doing something like this?
which one of the below method is faster and uses less resources?
I know I can use hover() but I used bind because I thought it is faster, is my thinking correct?
thank you
for (var i in slides) {
$(slides[i].el).bind( {
mouseenter: function (event) {
event.stopPropagation();
// do something
},
mouseleave: function (event) {
event.stopPropagation();
//do something
}
});
}
$("#vehicleSlides .vehicleAreas").bind( {
mouseenter: function (event) {
event.stopPropagation();
// do something
},
mouseleave: function (event) {
event.stopPropagation();
//do something
}
});
1 - is this the correct use of stopPropagation
If you wish to stop the event bubbling up the DOM tree, then yes.
2 - what's the best practice for doing something like this
Personally, I prefer the jQuery selector followed by methods, but this is just a preference. The best practice is whatever style you and your team all agree upon and use consistently.
3 - which one of the below method is faster and uses less resources
In practical terms, there will be next to no difference between the two.
4 - I know I can use hover() but I used bind because I thought it is faster, is my thinking correct
The jQuery hover method is shorthand for the bind to mouseenter and mouseleave events, so there will be one extra function call using hover, however there will be almost no difference in performance.
Best practice would make consistently correct functionality the highest priority, so it depends on whether or not the event should be seen or heard by a parent node once processed.
That depends on your design. For example, in a "window"-like object that you want to be able to drag around, you could either A. attach a mouse handler to the entire window, or B. attach a listener to a child "background" object to detect the mouse down event to begin dragging.
If you choose design B., then you have to make sure labels and other objects you don't want to receive mouse events have mouse events disabled (in Flash [AS3] set mouseEnabled and mouseChildren to false; not sure about JavaScript). One con of this design is that it would prevent any object in the U.I. from passively processing or modifying event behavior in the bubbling phase, because any interception in the capture phase would prevent it from reaching the background in the first place. One pro of this design is that by allowing the event to bubble, you could have monitors and other global effects processing mouse clicks at higher levels.
On the other hand, if you choose design A., then you don't have to worry about making child objects transparent to the mouse (an event on a label would still bubble up to the window container itself), but instead you have to make sure that event propagation on child objects like buttons is stopped once the event is handled so that they don't reach the window handler at the top of the hierarchy. It really depends on how you want it to function, and a hybrid approach is probably best.
You can have this down to a design science to the point where the "design" isn't a design at all, but a complex truth known to be true scientifically.
Any browser optimization of this system would involve keeping track, during the capture phase, of which parent nodes had bubble-phase event handlers attached for the event type. If for example it entered the target/bubbling phase knowing that no parent nodes had handlers, it could skip the entire bubbling phase, or jump directly to nodes known to have handlers. That's poor design however, IMO, because you might want to attach new handlers to parent nodes at any time during capture or bubbling, or you may want to move a node to another parent to try to cause the event to bubble up a different parent chain. Try it and see how it behaves in different browsers. There's bound to be huge inconsistency like anything else involving HTML rendering and event processing, in terms of both behavior and performance :P
There's probably not much difference between bind and hover. Work avoidance is always a good thing to consider but 1-3 more function calls to get to an event handler isn't going to put a dent in a modern JIT's performance.
You are not invoking stopPropagation incorrectly but if you're doing it for no particular reason other than bubbling making you uncomfortable or because you're afraid of triggering something else by accident, then yes, you are doing it wrong.
The first rule of UI work should always be:
DON'T DO ANYTHING YOU DON'T NEED TO DO
Examples:
Don't solve problems you don't have yet.
Don't do anything "just in case," because that means you don't know what's actually happening and you really need to understand what your stuff actually does and how it works before you call anything done in UI.
Don't stop people from using your UI differently than anticipated. e.g. validating HTML format and throwing errors when somebody tries to make something you wrote work a little differently. What are you, running a customer support line? It helps no one/serves nothing. What does it matter if they prefer a more semantically correct unordered list to a pile of divs?
But on stopProp specifically, if you must use it (and it can solve some problems very elegantly so never say never) try to only hit endpoint nodes with it so other things can be added to the same container without losing the benefits of bubbling. Yes, benefits I say. Don't fear bubbling. Events moving back up the ancestor line are only likely to trigger other UI events if your HTML is a complete disaster (it should be nothing but containers all the way back up to the body, right?).
Also if you can just verify that you have the right target element in the handler before taking action, do that instead of stopProp. But cripes it pisses me off when people add return false and e.stopPropagation to every single UI handler they write. Especially when they themselves pick up the event from a container that encompasses much more than the active element in question.
So don't do that. We might work in the same office some day and I can be whiny and insufferable and I'll sabotage your cheesecake.
Today is jQuery day. I found this in the documentation:
blur() Returns: jQuery Triggers the blur event of each matched element.
blur(fn) Returns: jQuery Bind a function to the blur event of each matched
element.
In other words, the behavior of the function is totally different depending if it accepts or not an argument.
Is this a design mistake or there's a historical reason for this ?
Keep into account that I know nothing about javascript nor jQuery, and I am trying to get a feeling of it.
That's how jQuery is designed, it's the same for all events. To add a handler to an element you use e.blur(function(){...}), and to trigger the event, you use e.blur(). It kind of makes sense, you just have to get used to it.
Definitely not a design mistake, because it goes for multiple events, such as click, however you should be using .trigger('blur')
It makes sense because .blur() or .click() by nature invokes the event handlers attached to the specific event, and all .blur(fn) does is bind it to .bind('event') where behind the scenes it registers the event handlers.