#

# Example: Reusing a JSONPRequest Instance to Poll a Remote Server

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>