This example shows how to create a reusable JSONPRequest for polling as well as how to configure success and failure callbacks. See the API docs and user guide for a full listing of available configurations.
For this example, we will use a JSONP service hosted on YUILibrary to fetch information about a random Gallery module and render some of the information on the page.
The data
The structure of the JavaScript object returned from YUILibrary's JSONP service will look like this:
{ modules: [ { url: (the url to the module), title: (the title of the module), summary: (short description of the module), ..., owner: { icon: (url to the author's thumb image), fullname: (the author's full name), rank: (YUI Team member?, Contributor? etc), ... } } ], ... }
We'll use these objects to populate an HTML template with data {placeholder}s using Y.Lang.sub( template, object )
.
Start simple
To make a single call to the YUILibrary Gallery API, we can just use
Y.jsonp("http://yuilibrary.com/gallery/api/random?callback={callback}", handleJSONP);
But since each call to Y.jsonp()
creates a new instance of Y.JSONPRequest
, we may as well store the instance and reuse it.
var gallery = new Y.JSONPRequest("http://yuilibrary.com/gallery/api/random?callback={callback}", handleJSONP); gallery.send();
Add polling
JSONPRequest doesn't have any built-in polling mechanism, but Y.later()
can handle this for us.
var url = "http://yuilibrary.com/gallery/api/random?callback={callback}"; function handleJSONP(response) { // populate template from the response object and add to the output div ... Y.one("#out").setHTML( Y.Lang.sub(template, module) ); // After 7 seconds, call the API for a new module Y.later(7000, this, this.send); }; var gallery = new Y.JSONPRequest(url, handleJSONP); gallery.send();
Add failure protection
In case the Gallery API is busy or some other problem arises, we'll also want to handle this case and display an error. We can do this by passing a configuration object as the second parameter rather than a simple success callback.
var gallery = new Y.JSONPRequest(url, { on: { success: function (response) { // populate output div from the template and response object ... Y.one("#out").setHTML( Y.Lang.sub(template, module) ); // After 7 seconds, call the API for a new module Y.later(7000, this, this.send); }, failure: function () { Y.one("#out").setHTML( failureTemplate ); } } }); gallery.send();
Add flare
Now we'll add a bit of flourish, by adding a visual indicator of how long until the next module is requested. We'll replace the call to Y.later()
with a call to node.transition()
using a shrinking border to show the remaining time. Then when the transition is complete, we call send()
again.
var gallery = new Y.JSONPRequest(url, { on: { success: function (response) { // populate output div from the template and response object ... Y.one("#out").setHTML( Y.Lang.sub(template, module) ); // Add some flare to the poll interval by showing a "time left" // indicator via the header's border Y.one("#out h4") .setStyle("borderRightWidth", "100px") .transition({ borderRightWidth: 0, duration: 7 }, function () { gallery.send(); }); }, failure: function () { Y.one("#out").setHTML( failureTemplate ); } } }); gallery.send();
Stop the poll
The final step is to add the ability to start and stop the polling. We'll manage this by adding a property to the gallery
JSONPRequest instance named gallery.polling
. See the full code listing below for the implementation.
Full Code Listing
HTML
<div id="demo"> <input type="button" id="start" value="Start polling"> <input type="button" id="stop" value="Stop polling"> <div id="out"> </div> </div>
JavaScript
<script> YUI().use("jsonp", "transition",function (Y) { var url = "http://yuilibrary.com/gallery/api/random?callback={callback}", outputDiv = Y.one("#out"), gallery; // Using the configuration object syntax gallery = new Y.JSONPRequest(url, { on: { success: function (response) { var module = response.modules[0], author = module.owner; // Some users don't have a rank if (!author.rank) { author.rank = "user"; } // Format the author info and store as a property of the // module object for use by Y.Lang.sub // ('this' refers to the JSONPRequest object by default) module.authorHTML = Y.Lang.sub(this.authorTemplate, author); outputDiv.setHTML(Y.Lang.sub(this.moduleTemplate, module)); // Add some flare to the poll interval by showing a "time left" // indicator via the header's border Y.one("#out h4") .setStyle("borderRightWidth", "100px") .transition({ borderRightWidth: 0, duration: 7 }, function () { if (gallery.polling) { gallery.send(); } }); }, failure: function () { gallery.polling = false; outputDiv.setHTML(this.failureTemplate); // Wire up the Try again button outputDiv.one("button").on("click", function () { gallery.send(); }); } } }); gallery.moduleTemplate = '<h4><a href="{url}">{title}</a></h4>' + '<p class="author">{authorHTML}</p>' + '<div>{summary}</div>'; gallery.authorTemplate = '<img src="{icon}" height="30" width="30">' + ' {fullname} <span class="rank">({rank})</span>'; gallery.failureTemplate = '<p class="error">Ack, I couldn\'t reach the Gallery web service!</p>' + '<button>Try again</button>'; gallery.polling = false; // Click the button to send the JSONP request Y.one("#start").on("click", function (e) { if (!gallery.polling) { gallery.polling = true; gallery.send(); } }); Y.one("#stop").on("click", function (e) { gallery.polling = false; }); }); </script>