Generic AJAX completed handler? - javascript

I'm working with a content management system that utilizes a number of different AJAX procedures for different functions. I really don't want to start poking around the core procedures because what I need doesn't warrant the effort.
So here's my question. Is there a generic JQuery on-completion handler that will detect if an AJAX call has been performed/was successful that I can utilize to launch a procedure without having to append to the return function of the specific query/process?

jQuery has a global .ajaxComplete event you can look into.
https://api.jquery.com/category/ajax/global-ajax-event-handlers/

Related

When making multiple ajax requests, is there a "good pattern" for tracking which data the responses line up with?

I build a lot of client-side js apps and have worked mostly with Backbone. Backbone always expects your api to return a copy of the created/changed/deleted model when such ajax actions are completed, allowing it to easily determine which "model" just got updated.
I'm working in a new scenario (new framework, freshly built API) in which all I get back from the API are success/error status codes. The whole "return the entire model" seems like a crutch...but the more I work trying to keep track of these async actions the more it feels like a necessary one.
Is there some kind of convention (outside of the Backbone world, perhaps) for more easily handling this kind of thing?
Edit: I may want to point out I'm using FLUX so the uni-directional flow is preventing me from just cross-wiring everything on either side of the dispatcher.
Your question title is more clear to me than the description, so I'll go with that.
If you are having difficulties in keeping track of multiple ajax requests results, you should use Promises.
For example, with the Q library you can do something like this:
Q.all([AjaxModel1(), AjaxModel2(), AjaxModel3()])
.spread(function(resultModel1, resultModel2, resultModel3) {
});
If what you need to know is how to get a model every time you make a change to them, I would need more details about your framework/server/code.

Modify jQuery getJSON - add functions on call and callback

I'm trying to create a loader that tracks when AJAX calls start and end. It's using JSONP so the .ajaxComplete() doesn't work / isn't reliable.
Ideally I'd like to modify getJSON so that every time it is called a function, addAJAX(), is also called. The callback will also fire a function removeAJAX().
Currently I'm having to do this by adding in functions to every getJSON, of which there are many and likely to be many more.
For example:
// Add ajax tracker
hl.addAJAX();
$.getJSON('someurl.com?callback=?',{ key: APIKEY }, function(json) {
// Remove the ajax tracker
hl.removeAJAX();
});
Creating a wrapper function for AJAX calls is one option, but I'd really like to know if jQuery can be modified this way?
Yes you can override jQuery to do such actions. I have posted one answer for a similar type question. So Instead of re-posting, providing the reference -
How to get default error of ajax call
Technically it certainly could be done -- jQuery is just JavaScript, so you could dig through the sources .js files, find the method in question and modify to your heart's content. However, this certainly isn't a trivial edit and I would strongly advise you against modifying core functionality of third party libraries unless you think that there's no other feasible option and you're ready for what comes along with it.
I say that because that will mean, among other things, that you'll have to maintain those changes when you're trying to move to future versions, and that you may break support for other libraries or plugins which expect certain functions to work certain ways.
As much as it may be annoying to call the function in the callback every time, that's the recommended way of accomplishing this type of functionality.

Lift session-valid ajax callback from a static javascript

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!

Javascript JQUERY AJAX: When Are These Implemented

I'm learning javascript. Poked around this excellent site to gather intel. Keep coming across questions / answers about javascript, JQUERY, JQUERY with AJAX, javascript with JQUERY, AJAX alone. My conclusion: these are all individually powerful and useful. My confusion: how does one determine which/which combination to use ?
I've concluded that javascript is readily available on most browsers. For example, I can extend a simple HTML page with
<html>
<body>
<script type="text/javascript">
document.write("Hello World!");
</script>
</body>
</html>
However, within the scope of Python/DJANGO, many of these questions are JQUERY and AJAX related. At which point or under what development circumstances would I conclude that javascript alone isn't going to "cut it", and I need to implement JQUERY and/or AJAX and/or some other permutation ?
Javascript is code that runs client-side in the browser.
AJAX is a term used to refer to the process of Javascript contacting the webserver directly and getting a response as opposed to the user navigating to a different page
jQuery is a javascript library that provides an easy-to-use abstraction over top of AJAX and the browser DOM
Django is Python code that runs server-side
In some situations you can do the same operation on either the client or on the server. Typically however, you determine if it should be done client/server by asking yourself, "where is the resource that needs to be used located?" For example, querying a database would be done on the webserver, because that's where that resource is. Conversely re-arranging the webpage's UI is done client-side, because that's where the the UI is.
Javascript alone can always "cut it", but the advantage jQuery brings is that it makes things easier and faster, and cuts out a lot of the browser issues in doing AJAX and DOM manipulation.
Since you are new to Javascript development, I'll try with relatable examples.
You can vote questions up or down on StackOverflow. Your vote action is sent to the server, and it gets recorded there. Had it not been for AJAX (and some other techniques), the entire page would need to be refreshed for that one action. AJAX solves the problem of asynchronously communicating with a server without requiring full page reloads.
jQuery is a library that provides convenient access to common Javascript tasks such as DOM manipulation, AJAX handling, etc. jQuery also hides away browser differences and provides a consistent interface for the end user. To illustrate these two points, see these examples:
finding all div elements on the page
// Javascript
var divs = document.getElementsByTagName("div")
// jQuery
$("div")
adding a click event handler to a button (illustrates browser differences)
With pure Javascript, it's best to create a cross-browser method to add events, as you surely wouldn't want to write this code every single time. Source - http://www.scottandrew.com/weblog/articles/cbs-events
function addEvent(obj, evType, fn, useCapture){
if (obj.addEventListener) { // standards-based browsers
obj.addEventListener(evType, fn, useCapture);
return true;
} else if (obj.attachEvent) { // IE
var r = obj.attachEvent("on"+evType, fn);
return r;
} else { // some unknown browser
alert("Handler could not be attached");
}
}
​Once this is setup (one-time only), you can add events to any elements using this function.
// Javascript
var button = document.getElementById("buttonID");
addEvent(button, "click", function() { alert("clicked"); }, false);
// jQuery (contains code similar to above function to handle browser differences)
$("#buttonID").click(function() { alert("clicked"); });
AJAX is part of Javascript and not a separate technology in itself. You would use AJAX to avoid doing full page refreshes when you need to send/receive data from the server.
jQuery, MooTools, Dojo, Ext.JS, Prototype.JS, and many other libraries provide a wrapper around Javascript to abstract away browser differences, and provide an easier interface to work with. The question is would you want to do all of this re-work yourselves. If you're not exactly sure what re-work you may need to do, researching pure Javascript examples of common tasks such as AJAX calls, DOM manipulation, event handling, along with abstracting away browser quirks and comparing those to examples to equivalents in libraries such as jQuery might be a good start.
The reason are exactly the same as you choose to use Django instead of Python alone.
jQuery is javascript library which will make your life easier and extends javascript.
Beyond the fact that jQuery is useful, I advise you to learn javascript first, as you should have learnt python before to use Django.
To resume :
pure javascript => simple code, native function exists for what you need
jQuery => complex code, rich application, functions doesn't exists in pure javascript ($.each() method for example).

Connecting a form to a Javascript Object (and other best practice advice)

I've been using javascript to do lightweight functionality on sites for years - DOM manipulation etc - but just now im beginning to investigate using it to do a lot more of the heavy lifting (in combo with PHP). I've only just started getting into OO JS, and im still trying to get my head around the best-practices and design patterns that work well with it.
To be more specific - my question is, can anyone here suggest techniques for connecting a form to a javascript object?
In my current implementation I have an JS object that can be edited by a (fairly large) form. When I instantiate the object I attach an onchange observer to the form, whose callback syncs the form fields with the object parameters. I'm handling the form submitting through AJAX - there is also a periodic request that saves a temporary version of the form info to a mySQL DB. One thing I wonder is whether it is possible to easily handle syncing in the other direction - onchange of the object the form fields update (on form reset for instance).
I am interested to know if this approach is a correct/sensible one, and more generally I would be very interested to hear advice with regard to OOJS form handling.
Cheers in advance :)
(Im using Prototype btw)
You can use $("form").serialize(true);
http://www.prototypejs.org/api/form/serialize
You dont need the onchange event, you can just call the serialize() method every time you need to get the form data.
Why not create a method in you object that resyncs the object with the form? And call that on every change of the object? You could create a special change function to assure that it gets called on every change.
It's a perfectly reasonable approach. JS doesn't entirely encourage this sort of thing due to its curious object system and in particular the way bound methods are not first-class objects, but with a bit of suitable metaclass and callback glue it's eminently possible.
You might also want to look at a widget library if you'd like to get more of this kind of low-level form handling stuff for free. Haven't tried the ones built on top of Prototype; other possibilities include YUI's one.
Updating the model from the server can be pretty simple. Generally you'd poll an AJAX request and have the server pass back either diffs, if it knows them, or else just timestamp each object update, send the new object details to the client side on each update, and have the client decide how to merge that with any changes the user has made in the meantime.

Categories

Resources