Example: Creating a Widget Plugin

This example shows how you can use Widget's plugin infrastructure to add additional features to an existing widget.

We use the "gallery-widget-io" plugin to add io capabilities bound to a widget instance. The plugin provides an io interface on Widget, which can be used to update the widget's contentBox contents.

NOTE: This example uses io-xdr to retrieve content from pipes, and requires Flash.

Using The Gallery IO Plugin For Widget

Setting Up The YUI Instance

For this example, we'll pull in widget; the gallery-widget-io plugin, and the json-parse modules to help us work with the JSON RSS data returned. The code to set up our sandbox instance is shown below:

YUI().use("widget", "gallery-widget-io", "json-parse", function(Y) {
    // We'll write our code here, after pulling in the default Widget module,
    // the IO plugin.
});

The Widget IO Plugin

The Widget IO plugin is a fairly simple plugin. It provides incremental functionality. It does not need to modify the behavior of any methods on the host Widget instance, or monitor any Widget events (unlike the AnimPlugin example).

It sets up the following attributes, which are used to control how the IO plugin's refresh method behaves:

uri
The uri to use for the io request
cfg
The io configuration object, to pass to io when initiating a transaction
formatter
The formatter to use to formatting response data. The default implementation simply passes back the response data passed in, unchanged.
loading
The default content to display while an io transaction is in progress

Using the Plugin

All objects derived from Base are Plugin Hosts. They provide plug and unplug methods to allow users to add/remove plugins to/from existing instances. They also allow the user to specify the set of plugins to be applied to a new instance, along with their configurations, as part of the constructor arguments.

In this example, we'll create a new instance of a Widget:

/* Create a new Widget instance, with content generated from script */
var widget = new Y.Widget();

And then use the plug method to add the WidgetIO plugin, providing it with a configuration to use when sending out io transactions (The Animation Plugin example shows how you could do the same thing during construction), render the widget, and refresh the plugin to fetch the content.

/*
 * Add the Plugin, and configure it to use a news feed uri, and work cross-domain, using xdr
 */
widget.plug(Y.Plugin.WidgetIO, {
    uri : 'http:/' + '/pipes.yahooapis.com/pipes/pipe.run?_id=6b7b2c6a32f5a12e7259c36967052387&_render=json&url=http:/' + '/rss.news.yahoo.com/rss/us',
    cfg:{
        xdr: {
            use:'flash'
        }
    },
    formatter: formatRSS,
    loading: '<img class="yui3-loading" width="32px" height="32px" src="../assets/widget/img/ajax-loader.gif">'
});

widget.render('#demo');

/* fetch the content */
widget.io.refresh();

We pass in a formatter to the io plugin, which is responsible for translating the JSON RSS from the uri to HTML:

var formatRSS = function (val) {
    var formatted = "Error parsing feed data";
    try {
        var json = Y.JSON.parse(val);

        if (json && json.count) {
            var html = ['<ul class="yui3-feed-data">'];
            var linkTemplate = '<li><a href="{link}" target="_blank">{title}</a></li>';

            Y.each(json.value.items, function(v, i) {
                if (i < 10) {
                    v.title = Y.Escape.html(v.title);
                    v.link = Y.Escape.html(v.link);
                    html.push(Y.Lang.sub(linkTemplate, v));
                }
            });
            html.push("</ul>");
            formatted = html.join("");
        } else {
            formatted = "No Data Available";
        }
    } catch(e) {
        formatted = "Error parsing feed data";
    }
    return formatted;
};

NOTE: Since we're using IO's XDR functionality for this example, we wrap the widget construction in a callback which notifies us when the flash XDR module is ready to service requests. In your local implementations, if you're not sending cross-domain requests, you don't need to use the XDR functionality and leave out the code below:

Y.on('io:xdrReady', function() {
    // Setup Widget when io xdr is available
});

// Set up io to use the flash XDR transport
Y.io.transport({
    id:'flash',
    yid: Y.id,
    src:'../../build/io-xdr/io.swf?stamp=' + (new Date()).getTime()
});

Complete Example Source

<div id="demo"></div>
<script type="text/javascript">
YUI().use("widget", "gallery-widget-io", "json-parse", "escape", function(Y) {

    var formatRSS = function (val) {
        var formatted = "Error parsing feed data";
        try {
            var json = Y.JSON.parse(val);

            if (json && json.count) {
                var html = ['<ul class="yui3-feed-data">'];
                var linkTemplate = '<li><a href="{link}" target="_blank">{title}</a></li>';

                Y.each(json.value.items, function(v, i) {
                    if (i < 10) {
                        v.title = Y.Escape.html(v.title);
                        v.link = Y.Escape.html(v.link);
                        html.push(Y.Lang.sub(linkTemplate, v));
                    }
                });
                html.push("</ul>");
                formatted = html.join("");
            } else {
                formatted = "No Data Available";
            }
        } catch(e) {
            formatted = "Error parsing feed data";
        }
        return formatted;
    };

    Y.on('io:xdrReady', function() {

        var widget = new Y.Widget();

        widget.plug(Y.Plugin.WidgetIO, {
            uri : 'http:/' + '/pipes.yahooapis.com/pipes/pipe.run?_id=6b7b2c6a32f5a12e7259c36967052387&_render=json&url=http:/' + '/rss.news.yahoo.com/rss/us',
            cfg:{
                xdr: {
                    use:'flash'
                }
            },
            formatter: formatRSS,
            loading: '<img class="yui3-loading" width="32px" height="32px" src="../assets/widget/img/ajax-loader.gif">'
        });
        widget.render('#demo');

        widget.io.refresh();
    });

    Y.io.transport({
        id:'flash',
        yid: Y.id,
        src:'../../build/io-xdr/io.swf?stamp=' + (new Date()).getTime()
    });

});
</script>