mpAjax (multi-part Ajax responses)
A demo of this plugin can be found here: http://test.getify.com/mpAjax
Basically, put simply, this plugin extends (but is still backward compatible with) the core $.ajax functionality to allow automatic parsing of responses for a special syntax of "multi-part responses". If a response matches this format, the response will be split out and treated as multiple responses, each being called to the proper "success" handler. If the response doesn't "look" like multi-part, then it falls through and behaves exactly as normal.
You may ask, why do we need multi-part responses? There's a few intended use cases, but it comes down to needing/wanting to return multiple different "parts" of data (different types, etc) in a single response.
1. You need to return a block of HTML (without encoding/escaping it into JSON), and a separate JSON packet with data.
2. You need to return an HTML template and some JSON data separately, without any obfuscation/encoding/escaping of either.
3. You need to return some HTML, some JSON, and also some CSS, and handle all three types of data separately.
4. You need to return two or more different blocks of HTML, and need to handle each separately.
In all these cases, you could of course encode one type of data and inline it with the other type of data (encode HTML into a JSON property, or embed your JSON into a hidden input field in your HTML). But those methods are inefficient and make your responses more complicated and harder to parse and debug.
The extra escaping of " characters in HTML when sticking it into a JSON property is both taxing on the server, as well as increases the download size by a \ character for each " character. Sticking JSON into your HTML requires extra unnecessary markup, CSS to hide it, and Javascript logic to find and parse it out.
But with a multi-part response, very similar to how MIME multi-part emails are formatted, you have each different data block/type in its own "part", natively and directly represented, no escaping/encoding necessary. And each is treated as their own response.
A "part" has a delimiter (the format syntax for multi-part responses mentioned above), and one or more "headers", such as "Content-type" or "Content-Length". The delimiter should contain a unique id (usually numeric) which you can use to identify the "part" when processing it in your Javascript. You can also identify the "parts" by their Content-type header ("text/html", "application/json", etc).
A multi-part response might look like:
!!!!!!=_NextPart_411426488
Content-Type: text/html
<div>Hello, I'm some HTML markup, and I can use " characters natively with no problems.</div>
!!!!!!=_NextPart_2106560908
Content-Type: application/json
{"greeting":"Hello","name":"I'm JSON, natively without any transformations or escaping!"}The code to consume this response is very unobtrusive and similar to how you currently make Ajax calls in jQuery:
Old:
jQuery.post(
"http://test.getify.com/mpAjax/search.php",
"json="+JSON.stringify(requestbody),
handleResponse
"text/plain"
);
New:
jQuery.post(
"http://test.getify.com/mpAjax/search.php",
"json="+JSON.stringify(requestbody),
{
"text/html":handleList,
"application/json":handleData
},
"text/plain"
);As you can see, you can specify an object with properties for each content-type expected in the response, and they will be called for the appropriate "parts" in the parsed response. You can also still specify just a single handler, and it will be called once for each part. The "data" object you're passed will have the delimiter header and the content-type header properties, so you can make similar processing logic decisions. Lastly, you can just pass an array of handlers ([.., ..]instead of the object {.., ..} literal) and the handlers in the array will be called in order, one for each "part" found.
Also, here's a very simple sample PHP function (which can easily be ported to any server language) for generating the "part" delimiters/headers in your response:
<?php
function generate_part($data,$type="plain/text",$showLength=false) {
$str = sprintf("!!!!!!=_NextPart_%d",+mt_rand());
if ($type) $str .= sprintf("\nContent-Type: %s",$type);
if ($showLength) $str .= sprintf("\nContent-Length: %d",strlen($data));
return $str."\n\n".$data."\n";
}
...
echo generate_part($results_html,"text/html");
echo generate_part(json_encode($data),"application/json");
?>