The YUI Simple Controls for Shared Hosting (ASP.NET)

posted on 7th Mar 2007

With the release of Yahoo!'s shared hosting for YUI (Read their article: Serving YUI Files from Yahoo! Servers) I thought I'd release a couple of ASP.NET server controls (and practices) I've found as a great helper.

Firstly, I think YUI (and I say it yooey :) is a great library. It uses some tight OO patterns, and is headed by some of the key instigators in how we currently use javascript as a first class object oriented language. A couple of years ago I read Douglas Crockford's articles on javascript and started understanding the real power we have with it, and he's one key member there. So it's got some really good minds behind it. Jack Slocum also thought YUI was good, but didn't quite get enough exposure, and started building his yui-ext library with it, and damn his work is looking good, but that's another story and I digress...

There are a couple of key benefits to using the hosted YUI solution.

  1. Benefiting from the cache That is, if someone visits Yahoo!, or another site that uses the shared YUI files, instead of downloading the files anew, the browser simply loads the files from the cache - you save bytes and time!
  2. Files are served minified, compressed (gzipped) and your site or application gets to take advantage of Yahoo!'s extensive network infrastructure and caching features.
  3. Easy deployment and upgrades Since you don't have to deploy the entire library each time or each new version, which can be tedious if you store the entire source in with your website files, you simply provide a reference to the right version of the right file.

There are two points to be aware of though:

  1. Yahoo! currently do not provide a securely hosted set of files. They recommend serving the files from your own server if you need HTTPS.
  2. If you are worried about privacy, it's worth noting that requests for the library from your site will produce relevant log file entries and statistics for Yahoo!. Nothing too sinister there I don't think, provided you know where you stand.

Enough background already! What do I get out of this? Well, fair enough. Thanks for your patience this far. The controls I write about are extremely simple. They're designed to make using the shared YUI library a sneeze and because YUI has a fairly frequent release cycle, it helps tackle upgrade issues.

All it really consists of is, a 'Script' control, that renders HTML script elements to your page, a YuiScript control which is complemented with a YuiScriptType enumeration. And then the same scenario for the YUI CSS files (Although with some limitations). The version of YUI to be used can be set programmatically, or via the web.config, so it makes upgrading a breeze.

How do you use it? There are two ways. Assuming you have the tag prefix and library registered in your web.config, or at the top of your page like so:

<%@ Register TagPrefix="YUI" Namespace="Singular.Web.YUI" Assembly="Singular.Web.YUI" %>

You can simply add the YUI Scripts in your .aspx page.

<YUI:YuiScript Runat="server" Type="YahooDomEvent" Version="2.2.0" />

The version attribute can be omitted, and preferably set in the web.config, so upgrades are uniform. Alternatively, you can add scripts programmatically to the controls in the head of your page like so:

protected void Page_Init(object sender, EventArgs e)
{
    Header.Controls.Add(new YuiScript(YuiScriptType.YahooDomEvent));
    Header.Controls.Add(new YuiScript(YuiScriptType.Dragdrop));
}

If you want to go the programmatic route, I'd suggest going a little further, and add a "scripts collection" to your applications base Page class.

public abstract class PageBase : System.Web.UI.Page
{
    ScriptList _scripts = new ScriptList();
    StylesheetList _styles = new StylesheetList();

    public ScriptList Scripts
    {
        get { return _scripts; }
    }

    public StylesheetList Styles
    {
        get { return _styles; }
    }

    protected override void OnPreRender(EventArgs e)
    {
        _scripts.ForEach(Header.Controls.Add);
        _styles.ForEach(Header.Controls.Add);

        base.OnPreRender(e);
    }
}

ScriptList and StyleList are included in the attached source, but are simply wrappers of an IList<Script>.

With the example above, you can concisely add client script and style sheets to your page.

// core
Scripts.Add(new YuiScript(YuiScriptType.YahooDomEvent));
Scripts.Add(new YuiScript(YuiScriptType.Dragdrop));

// logger
Scripts.Add(new YuiScript(YuiScriptType.Logger));
Styles.Add(new YuiCss(YuiCssType.Logger));

// overloaded add method for normal, non YUI Script
Scripts.Add("~/lib/js/ui/dashboard.js");

As you can see, the collection of script and stylesheet controls are simply add to the aspx page's header in the OnPreRender event. This means that you can investigate and manipulate the set of scripts or styles in a simple manner, removing some, adding more etc, right up until the page is rendered, like in the following example:

if (!Scripts.Contains("~/lib/js/ui/dashboard.js"))
{
    Scripts.Add("~/lib/js/ui/dashboard.js");
    Scripts.Add("alert( 'wooo!' );", false);
    Scripts.RemoveAt(3);
}

You can also see in the last example, an overload of the "Add" method to add a script that doesn't have an external source i.e. the "alert(...);" statement.

I feel this method has more control, and prefer it to the default Page.RegisterClientScript() and the ScriptManager, although they both have their pros and cons.

When their next release comes out (current release was 2.2.0 at the time of writing), you should be able to add a key to your web.config's AppSettings like so and your application will use the specified version, provided they don't break with their naming conventions:

<add key="YUI.Version" value="2.2.1" />

Download the sample project The sample project can be downloaded here. It contains all the necessary files to compile the library, including the dependent TextHelper utilities and base classes for the Script and Stylesheet (and collections) from our internal Singular library.

An improvement on this set of files might be to add a setting to serve the files from a local server location instead of the Yahoo! servers. This would help when developing locally, offline, intranet, or wanting to step through the files while debugging - like I said earlier, the shared files are minified, which doesn't make for very readable code ;)

One final note. The sample library was whacked together pretty quick and contains a couple of less-than-implemented sections: Two of the CSS locations for YUI don't seem to follow a consistent naming convention and have been omitted from the implementation. A better solution than the given samples would be to use a custom Attribute on each of the YuiScriptType and YuiCssType enumerations (or at least the ones that don't fit in with convention easily) to specify a custom location of the corresponding file.