I've been reading about custom events in jQuery and why they should be used but I'm still clearly missing the point. There is a very good article I read here that has the following code example;
function UpdateOutput() {
var name = $('#txtName').val();
var address = $('#txtAddress').val();
var city = $('#txtCity').val();
$('#output').html(name + ' ' + address + ' ' + city);
}
$(document).bind('NAME_CHANGE ADDRESS_CHANGE CITY_CHANGE', function() {
UpdateOutput();
});
$('#txtAddress').keyup(function() {
$(document).trigger('ADDRESS_CHANGE');
});
$('#txtCity').keyup(function() {
$(document).trigger('CITY_CHANGE');
});
Can someone tell me why I just don't call the UpdateOutput() function directly? It would still work exactly the same way, i.e.
$('#txtAddress').keyup(function() {
UpdateOutput()
});
$('#txtCity').keyup(function() {
UpdateOutput()
});
Many thanks
As your article starts with:
As everyone knows, the more dependencies you have in a system, the harder maintaining that system is. Javascript is no exception- and orchestrating actions across complex user interfaces can be a nightmare if not done properly.
Using events removes (some of) these dependencies:
When something happens (a key is released/up), a notification of this event is send, without knowing whether anyone is interested at the moment or not.
When someone is interested in a certain event he can subscribe for it, without knowing why this event was triggered (key released)
Both bullets are independent, the first notifies and the second responds. Removing one does not matter for the functionality of the other. It is also easy to have multiple instances firing/subscribing to events (Also due to the missing dependencies).
Because you are one client of that event, even though you have full control over the entire application. It helps decoupling your code better.
As one of the clients who is interested in knowing when the name, address, or city changes, you are updating the values in some part of the screen. Some other client might want to do something else such as pull up all adjacent cities, reverse geocode the address, do a name lookup on namesdatabase.com, and so on.
You can still control everything without events and call multiple functions directly or put everything in it's own function, but adding events decouples the implementation from what needs to be done, based only on the type of event, so UpdateOutput does not have to worry about pulling up names from a names database, and you don't have to worry about calling all the necessary functions yourself whenever a particular event happens as long as there is a basic understanding of the events defined in the system and what they represent.
A second reason is abstraction. For example, deleting of a user account might get triggered by a simple click, but just by translating that to a higher level event such as DeleteAccount, things would get simpler and understandable when you consider that there could be tens, or hundreds, or maybe even thousands of such events all across the application. Working at a higher level of abstraction than "keyups", "keydowns", "mouseovers", etc. (which are really meaningless anyways in the context of an application and the intent behind), things can get a lot more manageable as the application size grows.
It’s perfectly reasonable to wire up the UpdateOutput() call directly. Often, it’s difficult to represent the need for an abstraction that custom event pooling provides in simple examples.
However, there’s (arguably) two issues of maintainability (again, depending on the use) when calling UpdateOutput directly. The first problem occurs by repeating the UpdateOutput() call in numerous places. This makes refactoring functions (especially those with parameters) extremely difficult when they change. With Event Pooling, you can prep data before passing it to a function, which is helpful when disparate code blocks call the same function. With ajax heavy web apps around, controlling function calls is very important.
Secondly, it’s possible you’ll need to call multiple functions for the same event. Imagine in addition to UpdateOutput(), there’s also some validation function which needs to be fired. Or when a user updates the zip code, some maps api is trigged to show something, or whatever other functionality which could happen (the point being you may have numerous functions being called in a simple keyup() event. Having this wired up directly makes for very large blocks of code which simply call multiple functions, and if there’s conditional logic required, they can get out of hand. Rewritten with event pooling, you get a lot more control of how a function like UpdateOuput is being called, so you don’t need to chase down the method across numerous files. You can simply see what events that cal is binded too.
Related
I would like to detect when a variable's value is updated on a server and run a callback that sends the new value to a client in order to provide a real-time feed. For example, say a server generates a random number at random intervals, but it's important for the client to be aware of a new number being generated as soon as it happens.
One simple solution is to define a custom function that you use to set your value instead of directly setting it with '=':
function setValue(val) { a = val; websocket.send(a) }
But that requires going back through already written code and replacing all instances of that variable being updated to instead use the custom function. A tedious and error-prone process but only has to be done once.
Another solution that I read about is to define a setter on the variable when initializing it, as described here.
This would only require replacing all the places where the variable is being initialized for the first time, but since it's listening hidden in the background I worry it reduces readability and someone may forget there's a callback firing each time the variable is being updated.
I don't code professionally so I'm not sure which of these solutions would be more widely accepted, or if there's a better way I should be approaching it. Also not sure of the performance hit this would cause but I'm guessing pretty negligible.
Define the custom function. Take the refactor pain now and keep it readable. Coding is 20% creation and 80% maintenance, but it always feels like 99% creation and 1% maintenance when you’re in the thick of making something new.
It seems like Backbone.Radio provides 2 new abstractions - commands and requests. They're pretty much identical to Backbone.Events, except that they can have only 1 subscriber. Is that it, and if so what advantage do they provide over events?
I plan on using Backbone.Events/Radio with React.js, if that helps.
I have not actually used Backbone.Radio but do make extensive use of Backbone.wreqr https://github.com/marionettejs/backbone.wreqr which provides an almost identical command service.
In my usage the difference between events and commands is:
For events to work the sender and receiver of an event must both exist and have a reference to each other and the receiver must be in a position to deal with the event properly. This can often be problematic in a fully asynchronous browser environment where different parts of your application are running at the same time.
Commands allow you to decouple the sender and receiver. One object, lets say a View A, can simply send command 'update_user_details'.
My second Object View B sets up a command handler for 'update_user_details' which will change the user details on the screen.
But what if View B does not yet exist, or is not yet rendered. In the event listener pattern you would have to make sure View A exists, that it passes a reference to itself to View B and then you attach an event listener in View B.
With commands it is not a problem, View A sends a command, if no-one has set a handler then nothing bad happens, the command just does nothing.
When View B turns up, totally independent of View A, it sets a handler and will respond to all future commands.
Just a final note about intent:
The event pattern can be thought about in this way: I, View A have just done something, anyone that is interested (the event listeners) can do what they like about it, I View A don't care what you do.
In the command pattern: I View A want someone to do something, I don't care who does it, I just want it done right.
Channels. The key difference with Backbone.Radio over plain vanilla Backbone.Events that I have seen is that it allows you to setup channels to which your code can 'tune in' e.g. from the documentation:
var userChannel = Backbone.Radio.channel('user');
This means that logical functions or apps in your code can emit and handle events only on a specific channel - even if you emit events with the same name, if they're on different channels you won't get cross-contamination. This ties in nicely with the principles behind separation of duties in your code.
The other other difference, and IMHO it's subtle, more to do with elegance of coding than any real functionality difference, is that if you're telling something to respond to an event then it's really a Command, and Backbone.Radio allows you to separate these kinds of event into that type. Similar logic applies to the Requests type.
For completeness...
The docs also explain that a Channel is an object that has all three types of messages (Events, Commands and Requests) mixed in. You mix it into an object (I use Marionette so I'm mixing into an instance of Marionette.Object) using Underscore/Lo-Dash's .extend():
_.extend(objectToBeExtended, Backbone.Radio.Requests);
And the same for Commands of course. The syntax for events is different as that's baked into Backbone itself so the second parameter is just Backbone.Events.
I am currently implementing a graph visualisation tool using lift on the server side and d3 ( a javascript visualisation framework) for all the visualisation. The problem I have is that in the script I want to get session dependent data from the server.
So basically, my objective is to write lift-valid ajax callbacks in a static js script.
What I have tried so far
If you feel that the best solution is one that I already tried feel free to post a detailed answer telling me how to use it exactly and how it completely solves my problem.
Write the ajax callback in another script using lift and call it from the main script
This solution, which is similar to a hidden text input is probably the more likely to work. However it is not elegant and it would mean that I would have to load a lot of scripts on load, which is not really conveniant.
This seems to be one of the prefered solutions in the lift community as explained in this discussion on the mailing list.
REST interface
Usually what one would do to get data from a javascript function in lift is to create a REST interface. However this interface will not be linked to any session. This is the solution I got from my previous question: Get json data in d3 from lift snippet
Give function as argument of script
Another solution would be to give the ajaxcallback as an argument of the main script called to generate my graph. However I expect to have a lot of callbacks and I don't want to have to mess with the arguments of my script.
Write the whole script in lift and then serve it to the client
This solution can be elegant, however my script is very long and I would really prefer that it remainss static.
What I want
On client side
While reviewing the source code of my webpage I found that the callback for an ajaxSelect is:
<select onchange="liftAjax.lift_ajaxHandler('F966066257023LYKF4=' + encodeURIComponent(this.value), null, null, null)" name="F96606625703QXTSWU" id="node_delete" class="input">
Moreover, there is a variable containing the state of the page in the end of the webpage:
var lift_page = "F96606625700QRXLDO";
So, I am wondering if it is possible to simulate that my ajaxcall is valid using this liftAjax.lift_ajaxHandler function. However I don't know the exact synthax to use.
On server side
Since I "forged" a request on client side, I would now like to get the request on client side and to dispatch it to the correct function. This is where the LiftRules.dispatch object seems the best solution: when it is called, all the session management has been made (the request is authentified and linked to a session), however I don't know how to write the correct piece of code in the append function.
Remark
In lift all names of variables are changed to a random string in order to increase the security, I would like to have the same behavior in my application even if that will probably mean that I will have to "give" the javascript these values. However an array of 15 string values is still a better tradeoff than 15 functions as argument of a javascript function.
Edit
While following my research I found this page : Mapping server functions to client actions which somehow explains the goal of named functions even if it stil didn't lead me to a working solution.
Quick Answer
Rest in Lift does not have to be stateless. If you register your RestHelper with LiftRules.dispatch.append, then it will be handled statefully and Session information will be available through the S object as usual.
Long Answer
Since you seem interested, and it's come up on SO before, here's a more detailed explanation of how server-side functions are registered and called in Lift. If you haven't worked with Lift for some time, look away. What follows should not in any way be used to evaluate Lift or its complexity. This is purely library developer level stuff and a majority of Lift users go about their development blissfully unaware of it.
How it works
When you create stateful callbacks, typically by using the methods within the SHtml object, what you are really doing is registering objects of type S.AFuncHolder within the context of the users session, each with a unique ID. The unique ID that was generated during this process is what you're seeing when you come across a pattern like F96606625700QRXLDO. When data is submitted, via form post, ajax, or whatever, Lift will check the request for these function ids and execute the associated function if they exist. There are several helpers that provide more specific types of AFuncHolder, like S.SFuncHolder (accepts a single string query parameter) and S.BinFuncHolder (parameter is multipart form data) but they all return Any and behind the scenes Lift will collect those return values to create the proper type of response. A JsCmd, for instance, will result in a JavaScriptResponse that executes the command. You can also return a LiftResponse directly.
How to use it
AFuncHolders are registered using the S.fmapFunc method. You'd call it like this
S.fmapFunc(SFuncHolder({ (str: String) =>
doSomethingAwesomeWithAString(str)
}))(id => <input type="text" name={id} value=""/>)
The first parameter is your function, wrapped in the proper *FuncHolder type and the second parameter is a function that takes the generated id and outputs something. The something that gets output is what you will include on the page. It should somehow result in the id being sent to the server as a query parameter so that your function is executed.
Putting it all together
You could use the above to make your own Ajax calls, but when Lift makes an ajax call there are a few other considerations:
1) Most browsers only allow so many simultaneous connections to a given domain. Three seems to be the magic number.
2) AFuncHolders will often close over the scope of the snippet they are contained within and if multiple ajax requests are handled at once, each in its own thread, bad things can happen.
To combat these issues, the liftAjax.lift_ajaxHandler function queues each ajax request, ensuring that only one at a time is sent to the server.
The drawback to this approach is that it can make it difficult to make an Ajax call where the result needs to be passed to a callback. JQuery autocomplete, for instance, provides a callback function when input changes that accepts a list of matches. If you are manually calling LiftAjax.lift_ajaxHandler though, you can provide your own callback functions for success & error and I would recommend that you look at the source of those functions in your browser for more information on how they work.
There's actually more to it, like how Lift restores RequestVars on ajax callbacks (which is where the lift_page comes in, but that's about all I'm prepared to explain over coffee on a Saturday morning :)
Good luck with your app!
I often use data-attributes to store configuration that I can't semantically markup so that the JS will behave in a certain way for those elements. Now this is fine for pages where the server renders them (dutifully filling out the data-attributes).
However, I've seen examples where the javascript writes data-attributes to save bits of data it may need later. For example, posting some data to the server. If it fails to send then storing the data in a data-attribute and providing a retry button. When the retry button is clicked it finds the appropriate data-attribute and tries again.
To me this feels dirty and expensive as I have to delve into the DOM to then dig this bit of data out, but it's also very easy for me to do.
I can see 2 alternative approaches:
One would be to either take advantage of the scoping of an anonymous Javascript function to keep a handle on the original bit of data, although this may not be possible and could perhaps lead to too much "magic".
Two, keep an object lying around that keeps a track of these things. Instead of asking the DOM for the contents of a certain data-attribute I just query my object.
I guess my assumptions are that the DOM should not be used to store arbitrary bits of state, and instead we should use simpler objects that have a single purpose. On top of that I assume that accessing the DOM is more expensive than a simpler, but specific object to keep track of things.
What do other people think with regards to, performance, clarity and ease of execution?
Your assumptions are very good! Although it's allowed and perfectly valid, it's not a good practice to store data in the DOM. Sure, it's fine if you only have one input field, but, but as the application grows, you end up with a jumbled mess of data everywhere...and as you mentioned, the DOM is SLOW.
The bigger the app, the more essential it is to separate your interests:
DOM Events -> trigger JS functions -> access Data (JS object, JS API, or AJAX API) -> process results (API call or DOM Change)
I'm a big fan of creating an API to access JS data, so you can also trigger new events upon add, delete, get, change.
I'd like to have a chain of filters (mostly in cases of errors) which are called sequentially and are given the xhrObject, so that each filter function can decide what to do based on the specific fault. There should also be a mechanism for passing along the data to the next filter function, or stopping the chain at some point.
I know that the Deferred objects in jQuery allow something like that, but I don't really see a way to declare one global xhrObject, to which these filter callbacks will hook up at the very beginning, so that they are handling any response/fault. Besides, having one global service delegate is not good either, because it may make the app go out of sync if the users perform many operations, while the previous ones haven't finished yet.
Besides, having one global service delegate is not good either,
because it may make the app go out of sync if the users perform many
operations, while the previous ones haven't finished yet.
AJAX, by its nature, is asynchronous. You should program accordingly. There is nothing wrong with a single delegation AJAX function.
I'd like to have a chain of filters
I think you need to explain this portion a little more clearly.