<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>CSS/HTML</title>
        <link>http://www.ridgway.co.za/category/11.aspx</link>
        <description>CSS/HTML</description>
        <language>en-ZA</language>
        <copyright>Eden Ridgway</copyright>
        <managingEditor>eden@ridgway.co.za</managingEditor>
        <generator>Subtext Version 1.9.5.176</generator>
        <item>
            <title>Setting up an Optimised Deployment Version of your AJAX ASP.Net Application</title>
            <link>http://ridgway.co.za/archive/2008/01/28/setting-up-an-optimised-deployment-version-of-your-ajax-asp.net.aspx</link>
            <description>&lt;p&gt;With rich AJAX web applications one needs to look at optimising resources such as your CSS, JavaScript and image files. Yahoo has collected together a great &lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;collection of best practices&lt;/a&gt; that have been put into their &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; Firefox extension. These should be taken as a guideline and not gospel. In general however the core principals are as follows:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Keep server roundtrips to a minimum&lt;/strong&gt;. The techniques for the various resource types are as follows:
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;JavaScript&lt;/em&gt; - combine them into a single file if possible. One has to make certain they are combined in the correct order in the file. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;CSS&lt;/em&gt; - again merge them as far as possible. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Images&lt;/em&gt; - Use &lt;a href="http://www.alistapart.com/articles/sprites"&gt;CSS sprites&lt;/a&gt; where one combines several images into one and uses the background image offset to display the one you are after. To create the sprites you can always use this online sprite generator. &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Reduce the size of each request&lt;/strong&gt;. This is done in two ways:
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;GZip/Deflate&lt;/em&gt; compress text resources by configuring IIS and/or using an ASP.Net HTTP Module. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Reduce file sizes&lt;/em&gt;. The tools I use for each type are:
        &lt;ul&gt;
            &lt;li&gt;JavaScript - &lt;a href="http://www.raboof.com/projects/Jazmin/"&gt;Jazmin&lt;/a&gt; provides pretty good minification by removing whitespace. If you want better minification then you should take a look at the Dojo &lt;a href="http://dojotoolkit.org/docs/shrinksafe"&gt;ShrinkSafe&lt;/a&gt; compressor which will shorten the name of local variables and functions to reduce the file size even more. The downside to this is it makes troubleshooting a production issue more difficult. &lt;/li&gt;
            &lt;li&gt;CSS - &lt;a href="http://csstidy.sourceforge.net/index.php"&gt;CSSTidy&lt;/a&gt; not only reduces whitespace but optimises the CSS expressions as well. &lt;/li&gt;
            &lt;li&gt;Images - As PNGs are my image format of choice I use &lt;a href="http://brh.numbera.com/software/pnggauntlet/"&gt;PNGGauntlet&lt;/a&gt; to reduce the image file size. &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Ensure resources are cached&lt;/strong&gt;. If you know that the files are going to change infrequently then all you have to do is set IIS to enable content expiration for a folder/file to expire after a set number of days, say 10. This will ensure that the client browser caches the resources and does not re-download them. However depending on the frequency of your deployments and your server architecture you most likely want to ensure that your etags are setup correctly. These are used to indicate whether or not the cached browser resources have changed. When loading a page the browser will send a request to the server, with the etag, for each resource and if it has not changed then the server will only return a 304 status code. Note that this advice is contrary to Yahoo where they tell you to remove etags for a web farm scenario. What you should rather do is ensure that the etag change number is the same for each server in the web farm. This ensures that the etag generated for the same resource on a different server is the same (how to do this varies depending on your version of IIS - read this &lt;a href="http://www.lowtek.com/blog/2006/09/save-web-server-bandwidth-by-fixing.html"&gt;post&lt;/a&gt; for more IIS6 information). If you are using a single web server however the whole this is a non-issue for you. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay so we know we want to combine and minify our CSS and JavaScript files when we deploy to our test, staging and production environments, but we don't want to develop and debug our applications with monolithic files with no whitespace and cryptic names. The problem is that our pages contain references to these files and we are merge them them together for deployment our references will now be incorrect. Well this is quite easily solved using compiler directives, like so:&lt;/p&gt;
&lt;div class="code"&gt;&lt;span style="background-color: rgb(255, 255, 153);"&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;%&lt;/font&gt;&lt;font color="#ff0000"&gt; #if DEBUG %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/javascript"&lt;/font&gt;&lt;font color="#ff0000"&gt; src&lt;/font&gt;&lt;font color="#0000ff"&gt;='&amp;lt;%= ResolveUrl("~/JavaScript/File1.js") %&amp;gt;'&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/javascript"&lt;/font&gt;&lt;font color="#ff0000"&gt; src&lt;/font&gt;&lt;font color="#0000ff"&gt;='&amp;lt;%= ResolveUrl("~/JavaScript/File2.js") %&amp;gt;'&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/javascript"&lt;/font&gt;&lt;font color="#ff0000"&gt; src&lt;/font&gt;&lt;font color="#0000ff"&gt;='&amp;lt;%= ResolveUrl("~/JavaScript/File3.js") %&amp;gt;'&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
&lt;/font&gt;&lt;span style="background-color: rgb(255, 255, 153);"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;%&lt;/font&gt;&lt;font color="#ff0000"&gt; #else %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/javascript"&lt;/font&gt;&lt;font color="#ff0000"&gt; src&lt;/font&gt;&lt;font color="#0000ff"&gt;='&amp;lt;%= ResolveUrl("~/JavaScript/Section.minified.js") %&amp;gt;'&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
&lt;/font&gt;&lt;span style="background-color: rgb(255, 255, 153);"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;%&lt;/font&gt;&lt;font color="#ff0000"&gt; #endif %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;For CSS files you can either use the directives around alternative &amp;lt;link&amp;gt; elements or around @import statements, like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;style&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/css"&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#800000"&gt;      &lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;span style="background-color: rgb(255, 255, 153);"&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;%&lt;/font&gt;&lt;font color="#ff0000"&gt; #if DEBUG %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;font color="#800000"&gt;      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;@&lt;/font&gt;&lt;font color="#800000"&gt;import '&amp;lt;%&lt;/font&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;font color="#800000"&gt; ResolveUrl&lt;/font&gt;&lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;"~&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#800000"&gt;Css&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#800000"&gt;File1&lt;/font&gt;&lt;font color="#0000ff"&gt;.&lt;/font&gt;&lt;font color="#800000"&gt;css"&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt;&lt;font color="#800000"&gt; %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#800000"&gt;';      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;@&lt;/font&gt;&lt;font color="#800000"&gt;import '&amp;lt;%&lt;/font&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;font color="#800000"&gt; ResolveUrl&lt;/font&gt;&lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;"~&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#800000"&gt;Css&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#800000"&gt;File2&lt;/font&gt;&lt;font color="#0000ff"&gt;.&lt;/font&gt;&lt;font color="#800000"&gt;css"&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt;&lt;font color="#800000"&gt; %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#800000"&gt;';      &lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;span style="background-color: rgb(255, 255, 153);"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;%&lt;/font&gt;&lt;font color="#ff0000"&gt; #else %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;font color="#800000"&gt;      &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#0000ff"&gt;@&lt;/font&gt;&lt;font color="#800000"&gt;import '&amp;lt;%&lt;/font&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;font color="#800000"&gt; ResolveUrl&lt;/font&gt;&lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;"~&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#800000"&gt;Css&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#800000"&gt;CombinedStyles&lt;/font&gt;&lt;font color="#0000ff"&gt;.&lt;/font&gt;&lt;font color="#800000"&gt;minified&lt;/font&gt;&lt;font color="#0000ff"&gt;.&lt;/font&gt;&lt;font color="#800000"&gt;css"&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt;&lt;font color="#800000"&gt; %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#800000"&gt;';      &lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;span style="background-color: rgb(255, 255, 153);"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;%&lt;/font&gt;&lt;font color="#ff0000"&gt; #endif %&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;&lt;/font&gt;       &lt;br /&gt;
&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;style&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;There is a catch to this however, since the aspx pages are compiled separately, setting your application to compile as a release build will not cause the references to change. What you need to do is change the compilation setting in the application web.config file, which should be set to debug="false" in the production environment:&lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;compilation&lt;/font&gt;&lt;font color="#ff0000"&gt; debug&lt;/font&gt;&lt;font color="#0000ff"&gt;="false"&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;      &lt;br /&gt;
  ...       &lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;compilation&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;Now on to the merging and minification. This could be accomplished using MsBuild or a batch file, but a batch file is simpler, so I'll discuss that. On one of the build steps for the web site(s) invoke the batch file which then ensures that the optimised files are always up to date. So you want to add something like this to your pre/post build compilation step in the project property window:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ridgway.co.za/images/ridgway_co_za/WindowsLiveWriter/SettingupanOptimisedDeplo.NetApplication_E3AF/image_4.png"&gt;&lt;img width="504" height="196" border="0" src="http://ridgway.co.za/images/ridgway_co_za/WindowsLiveWriter/SettingupanOptimisedDeplo.NetApplication_E3AF/image_thumb_1.png" alt="image" style="border-width: 0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;I setup the "Build Scripts" folder to contain the optimisation programs as well as text files with lists of files to merge, for example:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ridgway.co.za/images/ridgway_co_za/WindowsLiveWriter/SettingupanOptimisedDeplo.NetApplication_E3AF/image_12.png"&gt;&lt;img width="164" height="105" border="0" src="http://ridgway.co.za/images/ridgway_co_za/WindowsLiveWriter/SettingupanOptimisedDeplo.NetApplication_E3AF/image_thumb_5.png" alt="image" style="border-width: 0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;You'll notice that I group the JavaScript files on the site by Section of the site and not by page. The granularity of file grouping really depends on the application, but by section or function is a pretty good starting point. Each line of the file will contain a file name, like this:&lt;/p&gt;
&lt;p&gt; SubDir\File1.js&lt;br /&gt;
SubDir\File2.js &lt;/p&gt;
&lt;p&gt;I don't need to specify the full relative path of the files, in respect to the build folder because when I develop web sites all JavaScript files are placed within a JavaScript folder off the root of the web site.&lt;/p&gt;
&lt;p&gt;In my simplified scenario the "Optimise Web Resources.bat" batch file contains the following:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre style="background: rgb(255, 255, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: rgb(0, 0, 0);"&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;set&lt;/span&gt; OLDDIR&lt;span style="color: rgb(128, 128, 48);"&gt;=&lt;/span&gt;%CD%&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(105, 105, 105);"&gt;:: Change to the current directory&lt;/span&gt;&lt;span style="font-family: mon;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;cd&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;/&lt;/span&gt;d &lt;span style="color: rgb(0, 140, 0);"&gt;%0&lt;/span&gt;&lt;span style="color: rgb(128, 128, 48);"&gt;\&lt;/span&gt;.. &lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(105, 105, 105);"&gt;::Ensure there are no old temporary files lying around&lt;/span&gt; &lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;del&lt;/span&gt; *.js&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;del&lt;/span&gt; *.css&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(105, 105, 105);"&gt;::Create a single file for the JavaScript in the admin section&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;for&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;/&lt;/span&gt;F &lt;span style="color: rgb(0, 0, 230);"&gt;"tokens=*"&lt;/span&gt; %%f &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;in&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;(&lt;/span&gt;AdminJsFiles.txt&lt;span style="color: rgb(128, 128, 48);"&gt;)&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;do&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;call&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;type&lt;/span&gt; &lt;span style="color: rgb(0, 0, 230);"&gt;"..\Web Sites\Site\JavaScript\%%f"&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(128, 128, 48);"&gt;&amp;gt;&lt;/span&gt; AdminCombined.js&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;type&lt;/span&gt; AdminCombined.js &lt;span style="color: rgb(128, 128, 48);"&gt;|&lt;/span&gt; jazmin &lt;span style="color: rgb(128, 128, 48);"&gt;&amp;gt;&lt;/span&gt; AdminCombined.minified.js&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;copy&lt;/span&gt; AdminCombined.minified.js &lt;span style="color: rgb(0, 0, 230);"&gt;"..\Web Sites\Site\JavaScript\AdminCombined.minified.js"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(105, 105, 105);"&gt;::Combine the Stylesheets into a single file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;for&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;/&lt;/span&gt;F &lt;span style="color: rgb(0, 0, 230);"&gt;"tokens=*"&lt;/span&gt; %%f &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;in&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;(&lt;/span&gt;CssFilesToMerge.txt&lt;span style="color: rgb(128, 128, 48);"&gt;)&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;do&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;call&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;type&lt;/span&gt; &lt;span style="color: rgb(0, 0, 230);"&gt;"..\Web Sites\Site\CSS\%%f"&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(128, 128, 48);"&gt;&amp;gt;&lt;/span&gt; CombinedStyles.css&lt;br /&gt;csstidy.exe CombinedStyles.css &lt;span style="color: rgb(128, 128, 48);"&gt;-&lt;/span&gt;&lt;span style="color: rgb(128, 128, 48);"&gt;-&lt;/span&gt;template&lt;span style="color: rgb(128, 128, 48);"&gt;=&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;high&lt;/span&gt; CombinedStyles.minified.css&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;copy&lt;/span&gt; CombinedStyles.minified.css &lt;span style="color: rgb(0, 0, 230);"&gt;"..\Web Sites\Site\CSS\CombinedStyles.minified.css"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(105, 105, 105);"&gt;::Remove the temporary files&lt;/span&gt;&lt;span style="font-family: mon;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;del&lt;/span&gt; *.js&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;del&lt;/span&gt; *.css&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(105, 105, 105);"&gt;::Restore the old "current directory"&lt;/span&gt; &lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(128, 0, 0);"&gt;chdir&lt;/span&gt; &lt;span style="color: rgb(128, 128, 48);"&gt;/&lt;/span&gt;d %OLDDIR%&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The one part of the batch file that confuses most people is the FOR /F "token=*" statement. That reads in a line at a time from the file specified in brackets and puts it in the %%f variable. The contents of each file is then appended into a single file using a "type SourceFile &amp;gt;&amp;gt; DestinationFile" statement. In the case of the JavaScript files they are then piped through the Jazmin compressor/minifier, the output of which is redirected in an output file, i.e. AdminCombined.minified.js. With the CSS files, the command line syntax is a little different, but the outcome is the same.&lt;/p&gt;
&lt;p&gt;Hopefully the rest of the batch file is pretty self evident and there is enough information here to get you started on implementing the approach yourself. If there are areas that need more explanation please leave a comment on the blog post.&lt;/p&gt;&lt;img src="http://ridgway.co.za/aggbug/193.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2008/01/28/setting-up-an-optimised-deployment-version-of-your-ajax-asp.net.aspx</guid>
            <pubDate>Mon, 28 Jan 2008 04:02:57 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2008/01/28/setting-up-an-optimised-deployment-version-of-your-ajax-asp.net.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/193.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Using ASP.Net AJAX WebServices (ScriptServices) in ExtJS</title>
            <link>http://ridgway.co.za/archive/2007/10/09/using-asp.net-ajax-webservices-scriptservices-in-extjs.aspx</link>
            <description>I've only just started investigating &lt;a href="http://extjs.com/"&gt;ExtJS&lt;/a&gt; and what it can possibly provide over and above the ASP.Net AJAX framework. The first thing I wanted to do was use the ASP.Net AJAX JavaScript webservice proxies instead of the expected REST style services. Unfortunately I ran into several problems and ended up using a slightly different approach to what I found on the &lt;a href="http://extjs.com/forum" target="_blank"&gt;ExtJS forums&lt;/a&gt;. Let me quickly outline the problem. In ExtJS they use a store wrapper for their data which is assigned to a grid panel. This store object may also know how to fetch external data that it needs via a proxy, which is defined like so:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;ds &lt;/font&gt;&lt;font color="blue"&gt;= new &lt;/font&gt;&lt;font color="black"&gt;Ext.data.Store({&lt;br /&gt;
    proxy: &lt;/font&gt;&lt;font color="blue"&gt;new &lt;/font&gt;&lt;font color="black"&gt;Ext.data.HttpProxy(&lt;br /&gt;
         {&lt;br /&gt;
          url: &lt;/font&gt;&lt;font color="#808080"&gt;'/WebServices/OrderService.asmx/GetOrders'&lt;/font&gt;&lt;font color="black"&gt;,&lt;br /&gt;
          params: { userId: getUserId(), day: &lt;/font&gt;&lt;font color="blue"&gt;new Date&lt;/font&gt;&lt;font color="black"&gt;() }&lt;br /&gt;
         }),&lt;br /&gt;
    reader: &lt;/font&gt;&lt;font color="blue"&gt;new &lt;/font&gt;&lt;font color="black"&gt;Ext.data.JsonReader(&lt;br /&gt;
        {&lt;br /&gt;
           id: &lt;/font&gt;&lt;font color="#808080"&gt;'WorkDoneId'&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
    ...&lt;br /&gt;
})&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
Unfortunately, try as I might to get this to call my web service (and I tried quite a few different approaches), I would get errors returned by the service. It may have been that unlike all the examples I had seen on the web, like &lt;a target="_blank" href="http://daniellarson.spaces.live.com/blog/cns!D3543C5837291E93!966.entry"&gt;Daniel Larson's&lt;/a&gt; my service calls actually needed to send parameters through to the service. One was to add additional properties to the ScriptMethod attribute on the web service like so:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="black"&gt;[ScriptMethod(ResponseFormat &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;ResponseFormat.Json, UseHttpGet &lt;/font&gt;&lt;font color="blue"&gt;= true&lt;/font&gt;&lt;font color="black"&gt;, XmlSerializeString &lt;/font&gt;&lt;font color="blue"&gt;= false&lt;/font&gt;&lt;font color="black"&gt;)]&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
I also tried using the ASPProxy class found on &lt;a href="http://extjs.com/forum/showthread.php?t=8587&amp;amp;highlight=asp+webservice+ajax"&gt;this forum post&lt;/a&gt;. This also didn't work properly and there were a few minor irritations with the code. It all seemed pretty silly since with the ScriptManager service reference I had a client side proxy that I knew would work properly. So I created the AspWebServiceProxy object that would allow you to simply pass in a reference to the client side web service proxy object and method and use that:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="black"&gt;AspWebServiceProxy &lt;/font&gt;&lt;font color="blue"&gt;= function &lt;/font&gt;&lt;font color="black"&gt;(conn)&lt;br /&gt;
           {&lt;br /&gt;
              AspWebServiceProxy.superclass.constructor.call(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
              &lt;/font&gt;&lt;font color="black"&gt;Ext.apply(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;, conn)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
           &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;Ext.extend(AspWebServiceProxy, Ext.data.DataProxy, &lt;br /&gt;
{&lt;br /&gt;
     load : &lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;(params, reader, callback, scope, arg)&lt;br /&gt;
            {&lt;br /&gt;
               &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;userContext &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;{&lt;br /&gt;
                                    callback: callback, &lt;br /&gt;
                                    reader: reader, &lt;br /&gt;
                                    arg: arg, &lt;br /&gt;
                                    scope: scope&lt;br /&gt;
                                 }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
               &lt;br /&gt;
               var &lt;/font&gt;&lt;font color="black"&gt;proxyWrapper &lt;/font&gt;&lt;font color="blue"&gt;= this;&lt;br /&gt;
               &lt;br /&gt;
               &lt;/font&gt;&lt;font color="darkgreen"&gt;//Handles the response we get back from the web service call&lt;br /&gt;
               &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;webServiceCallback &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;(response) &lt;br /&gt;
                                        { &lt;br /&gt;
                                            proxyWrapper.loadResponse(response, userContext)&lt;/font&gt;&lt;font color="blue"&gt;; &lt;br /&gt;
                                        &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
               &lt;br /&gt;
               &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;serviceParams &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;[]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
               &lt;br /&gt;
               &lt;/font&gt;&lt;font color="darkgreen"&gt;//Convert the params into an array of values so that they can be used in the call (note assumes that the properties on the object are in the correct order)&lt;br /&gt;
               &lt;/font&gt;&lt;font color="blue"&gt;for &lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;property &lt;/font&gt;&lt;font color="blue"&gt;in &lt;/font&gt;&lt;font color="black"&gt;params)&lt;br /&gt;
               {&lt;br /&gt;
                  serviceParams.push(&lt;/font&gt;p&lt;font color="black"&gt;arams[property])&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
               &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
               &lt;br /&gt;
               &lt;/font&gt;&lt;font color="darkgreen"&gt;//Add the webservice callback handlers&lt;br /&gt;
               &lt;/font&gt;&lt;font color="black"&gt;serviceParams.push(webServiceCallback)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
               &lt;/font&gt;&lt;font color="black"&gt;serviceParams.push(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.handleErrorResponse)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
               &lt;br /&gt;
               &lt;/font&gt;&lt;font color="darkgreen"&gt;//Make the actual ASP.Net web service call&lt;br /&gt;
               &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.webServiceProxyMethod.apply(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.webServiceProxy, serviceParams)&lt;/font&gt;&lt;font color="blue"&gt;; &lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
            &lt;br /&gt;
     handleErrorResponse : &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;(response, userContext, &lt;/font&gt;&lt;font color="black"&gt;methodName&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
                           {&lt;br /&gt;
                              &lt;/font&gt;&lt;font color="blue"&gt;alert&lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="#808080"&gt;"Error while calling web service method:&lt;/font&gt;&lt;font color="#808080"&gt;" + &lt;/font&gt;&lt;font color="black"&gt;methodName +&lt;/font&gt;&lt;font color="#808080"&gt; "\n" &lt;/font&gt;&lt;font color="black"&gt;+ &lt;/font&gt;&lt;font color="black"&gt;response&lt;/font&gt;&lt;font color="black"&gt;.get_message())&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
                           &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
 &lt;br /&gt;
     loadResponse : &lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;(response, userContext, methodName)&lt;br /&gt;
                    {&lt;br /&gt;
                        &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;result &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;userContext.reader.readRecords(response)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
                        &lt;/font&gt;&lt;font color="black"&gt;userContext.callback.call(userContext.scope, result, userContext.arg, &lt;/font&gt;&lt;font color="blue"&gt;true&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
                    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
        &lt;br /&gt;
})&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
So if you had an ASP.Net web service script reference on your page, like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;asp:ScriptManager&lt;/font&gt;&lt;font color="red"&gt; ID&lt;/font&gt;&lt;font color="blue"&gt;="PageScriptManager"&lt;/font&gt;&lt;font color="red"&gt; runat&lt;/font&gt;&lt;font color="blue"&gt;="server"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;Services&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;asp:ServiceReference&lt;/font&gt;&lt;font color="red"&gt; Path&lt;/font&gt;&lt;font color="blue"&gt;="/WebServices/OrderService.asmx"&lt;/font&gt;&lt;font color="red"&gt; InlineScript&lt;/font&gt;&lt;font color="blue"&gt;="false"&lt;/font&gt;&lt;font color="red"&gt; &lt;/font&gt;&lt;font color="blue"&gt;/&amp;gt;&lt;br /&gt;
    &amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;Services&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;asp:ScriptManager&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
to use the proxy class one would change the code at the start of the article to look like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;  &lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;ds &lt;/font&gt;&lt;font color="blue"&gt;= new &lt;/font&gt;&lt;font color="black"&gt;Ext.data.Store({&lt;br /&gt;
    proxy: &lt;/font&gt;&lt;font color="blue"&gt;new &lt;/font&gt;&lt;font color="black"&gt;AspWebServiceProxy(&lt;br /&gt;
         {&lt;br /&gt;
          webServiceProxy: Example.OrderService,&lt;br /&gt;
          webServiceProxyMethod: Example.OrderService.GetOrders,&lt;br /&gt;
          params: {userId: getUserId(), day: &lt;/font&gt;&lt;font color="blue"&gt;new Date&lt;/font&gt;&lt;font color="black"&gt;()}&lt;br /&gt;
         }),&lt;br /&gt;
    reader: &lt;/font&gt;&lt;font color="blue"&gt;new &lt;/font&gt;&lt;font color="black"&gt;Ext.data.JsonReader(&lt;br /&gt;
        {&lt;br /&gt;
           id: &lt;/font&gt;&lt;font color="#808080"&gt;'WorkDoneId'&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
    ...&lt;br /&gt;
})&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
I'm sure that I'll be tweaking the AspWebServiceProxy object over time as I discover its short comings, but at least it is a decent start and is hopefully useful to others as well. One of my concerns are the manner in which the attributes on the extraParams object must be specified in the same order as the web service method parameters. I did it this way to keep it consistent with all the other examples I had seen where they used an object as opposed to an array. I may change this, but I like the fact that with the current approach the parameter value pairs are obvious.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: rgb(255, 0, 0);"&gt;Update - 2 Nov 2007: Changed the service options of extraParams to params. So now one can use dataStore.load({params: {userId: 4, day: new Date()} }) to load data after the creation of the data source.&lt;/span&gt;&lt;img src="http://ridgway.co.za/aggbug/186.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2007/10/09/using-asp.net-ajax-webservices-scriptservices-in-extjs.aspx</guid>
            <pubDate>Tue, 09 Oct 2007 05:19:34 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2007/10/09/using-asp.net-ajax-webservices-scriptservices-in-extjs.aspx#feedback</comments>
            <slash:comments>20</slash:comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/186.aspx</wfw:commentRss>
        </item>
        <item>
            <title>A Simple Dojo Charting Example</title>
            <link>http://ridgway.co.za/archive/2007/04/13/A-Simple-Dojo-Charting-Example.aspx</link>
            <description>&lt;p&gt;When evaluating the &lt;a href="http://dojotoolkit.org/" target="_blank"&gt;Dojo Charting library&lt;/a&gt; as an option for my CruiseControl statistics page replacement it was very evident that the Dojo team hadn't gotten around to providing documentation for this donated library.  If you are unfamiliar with what the features the library offers you should take a look at this &lt;a href="http://ajaxian.com/archives/dojo-charting-engine-released" target="_blank"&gt;Ajaxian post&lt;/a&gt;.  There is also a &lt;a href="http://archive.dojotoolkit.org/nightly/charting/tests/charting/test_engine.html"&gt;test page&lt;/a&gt; for the library which I could have sworn was down a day or two ago.&lt;/p&gt;
&lt;p&gt;In the interest of possibly helping others save some time getting into the chrting library I wanted to post a basic introductory example.  Please be aware that I do not know this library in depth, nor have I worked with the Dojo libraries extensively.&lt;/p&gt;
&lt;p&gt;What is great about the Dojo charting implementation is that it is very versatile.  This however comes at the cost of a slightly more involved structure which makes it somewhat more tedious to use than &lt;a href="http://www.liquidx.net/plotkit/" target="_blank"&gt;PlotKit&lt;/a&gt;.  The composition of the various graphing objects is illustrated in the diagram below.  As you can see from the relationships in the diagram they have allowed for features such as the ability to render multiple different graphs, using different plotters, in one plot area.  They also have different implementations of the Axis, PlotArea and Plotter objects for VML and SVG rendering.&lt;/p&gt;
&lt;p align="center"&gt;&lt;a href="http://www.flickr.com/photos/47913250@N00/457296586/" target="_blank" title="Photo Sharing"&gt;&lt;img width="461" height="391" border="0" src="http://farm1.static.flickr.com/216/457296586_b45eb89c0d_o.gif" alt="Dojo Charting Diargam" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;The Example&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So to create a graph one would start off by including a reference to the dojo library and the required namespaces:&lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/javascript"&lt;/font&gt;&lt;font color="#ff0000"&gt; src&lt;/font&gt;&lt;font color="#0000ff"&gt;="dojo/dojo.js"&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#ff0000"&gt; type&lt;/font&gt;&lt;font color="#0000ff"&gt;="text/javascript"&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Include the required dojo libraries/namespaces&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;dojo.require(&lt;/font&gt;&lt;font color="#808080"&gt;"dojo.collections.Store"&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;dojo.require(&lt;/font&gt;&lt;font color="#808080"&gt;"dojo.charting.Chart"&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;dojo.require(&lt;/font&gt;&lt;font color="#808080"&gt;'dojo.json'&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/&lt;/font&gt;&lt;font color="#800000"&gt;script&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;You then define or retrieve the graph data and store it in the collection store.  This then will be fed into your graph as a series, defined like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;&lt;font color="#000000"&gt;exampleData &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;[&lt;br /&gt;
    { time: &lt;/font&gt;&lt;font color="#800000"&gt;10&lt;/font&gt;&lt;font color="#000000"&gt;, count: &lt;/font&gt;&lt;font color="#800000"&gt;7382 &lt;/font&gt;&lt;font color="#000000"&gt;},&lt;br /&gt;
    { time: &lt;/font&gt;&lt;font color="#800000"&gt;20&lt;/font&gt;&lt;font color="#000000"&gt;, count: &lt;/font&gt;&lt;font color="#800000"&gt;1852 &lt;/font&gt;&lt;font color="#000000"&gt;},&lt;br /&gt;
    { time: &lt;/font&gt;&lt;font color="#800000"&gt;35&lt;/font&gt;&lt;font color="#000000"&gt;, count: &lt;/font&gt;&lt;font color="#800000"&gt;2397 &lt;/font&gt;&lt;font color="#000000"&gt;},&lt;br /&gt;
    { time: &lt;/font&gt;&lt;font color="#800000"&gt;50&lt;/font&gt;&lt;font color="#000000"&gt;, count: &lt;/font&gt;&lt;font color="#800000"&gt;1442 &lt;/font&gt;&lt;font color="#000000"&gt;},&lt;br /&gt;
    { time: &lt;/font&gt;&lt;font color="#800000"&gt;55&lt;/font&gt;&lt;font color="#000000"&gt;, count: &lt;/font&gt;&lt;font color="#800000"&gt;1854 &lt;/font&gt;&lt;font color="#000000"&gt;}&lt;br /&gt;
]&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
var &lt;/font&gt;&lt;font color="#000000"&gt;store &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.collections.Store()&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;store.setData(exampleData)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
var &lt;/font&gt;&lt;font color="#000000"&gt;timeSeries &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.charting.Series({&lt;br /&gt;
                                dataSource: store,&lt;br /&gt;
                                bindings: { x: &lt;/font&gt;&lt;font color="#808080"&gt;"time"&lt;/font&gt;&lt;font color="#000000"&gt;, y: &lt;/font&gt;&lt;font color="#808080"&gt;"count" &lt;/font&gt;&lt;font color="#000000"&gt;},&lt;br /&gt;
                                label: &lt;/font&gt;&lt;font color="#808080"&gt;"Example Series"&lt;br /&gt;
                            &lt;/font&gt;&lt;font color="#000000"&gt;})&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;Next come the axis definitions where you can specify the data display range, data source and the tick labels:&lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#006400"&gt;//Define the x-axis&lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;&lt;font color="#000000"&gt;xAxis &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.charting.Axis()&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Set the upper and lower data range values&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;xAxis.range &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;{ lower: exampleData[&lt;/font&gt;&lt;font color="#800000"&gt;0&lt;/font&gt;&lt;font color="#000000"&gt;].time, upper: exampleData[exampleData.length-&lt;/font&gt;&lt;font color="#800000"&gt;1&lt;/font&gt;&lt;font color="#000000"&gt;].time }&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;xAxis.origin &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#808080"&gt;"max"&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;xAxis.showTicks &lt;/font&gt;&lt;font color="#0000ff"&gt;= true;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;xAxis.label &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#808080"&gt;"Example chart"&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Setup the x tick marks on the chart&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;xAxis.labels &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;[ &lt;br /&gt;
                    { label: &lt;/font&gt;&lt;font color="#808080"&gt;'First'&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;20 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                    { label: &lt;/font&gt;&lt;font color="#808080"&gt;'Second'&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;25 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                    { label: &lt;/font&gt;&lt;font color="#808080"&gt;'Third'&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;35 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                    { label: &lt;/font&gt;&lt;font color="#808080"&gt;'Fourth'&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;50 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                    { label: &lt;/font&gt;&lt;font color="#808080"&gt;'Fifth'&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;55 &lt;/font&gt;&lt;font color="#000000"&gt;}&lt;br /&gt;
               ]&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
               &lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Define the y-axis&lt;br /&gt;
&lt;/font&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;&lt;font color="#000000"&gt;yAxis &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.charting.Axis()&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;yAxis.range &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;{ lower: &lt;/font&gt;&lt;font color="#800000"&gt;0&lt;/font&gt;&lt;font color="#000000"&gt;, upper: &lt;/font&gt;&lt;font color="#800000"&gt;5000 &lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;yAxis.showLines &lt;/font&gt;&lt;font color="#0000ff"&gt;= true;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;yAxis.showTicks &lt;/font&gt;&lt;font color="#0000ff"&gt;= true;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;yAxis.label &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#808080"&gt;"Time Taken"&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
   &lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Setup the y tick marks on the chart&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;yAxis.labels &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;[ &lt;br /&gt;
                  { label: &lt;/font&gt;&lt;font color="#808080"&gt;"0s"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;0 &lt;/font&gt;&lt;font color="#000000"&gt;},&lt;br /&gt;
                  { label: &lt;/font&gt;&lt;font color="#808080"&gt;"1s"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;1000 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                  { label: &lt;/font&gt;&lt;font color="#808080"&gt;"2s"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;2000 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                  { label: &lt;/font&gt;&lt;font color="#808080"&gt;"3s"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;3000 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                  { label: &lt;/font&gt;&lt;font color="#808080"&gt;"4s"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;4000 &lt;/font&gt;&lt;font color="#000000"&gt;}, &lt;br /&gt;
                  { label: &lt;/font&gt;&lt;font color="#808080"&gt;"5s"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;font color="#000000"&gt;: &lt;/font&gt;&lt;font color="#800000"&gt;5000 &lt;/font&gt;&lt;font color="#000000"&gt;} &lt;br /&gt;
               ]&lt;/font&gt;&lt;font color="#0000ff"&gt;;    &lt;/font&gt; &lt;/div&gt;
&lt;p&gt;You then define how the data will be plotted by defining a Plot and assigning the series with a plotter to render it: &lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;&lt;font color="#000000"&gt;chartPlot &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.charting.Plot(xAxis, yAxis)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;chartPlot.addSeries({ &lt;br /&gt;
                data: timeSeries, &lt;br /&gt;
                plotter: dojo.charting.Plotters.CurvedArea &lt;br /&gt;
              })&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;This then needs to be rendered into a specific area, so one defines the PlotArea and adds the Plot to it: &lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;&lt;font color="#000000"&gt;chartPlotArea &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.charting.PlotArea()&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;chartPlotArea.size &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;{ width: &lt;/font&gt;&lt;font color="#800000"&gt;380&lt;/font&gt;&lt;font color="#000000"&gt;, height: &lt;/font&gt;&lt;font color="#800000"&gt;170 &lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;chartPlotArea.padding &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;{ top: &lt;/font&gt;&lt;font color="#800000"&gt;20&lt;/font&gt;&lt;font color="#000000"&gt;, right: &lt;/font&gt;&lt;font color="#800000"&gt;20&lt;/font&gt;&lt;font color="#000000"&gt;, bottom: &lt;/font&gt;&lt;font color="#800000"&gt;30&lt;/font&gt;&lt;font color="#000000"&gt;, left: &lt;/font&gt;&lt;font color="#800000"&gt;50 &lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Add the plot to the area &lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;chartPlotArea.plots.push(chartPlot)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;Finally one needs to create the chart and add the PlotArea to it.  The chart also needs to have a container element, which one assigns to the chart.node.&lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="#0000ff"&gt;var &lt;/font&gt;&lt;font color="#000000"&gt;chart &lt;/font&gt;&lt;font color="#0000ff"&gt;= new &lt;/font&gt;&lt;font color="#000000"&gt;dojo.charting.Chart(&lt;/font&gt;&lt;font color="#0000ff"&gt;null&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#808080"&gt;"Example chart"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#808080"&gt;"This is the example chart description"&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Add the plot area at an offset of 10 pixels from the top left&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;chart.addPlotArea({ x: &lt;/font&gt;&lt;font color="#800000"&gt;10&lt;/font&gt;&lt;font color="#000000"&gt;, y: &lt;/font&gt;&lt;font color="#800000"&gt;10&lt;/font&gt;&lt;font color="#000000"&gt;, plotArea: chartPlotArea })&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="#006400"&gt;//Setup the chart to be added to the DOM on load&lt;br /&gt;
&lt;/font&gt;&lt;font color="#000000"&gt;dojo.addOnLoad(&lt;/font&gt;&lt;font color="#0000ff"&gt;function&lt;/font&gt;&lt;font color="#000000"&gt;()&lt;br /&gt;
               {&lt;br /&gt;
                   chart.node &lt;/font&gt;&lt;font color="#0000ff"&gt;= &lt;/font&gt;&lt;font color="#000000"&gt;dojo.byId(&lt;/font&gt;&lt;font color="#808080"&gt;"GraphContainerArea"&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
                   &lt;/font&gt;&lt;font color="#000000"&gt;chart.render()&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;
               &lt;/font&gt;&lt;font color="#000000"&gt;})&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt; &lt;/div&gt;
&lt;p&gt;And voila, you have a graph that looks like this:&lt;/p&gt;
&lt;p align="center"&gt;&lt;a href="http://www.flickr.com/photos/47913250@N00/457296570/" target="_blank" title="Photo Sharing"&gt;&lt;img width="409" height="199" border="0" src="http://farm1.static.flickr.com/175/457296570_3c9e315e32_o.jpg" alt="Dojo Graph Example" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To see the graph in action, take a look at this &lt;a href="http://www.ridgway.co.za/demos/DojoChartExample/DemoDojoGraph.html" target="_blank"&gt;demo page&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://ridgway.co.za/aggbug/182.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2007/04/13/A-Simple-Dojo-Charting-Example.aspx</guid>
            <pubDate>Fri, 13 Apr 2007 05:14:08 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2007/04/13/A-Simple-Dojo-Charting-Example.aspx#feedback</comments>
            <slash:comments>9</slash:comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/182.aspx</wfw:commentRss>
        </item>
        <item>
            <title>CruiseControl.Net Statistics Graphs using PlotKit</title>
            <link>http://ridgway.co.za/archive/2007/03/27/181.aspx</link>
            <description>[&lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt;: This does not apply to the Dojo Toolkit vesion of the Statistics Plugin.  For information on how to customize that version go to this &lt;a href="http://ridgway.co.za/archive/2007/05/21/adding-custom-graphs-to-the-cruisecontrol.net-statistics-replacement.aspx"&gt;page&lt;/a&gt;.] &lt;br /&gt;
&lt;br /&gt;
As promised in my previous post, &lt;a href="http://ridgway.co.za/archive/2007/03/23/180.aspx"&gt;CruiseControl Statistics Graphs&lt;/a&gt;, here is a high level description of the implementation  that allowed me to display graphs in CruiseControl.Net.  I've also included a quick guide on how to extend the report to include your own custom statistics that you may have published as part of your build.&lt;br /&gt;
&lt;br /&gt;
After I had decided to create a graphical view of the CruiseControl statistics I assessed various options that were available.  My immediate thoughts were to use XSLT to create either SVG or VML graphs.  The problem is that I wanted something that was quick and easy to implement and quite frankly the effort required to do all of this using xslt was just too great.  My attentions then turned to doing the majority of the processing in JavaScript.  The Dojo Charting library was the first solution that sprung to mind, but on further investigation is appeared to be undergoing some restructuring and the documentation is almost non-existent.  It was then that I came across &lt;a href="http://www.liquidx.net/plotkit/"&gt;PlotKit&lt;/a&gt;, a cross browser charting framework built on top of MochiKit.  It was simple and had documentation so it was a clear winner.&lt;br /&gt;
&lt;br /&gt;
So the Statistics Graph solution ended up being structured as follows:&lt;br /&gt;
&lt;ol&gt;
    &lt;li&gt;StatisticsGraphs.xsl - creates JSON representation of the detailed stats data and the general page structure&lt;/li&gt;
    &lt;li&gt;StatisticsGraphs.js - contains the logic to summarise the detailed stats data and to create the plotkit graphs and tables&lt;/li&gt;
    &lt;li&gt;MochiKit_lite_packed.js, PlotKit_Packed.js - packed versions of the libraries that provide the graphing functionality (from PlotKit)&lt;/li&gt;
    &lt;li&gt;excanvas.js - provides canvas emulation for Internet Explorer (from PlotKit)&lt;/li&gt;
&lt;/ol&gt;
If one wanted to create their own custom summary graph of new statistics on the page (for more info on including custom statistics see &lt;a href="http://www.kiwidude.com/blog/2006/10/ccstatistics-for-cruisecontrolnet-11.html"&gt;Grant Drake's blog post&lt;/a&gt;), you would open up StatisticsGraphs.js and do the following:&lt;br /&gt;
&lt;ol&gt;
    &lt;li&gt;Edit the generateDailySummaries function and add your summarised statistic to daySummary&lt;br /&gt;
    &lt;br /&gt;
    &lt;div class="code"&gt; &lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;daySummary &lt;/font&gt;&lt;font color="blue"&gt;= &lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;{&lt;br /&gt;
    day : day,&lt;br /&gt;
    successfulBuildCount : count(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"Status"&lt;/font&gt;&lt;font color="black"&gt;, &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;(item) { &lt;/font&gt;&lt;font color="blue"&gt;return &lt;/font&gt;&lt;font color="black"&gt;(item[&lt;/font&gt;&lt;font color="#808080"&gt;"Status"&lt;/font&gt;&lt;font color="black"&gt;] &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="#808080"&gt;"Success"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;}),&lt;br /&gt;
    failedBuildCount : count(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"Status"&lt;/font&gt;&lt;font color="black"&gt;, &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;(item) { &lt;/font&gt;&lt;font color="blue"&gt;return &lt;/font&gt;&lt;font color="black"&gt;(item[&lt;/font&gt;&lt;font color="#808080"&gt;"Status"&lt;/font&gt;&lt;font color="black"&gt;] &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="#808080"&gt;"Failure"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;}),&lt;br /&gt;
    lastBuildLabel : getLastValue(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"BuildLabel"&lt;/font&gt;&lt;font color="black"&gt;),&lt;br /&gt;
    testCount : testCount,&lt;br /&gt;
    testsPassed : testCount - testFailures - testsIgnored,&lt;br /&gt;
    testFailures : testFailures,&lt;br /&gt;
    testsIgnored : testsIgnored,&lt;br /&gt;
    fxCopWarnings : average(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"FxCop Warnings"&lt;/font&gt;&lt;font color="black"&gt;),&lt;br /&gt;
    fxCopErrors : average(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"FxCop Errors"&lt;/font&gt;&lt;font color="black"&gt;),&lt;br /&gt;
    averageBuildDuration: average(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"Duration"&lt;/font&gt;&lt;font color="black"&gt;),&lt;br /&gt;
    minBuildDuration: min(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"Duration"&lt;/font&gt;&lt;font color="black"&gt;),&lt;br /&gt;
    maxBuildDuration: max(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"Duration"&lt;/font&gt;&lt;font color="black"&gt;),&lt;br /&gt;
    &lt;br /&gt;
    &lt;/font&gt;&lt;font color="darkgreen"&gt;//Insert new summarised statistics here&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;averageCodeCoverage : average(currentStatistics, &lt;/font&gt;&lt;font color="#808080"&gt;"CodeCoverage"&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
    }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
    &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt; Create a new function to create the graph.  Note that the createGraph function creates the title, graph and legend for you. eg.&lt;br /&gt;
    &lt;br /&gt;
    &lt;div class="code"&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;createCodeCoverageGraph()&lt;br /&gt;
    {&lt;br /&gt;
    createGraph({&lt;br /&gt;
    graphName : &lt;/font&gt;&lt;font color="#808080"&gt;"Average Daily Code Coverage"&lt;/font&gt;&lt;font color="black"&gt;,&lt;br /&gt;
    series : [&lt;br /&gt;
    { &lt;br /&gt;
    name : &lt;/font&gt;&lt;font color="#808080"&gt;"Average Code Coverage"&lt;/font&gt;&lt;font color="black"&gt;, &lt;br /&gt;
    attributeName: &lt;/font&gt;&lt;font color="#808080"&gt;"averageCodeCoverage"&lt;/font&gt;&lt;font color="black"&gt;, &lt;br /&gt;
    color : Color.greenColor() &lt;br /&gt;
    }&lt;br /&gt;
    ]&lt;br /&gt;
    })&lt;br /&gt;
    } &lt;/font&gt; 	&lt;/div&gt;
    &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt; Then call your new function in the setupGraphs&lt;br /&gt;
    &lt;br /&gt;
    &lt;div class="code"&gt; &lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;setupGraphs()&lt;br /&gt;
    {&lt;br /&gt;
    createBuildReportGraph()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;createBuildDurationGraph()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;createTestGraph()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;createFxCopGraph()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;br /&gt;
    &lt;/font&gt;&lt;font color="darkgreen"&gt;//Insert calls to functions that create new graphs here&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;createCodeCoverageGraph()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;/div&gt;
    &lt;/li&gt;
&lt;/ol&gt;
So if you are keen to give it a go take a look at my &lt;a href="http://ridgway.co.za/archive/2007/03/27/180.aspx"&gt;previous post&lt;/a&gt; for the download.&lt;img src="http://ridgway.co.za/aggbug/181.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2007/03/27/181.aspx</guid>
            <pubDate>Tue, 27 Mar 2007 07:23:42 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2007/03/27/181.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/181.aspx</wfw:commentRss>
        </item>
        <item>
            <title>HTMLElement Prototype for Internet Explorer</title>
            <link>http://ridgway.co.za/archive/2005/11/25/htmlelementprototypeforinternetexplorer.aspx</link>
            <description>&lt;p&gt;
You most likely know that since HTML Elements in Internet Explorer are wrappers around
COM objects, you can't use  HTMLElement.prototype, unlike Firefox (or another
Mozilla based browser).  &lt;a href="http://www.jasonkarldavis.com/"&gt;Jason Davis&lt;/a&gt; has
a presented a solution to this in his post, &lt;a href="http://blog.codingforums.com/index.php/main/blogentry/element_prototyping_in_internet_explorer_55_and_above/"&gt;Element
Prototyping in Internet Explorer 5.5 and above&lt;/a&gt;, where he used a behavior to provide
this missing functionality.
&lt;/p&gt;
&lt;p&gt;
It would appear that there is a &lt;a href="http://dotnetjunkies.com/WebLog/kmotion/archive/2004/12/08/35627.aspx"&gt;memory
leak&lt;/a&gt; and &lt;a href="http://www.aplus.co.yu/adxmenu/csshoverhtc-and-ie-freeze/"&gt;possible
performance issues&lt;/a&gt; (which I was not aware of) with the use of behaviors,
so way up your options carefully before employing this approach.
&lt;/p&gt;
&lt;img src="http://ridgway.co.za/aggbug/154.aspx" width="1" height="1" /&gt;</description>
            <guid>http://ridgway.co.za/archive/2005/11/25/htmlelementprototypeforinternetexplorer.aspx</guid>
            <pubDate>Fri, 25 Nov 2005 01:47:21 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/11/25/htmlelementprototypeforinternetexplorer.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/154.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Dynamic Javascript Image Generation with XBM Images</title>
            <link>http://ridgway.co.za/archive/2005/11/13/dynamicjavascriptimagegenerationwithxbmimages.aspx</link>
            <description>&lt;p&gt; While browsing the net I came across a code example that looked like this: &lt;/p&gt;
&lt;code&gt;&lt;/code&gt;
&lt;pre&gt;&lt;font face="Courier New"&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;script&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &lt;/strong&gt;&lt;/font&gt;var&lt;br /&gt;icon = '#define icon_width 4\n#define icon_height 4\nstatic char icon_bits[] = { 0x05,&lt;br /&gt;0x0A, 0x05, 0x0A };'; &lt;font color="#808080"&gt;&lt;strong&gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/script&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;img &lt;/strong&gt;&lt;/font&gt;&lt;font color="#000080"&gt;&lt;strong&gt;src&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;=&lt;/strong&gt;&lt;/font&gt;&lt;font color="#800000"&gt;"javascript:icon;"&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt; &lt;/pre&gt;
&lt;p&gt; Not having seen anything like this before, I did some more digging to discover that the icon was in fact an &lt;a href="http://en.wikipedia.org/wiki/XBM"&gt;XBM&lt;/a&gt; image definition.  I was quite excited at the prospect of being able to dynamically generate images in a browser client only to discover that as of Windows XP SP2, XBM images no longer render in IE by default (source: &lt;a href="http://karma.nucleuscms.org/item/66/catid/9"&gt;Karma's Nucleus Dev Blog&lt;/a&gt;).  You can however override this by setting the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Security BlockXBM dword value to zero.  Here is a registry file to make things a little easier: &lt;a href="http://www.ridgway.co.za/Images/UnblockXBM.zip"&gt;UnblockXBM.zip&lt;/a&gt;.  After applying this registry change, reboot your machine. &lt;/p&gt;
&lt;p&gt; An incredible showcase of what can be achieved using dynamic XBM image generation can be found at the &lt;a href="http://www.wolf5k.com/"&gt;Wolfenstein 5K site&lt;/a&gt;.  It's actually one of the most impressive things I've seen on the web for ages (pity about the performance though).  There is also a &lt;a href="http://david.blackledge.com/XBMDrawLibrary.html"&gt;XBM Image Creation Library for JavaScript&lt;/a&gt; available to ease generation of these images. &lt;/p&gt;
&lt;p&gt; I also found a rather interesting &lt;a href="http://karma.nucleuscms.org/experiments/ImageAsHtml/nucleuslogo.html"&gt;CSS &amp;amp; div based image rendering example&lt;/a&gt; on Karma's blog.   That must have taken quite some time to get right and I most certainly would not entertain using it as a way of effectively embedding your images in your client side controls/javascript. &lt;/p&gt;
&lt;p&gt; As a side note, XBM images do render in FireFox by default, so I wonder how they address the apparent security concerns with the C based image format.  However, since FireFox also supports the &lt;a href="http://www.faqs.org/rfcs/rfc2397.html"&gt;data url scheme&lt;/a&gt;, the XBM image support is a lot less important.  For those who don't know what I'm going on about, the data url scheme allows you to embed a base64 encoded image directly into your HTML like this: &lt;/p&gt;
&lt;code class="xml"&gt;&lt;/code&gt;
&lt;pre&gt;&amp;lt;img src="data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM/////&lt;br /&gt;wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4ML&lt;br /&gt;wWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="&lt;br /&gt;alt="Base64 encoded image" width="150" height="150"/&amp;gt; &lt;br /&gt;&lt;/pre&gt;
&lt;p&gt; In conclusion, it's a great sadness for me that the XBM format is no longer supported in IE.  If anyone knows of a way to generate a dynamic image from JavaScript in IE (not using VML or CSS) I'm all ears. &lt;/p&gt;
&lt;p&gt; Here are some more resources if you are interested:  &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt; &lt;a href="http://www.javaworld.com/jw-08-1996/jw-08-javascript-p3.html"&gt;Using JavaScript and graphics The easy way to make your images dynamic&lt;/a&gt;  &lt;/li&gt;
    &lt;li&gt; &lt;a href="http://www.icarusindie.com/DoItYourSelf/javascript3D/xbm.php"&gt;JavaScript 3D&lt;/a&gt;  &lt;/li&gt;
    &lt;li&gt; &lt;a href="http://www.sxlist.com/techref/language/java/script/dnyimgtst.htm"&gt;Inline Dynamic image test&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://ridgway.co.za/aggbug/153.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2005/11/13/dynamicjavascriptimagegenerationwithxbmimages.aspx</guid>
            <pubDate>Sun, 13 Nov 2005 01:56:57 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/11/13/dynamicjavascriptimagegenerationwithxbmimages.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/153.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Using CSS Expressions to Hook Up Event Handlers</title>
            <link>http://ridgway.co.za/archive/2005/11/08/usingcssexpressionstohookupeventhandlers.aspx</link>
            <description>/SubText/ImagesI cannot give the relevant author credit.  I just want to clearly state that this is not something that I discovered, but it is an interesting technique so I wanted to blog about it.  The downside of this approach is that it obfuscates the event wiring logic because most people won't look at the styles to find the logic. 
&lt;p&gt; It appears that IE will evaluate and execute a CSS expression even if the style property you are trying to set is invalid.  So if you were to define the following CSS style and markup, it will hookup &lt;strong&gt;mouseover&lt;/strong&gt;, &lt;strong&gt;mouseout&lt;/strong&gt; and &lt;strong&gt;onclick&lt;/strong&gt; event handlers for each TR within the table body and &lt;font color="#800000"&gt;AlternatingRowsTable &lt;/font&gt;css class.  This allows me to create a mouse rollover or "hover" effect on the TRs.  Note how it is being applied to the completely bogus &lt;font color="#ff0000"&gt;HookupEvent&lt;/font&gt; style attribute.  I could have called it XYZ and it still would have wired up the events for me. &lt;/p&gt;
&lt;code&gt;&lt;/code&gt;
&lt;pre&gt;&lt;font face="Courier New"&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;style &lt;/strong&gt;&lt;/font&gt;&lt;font color="#000080"&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;=&lt;/strong&gt;&lt;/font&gt;&lt;font color="#800000"&gt;"text/css"&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &lt;/strong&gt;&lt;/font&gt;.AlternatingRowsTable&lt;br /&gt;tbody TR { HookupEvents:expression(this.onmouseover=new Function("this.style.background='lightyellow';"),&lt;br /&gt;this.onmouseout =new Function("this.style.background='white';"), this.onclick=new&lt;br /&gt;Function("alert('Hello')")); } &lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/style&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;table &lt;/strong&gt;&lt;/font&gt;&lt;font color="#000080"&gt;&lt;strong&gt;class&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;=&lt;/strong&gt;&lt;/font&gt;&lt;font color="#800000"&gt;"AlternatingRowsTable" &lt;/font&gt;&lt;font color="#000080"&gt;&lt;strong&gt;style&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;=&lt;/strong&gt;&lt;/font&gt;&lt;font color="#800000"&gt;"width:50%" &lt;/font&gt;&lt;font color="#000080"&gt;&lt;strong&gt;ID&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;=&lt;/strong&gt;&lt;/font&gt;&lt;font color="#800000"&gt;"Table1"&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &lt;/strong&gt;&lt;/font&gt; &lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;thead&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;tr&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;th&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/font&gt;Col&lt;br /&gt;1&lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/th&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/tr&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/thead&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;tbody&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;tr&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;td&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/font&gt;Data&lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/td&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/tr&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;tr&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;td&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/font&gt;Data&lt;font color="#808080"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/td&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/tr&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/tbody&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/table&lt;/strong&gt;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;strong&gt;&amp;gt; &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;p&gt; And here is a demo of the technique (IE only): &lt;a href="/Images/ridgway_co_za/CssExpressionsEventHookup.htm"&gt;CssExpressionsEventHookup.htm&lt;/a&gt; &lt;/p&gt;
&lt;img src="http://ridgway.co.za/aggbug/152.aspx" width="1" height="1" /&gt;</description>
            <guid>http://ridgway.co.za/archive/2005/11/08/usingcssexpressionstohookupeventhandlers.aspx</guid>
            <pubDate>Tue, 08 Nov 2005 02:01:14 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/11/08/usingcssexpressionstohookupeventhandlers.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/152.aspx</wfw:commentRss>
        </item>
        <item>
            <title>A Simple CSS Based TreeView</title>
            <link>http://ridgway.co.za/archive/2005/10/30/asimplecssbasedtreeview.aspx</link>
            <description>/SubText/Imagesach is a reaction to this type of markup.  Ultimately one should use markup that reflects the type of information being presented.  Hence you have CSS menus that uses nested ordered/unordered lists since this HTML more accurately represents the type of information being displayed.  The same is true for treeviews, they are just nested lists of data and if one applied a little thought to the problem, it is quite easy to create a CSS based treeview solution. 
&lt;p&gt; I'm going to present a simple example of a CSS based treeview I recently wrote.  The markup below represents a two level treeview with a single nested list: &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="darkgreen"&gt;&amp;lt;!-- Level 1 nodes --&amp;gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;ul&lt;/font&gt;&lt;font color="red"&gt; class&lt;/font&gt;&lt;font color="blue"&gt;="TreeView"&lt;/font&gt;&lt;font color="red"&gt; id&lt;/font&gt;&lt;font color="blue"&gt;="TreeView"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
  &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;li&lt;/font&gt;&lt;font color="red"&gt; class&lt;/font&gt;&lt;font color="blue"&gt;="Collapsed"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; First level 1 node &lt;br /&gt;
  &lt;/font&gt;&lt;font color="darkgreen"&gt;&amp;lt;!-- level 2 nodes --&amp;gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;ul&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
      &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;li&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;First level 2 node&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;li&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
      &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;li&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;Second level 2 node&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;li&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;ul&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
  &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;li&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;ul&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; Without any CSS styling the information looks like this: &lt;/p&gt;
&lt;ul&gt;
    &lt;li class="Collapsed"&gt; First level 1 node  &lt;!-- level 2 nodes --&gt;
    &lt;ul&gt;
        &lt;li&gt; First level 2 node  &lt;/li&gt;
        &lt;li&gt; Second level 2 node  &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; Now by default I want the first level node to be collapsed with a plus image next to it, to indicate that the node can be expanded.  In order to achieve this we can get rid of the li symbols by making the list items float left.  This makes them stack up, so you can then set the elements to display at a 100% of the containing element.  We then want space to place our treeview expandable image, so we put in a left padding of 18px.  To make life simpler you can use a CSS child selector to apply this to all list elements within the treeview, like this: &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="blue"&gt;.&lt;/font&gt;&lt;font color="maroon"&gt;TreeView LI &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;{&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    padding&lt;/font&gt;&lt;font color="blue"&gt;: 0 0 0 18px;&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    float&lt;/font&gt;&lt;font color="blue"&gt;: left;&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    width&lt;/font&gt;&lt;font color="blue"&gt;: 100%;&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    list-style&lt;/font&gt;&lt;font color="blue"&gt;: none;&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;}&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; Adding the collpasing and expanding images and the associated effects to the child nodes is achieved with the following styles: &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;.&lt;/font&gt;&lt;font color="maroon"&gt;Expanded&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;{&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
    background&lt;/font&gt;&lt;font color="blue"&gt;: url(minus.gif) no-repeat left top;&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;}&lt;/font&gt;&lt;font color="maroon"&gt;&lt;br /&gt;
&lt;br /&gt;
LI&lt;/font&gt;&lt;font color="blue"&gt;.&lt;/font&gt;&lt;font color="maroon"&gt;Expanded ul&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;{&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
    display&lt;/font&gt;&lt;font color="blue"&gt;: block;&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;}&lt;/font&gt;&lt;font color="maroon"&gt;&lt;br /&gt;
&lt;br /&gt;
LI&lt;/font&gt;&lt;font color="blue"&gt;.&lt;/font&gt;&lt;font color="maroon"&gt;Collapsed &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;{&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
    background&lt;/font&gt;&lt;font color="blue"&gt;: url(plus.gif) no-repeat left top;&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;}&lt;/font&gt;&lt;font color="maroon"&gt;&lt;br /&gt;
&lt;br /&gt;
LI&lt;/font&gt;&lt;font color="blue"&gt;.&lt;/font&gt;&lt;font color="maroon"&gt;Collapsed ul&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;{&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
    display&lt;/font&gt;&lt;font color="blue"&gt;: none;&lt;/font&gt;&lt;font color="red"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;}&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; Then one needs to add JavaScript to the page to toggle the applied styles.  For this, I decided to go with an approach that could handle multiple styles being applied to a single element, so my solution is a little more complex than a simple className replacement approach: &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="blue"&gt;Array&lt;/font&gt;&lt;font color="black"&gt;.prototype.indexOf &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;IndexOf&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="darkgreen"&gt;//Toggles between two classes for an element&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;ToggleClass(element, firstClass, secondClass, &lt;/font&gt;&lt;font color="blue"&gt;event&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;event&lt;/font&gt;&lt;font color="black"&gt;.cancelBubble &lt;/font&gt;&lt;font color="blue"&gt;= true;&lt;br /&gt;
    &lt;br /&gt;
    var &lt;/font&gt;&lt;font color="black"&gt;classes &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;element.className.split(&lt;/font&gt;&lt;font color="#808080"&gt;" "&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    var &lt;/font&gt;&lt;font color="black"&gt;firstClassIndex &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;classes.indexOf(firstClass)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    var &lt;/font&gt;&lt;font color="black"&gt;secondClassIndex &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;classes.indexOf(secondClass)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;br /&gt;
    if &lt;/font&gt;&lt;font color="black"&gt;(firstClassIndex &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="black"&gt;-&lt;/font&gt;&lt;font color="maroon"&gt;1 &lt;/font&gt;&lt;font color="black"&gt;&amp;amp;&amp;amp; secondClassIndex &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="black"&gt;-&lt;/font&gt;&lt;font color="maroon"&gt;1&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
    {&lt;br /&gt;
        classes[classes.length] &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;firstClass&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;else if &lt;/font&gt;&lt;font color="black"&gt;(firstClassIndex !&lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;-&lt;/font&gt;&lt;font color="maroon"&gt;1&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
    {&lt;br /&gt;
        classes[firstClassIndex] &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;secondClass&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;else&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;{&lt;br /&gt;
        classes[secondClassIndex] &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;firstClass&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    &lt;br /&gt;
    element.className &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;classes.join(&lt;/font&gt;&lt;font color="#808080"&gt;" "&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="darkgreen"&gt;//Finds the index of an item in an array&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;IndexOf(item)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;for &lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;i&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="maroon"&gt;0&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;i &amp;lt; &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.length&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;i++)&lt;br /&gt;
    {        &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;[i] &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="black"&gt;item)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/font&gt;&lt;font color="blue"&gt;return &lt;/font&gt;&lt;font color="black"&gt;i&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;return &lt;/font&gt;&lt;font color="black"&gt;-&lt;/font&gt;&lt;font color="maroon"&gt;1&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; I then wrote a script to setup the treeview based on a nested list container.  The main reason I chose not to have all the event wiring in the HTML itself is that my approach leads to cleaner markup and allows one to easily convert any unordered list into a treeview.  Here is the script to hookup the click events (it works in both IE and FireFox): &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="darkgreen"&gt;//The toggle event handler for each expandable/collapsable node&lt;br /&gt;
//- Note that this also exists to prevent any IE memory leaks &lt;br /&gt;
//(due to circular references caused by this)&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;ToggleNodeStateHandler(&lt;/font&gt;&lt;font color="blue"&gt;event&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
{&lt;br /&gt;
    ToggleClass(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;, &lt;/font&gt;&lt;font color="#808080"&gt;"Collapsed"&lt;/font&gt;&lt;font color="black"&gt;, &lt;/font&gt;&lt;font color="#808080"&gt;"Expanded"&lt;/font&gt;&lt;font color="black"&gt;, (&lt;/font&gt;&lt;font color="blue"&gt;event == null&lt;/font&gt;&lt;font color="black"&gt;) ? &lt;/font&gt;&lt;font color="blue"&gt;window&lt;/font&gt;&lt;font color="black"&gt;.&lt;/font&gt;&lt;font color="blue"&gt;event &lt;/font&gt;&lt;font color="black"&gt;: &lt;/font&gt;&lt;font color="blue"&gt;event&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="darkgreen"&gt;//Prevents the onclick event from bubbling up to parent elements&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;PreventBubbleHandler(&lt;/font&gt;&lt;font color="blue"&gt;event&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(!&lt;/font&gt;&lt;font color="blue"&gt;event&lt;/font&gt;&lt;font color="black"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;event = window&lt;/font&gt;&lt;font color="black"&gt;.&lt;/font&gt;&lt;font color="blue"&gt;event;&lt;br /&gt;
    event&lt;/font&gt;&lt;font color="black"&gt;.cancelBubble &lt;/font&gt;&lt;font color="blue"&gt;= true;&lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="darkgreen"&gt;//Adds the relevant onclick handlers for the nodes in the tree view&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;function &lt;/font&gt;&lt;font color="black"&gt;SetupTreeView(elementId)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;tree &lt;/font&gt;&lt;font color="blue"&gt;= document&lt;/font&gt;&lt;font color="black"&gt;.getElementById(elementId)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    var &lt;/font&gt;&lt;font color="black"&gt;treeElements &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;tree.getElementsByTagName(&lt;/font&gt;&lt;font color="#808080"&gt;"li"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;br /&gt;
    for &lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;i&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="maroon"&gt;0&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;i &amp;lt; treeElements.length&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;i++)&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(treeElements[i].getElementsByTagName(&lt;/font&gt;&lt;font color="#808080"&gt;"ul"&lt;/font&gt;&lt;font color="black"&gt;).length &amp;gt; &lt;/font&gt;&lt;font color="maroon"&gt;0&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
        {&lt;br /&gt;
            treeElements[i].onclick &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;ToggleNodeStateHandler&lt;/font&gt;&lt;font color="blue"&gt;; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;else&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;{&lt;br /&gt;
            treeElements[i].onclick &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;PreventBubbleHandler&lt;/font&gt;&lt;font color="blue"&gt;; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; In this example to get it all going, you would call SetupTreeView("TreeView") after the page has loaded to setup the treeview for the nested lists. &lt;/p&gt;
&lt;p&gt; And this is the end result: &lt;a href="/Images/ridgway_co_za/CssTreeView.htm"&gt;CssTreeView.htm&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; I was informed of a TreeView control that pretty much does what I blogged about here and more.  You should take a look at the &lt;a href="http://www.silverstripe.com/downloads/tree/"&gt;SilverStripe Tree Control&lt;/a&gt; if you found this post interesting.  Thanks &lt;a href="http://www.oneafrikan.com/"&gt;Garreth&lt;/a&gt; for the information. &lt;/p&gt;
&lt;img src="http://ridgway.co.za/aggbug/150.aspx" width="1" height="1" /&gt;</description>
            <guid>http://ridgway.co.za/archive/2005/10/30/asimplecssbasedtreeview.aspx</guid>
            <pubDate>Sun, 30 Oct 2005 07:48:23 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/10/30/asimplecssbasedtreeview.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/150.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Drag and Drop TreeView</title>
            <link>http://ridgway.co.za/archive/2005/10/24/draganddropexample.aspx</link>
            <description>It's incredible at how easy it is to create an IE specific drag and drop treeview.  While playing aroudn with this I created a  survey editor where questions may be reordered or dragged on to answers to create drill down survey question dependencies.
&lt;p&gt; To start off I setup a set of nested survey questions and answers using ordered lists, like this: &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="darkgreen"&gt;&amp;lt;!-- Level 1 questions --&amp;gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="red"&gt; class&lt;/font&gt;&lt;font color="blue"&gt;="Questions"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
  &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; Where do you like to eat? &lt;br /&gt;
  &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="red"&gt; class&lt;/font&gt;&lt;font color="blue"&gt;="Answers"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;At home&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; At the pub &lt;/font&gt;&lt;font color="darkgreen"&gt;&amp;lt;!-- Level 2 sub questions --&amp;gt; &lt;br /&gt;
      &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="red"&gt; class&lt;/font&gt;&lt;font color="blue"&gt;="Questions"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; How often do you eat at the pub? &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="red"&gt; class&lt;/font&gt;&lt;font color="blue"&gt;="Answers"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
          &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;Once a week&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
          &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;Twice a week&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; How much money do you spend at the pub? &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
      &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;At a restuarant&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;Take away&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
  &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
  &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;LI&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;OL&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; As you can see from the HTML above, the idea is that if you answered that you like to eat at the pub, you would then be presented with a question as to how often you eat there.  I used the class names to identify whether the lists were questions or answers.  While I'm not entirely happy with this solution, it makes a fair amount of practical sense since you would most likely style the two differently in any case. &lt;/p&gt;
&lt;p&gt; Then comes the fun part hooking up the drag and drop code.  I decided that instead of adding all the event handlers inline I would add them using a script that ran once the survey elements had been rendered.  This was because the markup was becoming messy and confused with all the handlers.  It would also easily facilitate the turning on and off of the drag and drop functionality.  I did this using the following script block to loop through all the ordered lists on the page and attach the relevant event handlers to questions and answers: &lt;/p&gt;
&lt;div class="code"&gt; &lt;font color="black"&gt;var listItems &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;document.getElementsByTagName(&lt;/font&gt;&lt;font color="#808080"&gt;"LI"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
for &lt;/font&gt;&lt;font color="black"&gt;(i&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="maroon"&gt;0&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;i &amp;lt; listItems.length&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="black"&gt;i++)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(listItems[i].parentElement.className &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="#808080"&gt;"Questions"&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
    {&lt;br /&gt;
        listItems[i].onmousedown &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;() { StartDrag(this) }&lt;/font&gt;&lt;font color="blue"&gt;; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondrag &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;DragQuestion&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondragend &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;() { RepositionQuestion(this) }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondragenter &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;() { DisplayDropOption(this) }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondragleave &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;() { RemoveDropOption(this) }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondragover &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;AllowDrop&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    //Allow users &lt;/font&gt;&lt;font color="blue"&gt;to &lt;/font&gt;&lt;font color="black"&gt;drop questions under answers &lt;/font&gt;&lt;font color="blue"&gt;and &lt;/font&gt;&lt;font color="black"&gt;thereby create a recursive question&lt;br /&gt;
    //based &lt;/font&gt;&lt;font color="blue"&gt;on &lt;/font&gt;&lt;font color="black"&gt;an answer&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;else if &lt;/font&gt;&lt;font color="black"&gt;(listItems[i].parentElement.className &lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="#808080"&gt;"Answers"&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
    {&lt;br /&gt;
        listItems[i].ondragenter &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;() { DisplayDropOption(this) }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondragleave &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;() { RemoveDropOption(this) }&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;listItems[i].ondragover &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;AllowDrop&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
}&lt;/font&gt; 	&lt;/div&gt;
&lt;p&gt; As you can see questions are both drop targets and draggable while answers can only act as drag targets.  The event sequence when performing a drag and drop operation is therefore as follows: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt; OnMouseDown - start the drag and drop operation on the element using element.dragDrop() (note that this is IE specific code).  In this handler I created two clones of the question being dragged, one to drag around under the cursor as the user selects a target and another to act as a preview of the drag &amp;amp; drop.  &lt;/li&gt;
    &lt;li&gt; OnDrag - draws the question as it is being dragged around  &lt;/li&gt;
    &lt;li&gt; OnDragEnter - adds a preview of the dragged question to the relevant list or if the drag target is an answer it will dynamically create an ordered list container for the element and display it within that.  &lt;/li&gt;
    &lt;li&gt; OnDragOver - simply cancels the default event handler and thereby makes the question or element a valid drag target  &lt;/li&gt;
    &lt;li&gt; OnDragLeave - removes the previewed element from the target element  &lt;/li&gt;
    &lt;li&gt; OnDragEnd - repositions the question at the target position by swapping out the preview question with the question originally clicked on&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt; Since there is a fair amount of code involved in this, you will want to take a look at this demo page to see it all in action: &lt;a href="http://www.ridgway.co.za/Images/ridgway_co_za/DragAndDropDemo.htm"&gt;DragAndDropDemo.htm&lt;/a&gt; &lt;/p&gt;&lt;img src="http://ridgway.co.za/aggbug/147.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2005/10/24/draganddropexample.aspx</guid>
            <pubDate>Mon, 24 Oct 2005 02:34:53 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/10/24/draganddropexample.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/147.aspx</wfw:commentRss>
        </item>
        <item>
            <title>An Editable HTML Select List</title>
            <link>http://ridgway.co.za/archive/2005/10/15/aneditablehtmlselectlist.aspx</link>
            <description>/SubText/Imagesp down arrow next to a select list in windows XP looks different to that of windows 2000.  Hence the illusion of the control being a funked up version of a normal drop down list is lost.  However there is a way to effectively create the illusion if you place an input box on top of a select list.  The user would then be allowed to type into the text box as if they were typing directly into the select and you could then use JavaScript to perform whatever logic you wanted.  Unfortunately a select list appears over most HTML elements as it is a special windows control.  However if you use region clipping you can hide the rendering of the part of the drop down list that contains the input control.  The code below shows you how it is possible (please note that css expressions are only available in IE): 
&lt;div class="code"&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;html&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;style&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;&lt;/font&gt;&lt;font color="maroon"&gt; &lt;br /&gt;
&lt;br /&gt;
SELECT &lt;/font&gt;&lt;font color="blue"&gt;{&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    top&lt;/font&gt;&lt;font color="blue"&gt;: expression(this.previousSibling.offsetTop);&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    left&lt;/font&gt;&lt;font color="blue"&gt;: expression(this.previousSibling.offsetLeft);&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    width&lt;/font&gt;&lt;font color="blue"&gt;: expression(this.previousSibling.offsetWidth);&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    position&lt;/font&gt;&lt;font color="blue"&gt;: absolute;&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    clip&lt;/font&gt;&lt;font color="blue"&gt;: expression("rect(auto auto auto " + (this.previousSibling.offsetWidth - 20) + "px)");&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
    overflow&lt;/font&gt;&lt;font color="blue"&gt;: hidden;&lt;/font&gt;&lt;font color="red"&gt; &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;style&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;script&lt;/font&gt;&lt;font color="red"&gt; language&lt;/font&gt;&lt;font color="blue"&gt;="javascript"&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;oNewOption &lt;/font&gt;&lt;font color="blue"&gt;= null;&lt;br /&gt;
&lt;br /&gt;
function &lt;/font&gt;&lt;font color="black"&gt;AddListItem(oInput) {&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;oSelect &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;oInput.nextSibling&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;br /&gt;
    if &lt;/font&gt;&lt;font color="black"&gt;(oNewOption &lt;/font&gt;&lt;font color="blue"&gt;== null&lt;/font&gt;&lt;font color="black"&gt;) {&lt;br /&gt;
        oNewOption &lt;/font&gt;&lt;font color="blue"&gt;= document&lt;/font&gt;&lt;font color="black"&gt;.createElement(&lt;/font&gt;&lt;font color="#808080"&gt;"OPTION"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;oSelect.options.add(oNewOption)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    &lt;br /&gt;
    oNewOption.text &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;oInput.&lt;/font&gt;&lt;font color="blue"&gt;value;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;oNewOption.&lt;/font&gt;&lt;font color="blue"&gt;value = &lt;/font&gt;&lt;font color="black"&gt;oInput.&lt;/font&gt;&lt;font color="blue"&gt;value;&lt;br /&gt;
    &lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;script&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;body&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;form&lt;/font&gt;&lt;font color="red"&gt; id&lt;/font&gt;&lt;font color="blue"&gt;='Form1'&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;input&lt;/font&gt;&lt;font color="red"&gt; id&lt;/font&gt;&lt;font color="blue"&gt;='txtInput'&lt;/font&gt;&lt;font color="red"&gt; type&lt;/font&gt;&lt;font color="blue"&gt;='text'&lt;/font&gt;&lt;font color="red"&gt; onkeyup&lt;/font&gt;&lt;font color="blue"&gt;="AddListItem(this)"/&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;select&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
                                                                        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;option&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;abc&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;option&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
                                                                        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;option&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;cde&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;option&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
                                                                        &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;&lt;/font&gt;&lt;font color="maroon"&gt;option&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt;efg&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;option&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
                                                                    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;select&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;form&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;body&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;/font&gt;&lt;font color="blue"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="maroon"&gt;html&lt;/font&gt;&lt;font color="blue"&gt;&amp;gt;&lt;/font&gt;&lt;font color="black"&gt; &lt;br /&gt;
&lt;/font&gt; &lt;/div&gt;
Here is the code in action: &lt;a href="/Images/ridgway_co_za/EditableCombo.htm"&gt;EditableCombo.htm&lt;/a&gt;&lt;img src="http://ridgway.co.za/aggbug/144.aspx" width="1" height="1" /&gt;</description>
            <guid>http://ridgway.co.za/archive/2005/10/15/aneditablehtmlselectlist.aspx</guid>
            <pubDate>Sat, 15 Oct 2005 12:18:55 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/10/15/aneditablehtmlselectlist.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/144.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>