<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'><id>tag:blogger.com,1999:blog-2253917077127539958</id><updated>2008-08-21T17:35:18.556+01:00</updated><title type='text'>blog.dogma.co.uk</title><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-4938524374895344403</id><published>2008-08-21T17:20:00.003+01:00</published><updated>2008-08-21T17:35:18.568+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='.net2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='visualstudio'/><category scheme='http://www.blogger.com/atom/ns#' term='.net3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='customclasses'/><title type='text'>jQuery Ajax Dot Net 1.1.3 and Examples</title><content type='html'>&lt;p&gt;Version 1.1.3 contains a single bug fix in the parser. I have also uploaded two example Visual Studio projects, one for .NET 2.0 and one for .NET 3.5. The projects, in addition to the example calls, illustrate the plugins inability to send custom classes to the server. This is a feature I'm currently working on.&lt;/p&gt;
&lt;p&gt;The example projects can be found here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.dogma.co.uk/blog/AjaxDotNet2.0Example.zip" title="Ajax Dot Net 2.0 Example"&gt;AjaxDotNet2.0Example.zip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dogma.co.uk/blog/AjaxDotNet3.5Example.zip" title="Ajax Dot Net 3.5 Example"&gt;AjaxDotNet3.5Example.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/08/jquery-ajax-dot-net-113-and-examples.html' title='jQuery Ajax Dot Net 1.1.3 and Examples'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=4938524374895344403' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/4938524374895344403/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/4938524374895344403'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/4938524374895344403'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-7447680205041247291</id><published>2008-08-12T21:33:00.004+01:00</published><updated>2008-08-12T21:57:50.369+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='intellisense'/><title type='text'>jQuery Ajax Dot Net 1.1.2</title><content type='html'>&lt;p&gt;A new version of the Ajax Dot Net jQuery plugin has been released. The release restructures the way the plugin parses server responses into a JavaScript object. The release is also split into packed and Intellisense versions.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://plugins.jquery.com/project/ajaxdotnet" title="jQuery Ajax Dot Net"&gt;Plugin Page&lt;/a&gt;&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/08/jquery-ajax-dot-net-112.html' title='jQuery Ajax Dot Net 1.1.2'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=7447680205041247291' title='5 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/7447680205041247291/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/7447680205041247291'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/7447680205041247291'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-3590224361182464298</id><published>2008-08-06T20:58:00.006+01:00</published><updated>2008-08-12T00:58:01.646+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='googlemaps'/><category scheme='http://www.blogger.com/atom/ns#' term='visualstudio'/><category scheme='http://www.blogger.com/atom/ns#' term='intellisense'/><title type='text'>Google Maps JavaScript Intellisense</title><content type='html'>&lt;p&gt;I'm working on a project that uses &lt;a href="http://code.google.com/apis/maps/" title="Google Maps API"&gt;Google Maps&lt;/a&gt; extensively. I've used GM for basic stuff in the past but that was pre &lt;a href="http://code.google.com/apis/ajax/documentation/" title="API Loader"&gt;API Loader&lt;/a&gt; and Visual Studio 2008. The API Loader is cool, I like namespaces it keeps everything neat, &lt;code&gt;GMap2&lt;/code&gt; looked too much like COM programming. &lt;code&gt;google.maps.Map2&lt;/code&gt; is something I can get into.&lt;/p&gt;
&lt;p&gt;The namespaces got me thinking, someone must have found a way to get Intellisence for &lt;code&gt;google.maps&lt;/code&gt;. The closest I could find was a blog post by &lt;a href="http://blog.rodj.org/archive/2008/04/15/google-maps-javascript-intellisense.aspx" title="Google Maps JavaScript Intellisense"&gt;Roger Chapman&lt;/a&gt;, his solution is pre loader and hand written, rather than the &lt;a href="http://blogs.ipona.com/james/archive/2008/02/15/JQuery-IntelliSense-in-Visual-Studio-2008.aspx" title="JQuery IntelliSense in Visual Studio 2008"&gt;scripted solutions for jQuery&lt;/a&gt; (thanks to the way jQuery is documented). That said, I am extremely grateful for work that must have been time consuming and Roger is to be commended. Roger Chapman I salute you.&lt;/p&gt;
&lt;p&gt;I have taken Roger's original file and namespace'd it. I've added a few lines to the top of the file which declares &lt;code&gt;google.maps&lt;/code&gt; and the the API Loader functionality. Then, using Find &amp;amp; Replace, I switched all those ugly capital &lt;code&gt;G&lt;/code&gt;s and &lt;code&gt;G_&lt;/code&gt;s for &lt;code&gt;google.maps&lt;/code&gt;. I've also added one or two additional classes that weren't included in Roger's original file. I'll continue to add more as and when I need to. I'd certainly appreciate any additional classes that other people have added. The current version of the file is available to download &lt;a href="http://www.dogma.co.uk/blog/google.intellisense.0.1.js.txt" title="JavaScript Intellisense for Google Maps API Loader"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I believe Roger has since created a &lt;a href="http://www.codeplex.com/GMapJS" title="GMapJS"&gt;CodePlex project&lt;/a&gt; for his work. If there is any interest in me doing so, I'll contact Roger with a view to forking the project for the API Loader variation.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/08/google-maps-javascript-intellisense.html' title='Google Maps JavaScript Intellisense'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=3590224361182464298' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/3590224361182464298/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/3590224361182464298'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/3590224361182464298'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-6035024536846268018</id><published>2008-07-29T21:30:00.003+01:00</published><updated>2008-07-29T23:09:57.686+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puzzles'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Square the Sum</title><content type='html'>&lt;p&gt;I'm teaching myself F#. It's the first time I've worked with a language of this type, it's also been a while since I spent anytime with algorithms. Maths was never really my strong point. In the past I've learnt languages through necessity but I don't usually find myself in situations where neither C# or JavaScript will do the job.&lt;/p&gt;
&lt;p&gt;I decided to learn F# by solving mathematical puzzles. To that end I've found a number of suitable puzzles, the first of which can be found &lt;a href="http://foohack.com/2008/07/programming-puzzles-and-our-mismatch-problem/" title="Programming Puzzles and our Mismatch Problem"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The first of the problems listed at Foo Hack is called 'Square the Sum', it is this puzzle that is the subject of this post. I won't describe the problem here, for more information see the original post at &lt;a href="http://foohack.com/2008/07/programming-puzzles-and-our-mismatch-problem/" title="Programming Puzzles and our Mismatch Problem"&gt;Foo Hack&lt;/a&gt;. What I will describe are the challenges I faced while devising the solution.&lt;/p&gt;
&lt;p&gt;As my first attempt at writing anything significant in F#, I felt like a fish out of water. I was unsure how to layer multiple steps within a single function, my head was swimming with features (I'd yet to try in C#) like anonymous methods and lambda expressions, that I knew had there roots in languages like F#. The mist cleared when I understood that all functions in F# are essentially single parameter functions. Functions that appear to have multiple parameters are actually curried, each parameter is parsed by a function generated by the function that parsed the previous parameter. I hope that makes sense, it took me a little while to get my head around it. The concept is best explained at &lt;a href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!169.entry" title="F# function types: fun with tuples and currying"&gt;Inside F#&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With this point explained, the idea of layering multiple functions on top of each other is easier to swallow. I believe the pipeline operator can be used to do something similar, but I've not touched on that yet. I now have a function called &lt;code&gt;sqSum&lt;/code&gt; that performs all the steps required to split &lt;code&gt;x&lt;/code&gt; in half, add those halves together and square the total. Now I need to iterate through a range of integers and identify those that match the criteria as laid out in the original problem. This functionality was provided in the form of &lt;code&gt;List.filter&lt;/code&gt;. &lt;code&gt;List&lt;/code&gt; is part of the &lt;code&gt;FSharp.Collections&lt;/code&gt; namespace, the &lt;code&gt;filter&lt;/code&gt; function allows you create a collection based on the condition set in your anonymous function, in this case when the result of sqSum equals the original figure.&lt;/p&gt;
&lt;p&gt;My last hurdle was the dynamic typing performed by F#. In C# I'm used to strongly typing everything, in JavaScript I'm used checking whenever possible. After a few implicit conversion errors I soon  remembered when to decimalise and explicitly type.&lt;/p&gt;
&lt;p&gt;My solution is below:&lt;/p&gt;
&lt;pre name="code" class="f#"&gt;
let sqSum x : float =
&amp;#160;let top = round (x / 1000.00)
&amp;#160;let bot = x - (top * 1000.00)
&amp;#160;let tot = top + bot
&amp;#160;tot * tot

let lst = List.filter (fun x -&gt; float x = sqSum (float x)) [100000 .. 999999]
&lt;/pre&gt;
&lt;p&gt;Which returns:&lt;/p&gt;
&lt;code&gt;
[494209; 998001]
&lt;/code&gt;
&lt;p&gt;I'm sure there are a myriad of ways in which you can come to this solution, what I'd be interested in is some insight into the efficiency of my solution and how it might bettered. This is a learning exercise after all.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/07/square-sum.html' title='Square the Sum'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=6035024536846268018' title='2 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/6035024536846268018/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/6035024536846268018'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/6035024536846268018'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-5501614880576945226</id><published>2008-07-25T20:23:00.003+01:00</published><updated>2008-07-25T20:37:11.012+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xhr'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>Date Support For Ajax Dot Net Plugin</title><content type='html'>&lt;p&gt;The Ajax Dot Net jQuery plugin now returns native JavaScript Date objects.&lt;/p&gt;
&lt;p&gt;Details &lt;a href="http://plugins.jquery.com/project/ajaxdotnet"&gt;here&lt;/a&gt;.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/07/date-support-for-ajax-dot-net-plugin.html' title='Date Support For Ajax Dot Net Plugin'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=5501614880576945226' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/5501614880576945226/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/5501614880576945226'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/5501614880576945226'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-730177036781229966</id><published>2008-07-14T21:39:00.004+01:00</published><updated>2008-07-14T21:42:45.136+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sketch'/><title type='text'>School Boy</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_rgILlh0zL1E/SHu5tCdzW8I/AAAAAAAAAAU/HJbUrqXbXYg/s1600-h/school-boy.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_rgILlh0zL1E/SHu5tCdzW8I/AAAAAAAAAAU/HJbUrqXbXYg/s400/school-boy.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5222972376273345474" /&gt;&lt;/a&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/07/school-boy.html' title='School Boy'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=730177036781229966' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/730177036781229966/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/730177036781229966'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/730177036781229966'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-369490620546062895</id><published>2008-07-09T13:16:00.002+01:00</published><updated>2008-07-09T13:21:14.796+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>ASP.NET jQuery Plugin</title><content type='html'>&lt;p&gt;Following my previous post on communicating with ASP.NET Ajax enabled Web Services and PageMethods. I have encapsulated the code in a jQuery Plugin.&lt;/p&gt;
&lt;p&gt;Details can be found &lt;a href="http://plugins.jquery.com/project/ajaxdotnet"&gt;here&lt;/a&gt;.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/07/aspnet-jquery-plugin.html' title='ASP.NET jQuery Plugin'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=369490620546062895' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/369490620546062895/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/369490620546062895'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/369490620546062895'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-5252529349903343674</id><published>2008-06-27T14:51:00.008+01:00</published><updated>2008-06-27T15:20:08.702+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xhr'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='gracefuldegradation'/><category scheme='http://www.blogger.com/atom/ns#' term='designpatterns'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>Graceful Lists</title><content type='html'>&lt;p&gt;In a project I was working on recently I needed to return a list. I can't remember what the list consisted of (okay not that recent), but each item in the list was going to require some processor power to generate the item's associated content. I didn't want to take the standard server side approach of building the list prior to rendering the page. While the list size was fixed, the processing time for each item varied, making timeouts a factor. The age of the data was also important, preventing the possibility of server side caching over any length of time.&lt;/p&gt;
&lt;p&gt;The proposition I came up with is not an uncommon one. The idea was to create a page which loaded each item on the list incrementally using &lt;acronym title="XMLHTTPRequest"&gt;XHR&lt;/acronym&gt;. But what about browsers without JavaScript or with JavaScript switch off? Initially, I considered drastically reducing the amount of results returned by the page using paging. My main concern here was that while you can generally tell whether the user's browser is JavaScript enabled from the User Agent, it's impossible (as far as I'm aware) to detect whether the user has opted to disable JavaScript, on the first request to the server. Also, paging drives me nuts, I prefer to scroll!&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I had assumed browsers broadcasted the status of scripting abilities and alike in the header of each request. I have no reason for assuming this, other than it sounds like quite a good idea to me.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Without being able to reliably detect a browser's scripting ability, the paging solution risks serving an empty page to browsers with JavaScript disabled. While investigating this problem I came across &lt;a href="http://www.123-reg.co.uk" target="_blank"&gt;123-reg.co.uk&lt;/a&gt;. &lt;a href="http://www.123-reg.co.uk" target="_blank"&gt;123-reg.co.uk&lt;/a&gt; uses a similar pattern to the one I've suggested, for displaying domain availability. User's with JavaScript enabled browsers see the list built in front of them using Ajax. Everyone else is served a pre-rendered list. What is clever (in its simplicity) is the way in which &lt;a href="http://www.123-reg.co.uk" target="_blank"&gt;123-reg.co.uk&lt;/a&gt; detects JavaScript. On the page where the user enters their search terms, a script modifies the action URL of the form to include the parameter &lt;code&gt;"ajax_enabled=true"&lt;/code&gt;. The results page is rendered based on the value of that parameter.&lt;/p&gt;
&lt;a href="http://bp1.blogger.com/_rgILlh0zL1E/SGTw-8z4NYI/AAAAAAAAAAM/gZGVHF1Inqs/s1600-h/123-reg.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_rgILlh0zL1E/SGTw-8z4NYI/AAAAAAAAAAM/gZGVHF1Inqs/s320/123-reg.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216559232668153218" /&gt;&lt;/a&gt;
&lt;p&gt;The example provided by &lt;a href="http://www.123-reg.co.uk" target="_blank"&gt;123-reg.co.uk&lt;/a&gt; is a great way of detecting script. The problem with this approach is the reliance on the search page (to modify the URL), my list exists on a page that is a possible entry point to the application. I'm not making it easy for myself. As a result of the previous example I also toyed with the idea of a page that assumes JavaScript is switched on, but with a META Refresh tag in the header. If JavaScript is enabled, remove the META tag. If JavaScript is disabled, the page redirects (via the META tag) to a pre-rendered page. I was put off by the idea of effectively breaking the Back button for users without JavaScript.&lt;/p&gt;
&lt;p&gt;My eventual implementation was a pre-rendered list that assumed JavaScript was switched off. This list doesn't contain any of the extended content, so no heavy lifting that originally had me concerned. Each item on the list instead provides anchors to a second page that generates the extended content. Once the page is loaded, JavaScript enabled browsers move though each of the items, dynamically adding the extend content. This solution works extremely well for script enabled browsers, everything on one page with visual feedback for the processing going on server side. Unscripted browsers have the burden of an extra click to and from the extended content, but the initial page load dramatically reduced when compared to the server side approach described at the beginning of this post.
&lt;/p&gt;
&lt;p&gt;This particular problem made me think a lot about my audience and the merits of graceful degradation. Who am I making this application for? And more importantly, who am I willing to exclude? Within a corporate Intranet, these decisions are sometimes made by company guidelines and policies, a lot of the time by time constraints. In the open web, (I believe) accessibility is extremely important. If you are building something like &lt;a href="http://www.facebook.com"&gt;Facebook&lt;/a&gt;, where you a targeting a market defined by age, gender or interest, your application should be accessible to text readers and main stream browsers alike. The experience has also showed me that I'm not so bothered about catering for users that have purposefully restricted the capability of their own browser (switching off script or &lt;acronym title="Cascading Style Sheets"&gt;CSS&lt;/acronym&gt;). I guess there might be a valid reason for doing this, but I'm unable to come up with one.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/06/graceful-lists.html' title='Graceful Lists'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=5252529349903343674' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/5252529349903343674/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/5252529349903343674'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/5252529349903343674'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry><entry><id>tag:blogger.com,1999:blog-2253917077127539958.post-3546499294897074082</id><published>2008-06-21T14:40:00.023+01:00</published><updated>2008-06-26T22:09:33.649+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>Bridging ASP.NET &amp; jQuery</title><content type='html'>&lt;p&gt;Until recently I was inclined to use the ASP.NET AJAX framework when working with JavaScript within Visual Studio, if I used a library at all. I hadn't really been sold on the idea of JavaScript frameworks or libraries from the get go. I realise this sounds a bit ridiculous coming from an ASP.NET developer, but I enjoy writing JavaScript and saw these libraries as taking some of the fun out of it.&lt;/p&gt;
&lt;p&gt;I eventually saw the benefits of a library when I started playing around with the wicked cool JavaScript intellisence and debugging support in Visual Studio 2008. Still, it was a mixed bag. I enjoyed the short cuts and the object descriptor’s provided through the script manager but was wary of the amount of JavaScript being generated in the background. I was also very conscious that, at least in my opinion, this library was built for developers who don't enjoy working with the client, in fact providing a level of abstraction such that the developer doesn't need to touch the client at all. For that last concern I found jQuery. jQuery isn’t just about creating short cuts around well trodden problems, jQuery enables you to work in an entirely more intuitive way. Thank you John Resig.&lt;/p&gt;
&lt;p&gt;So now I have two libraries, I was torn. If I wanted to make use of ASP.NET great JSON web services I had to use the Microsoft library. If I wanted to do anything else I was using jQuery. It’s all sounding a bit bloated.&lt;/p&gt;
&lt;p&gt;That was until I read a fantastic article @ Encosia called &lt;a title="3 mistakes to avoid when using jQuery with ASP.NET AJAX" href="http://encosia.com/2008/06/05/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/" target="_blank"&gt;3 mistakes to avoid when using jQuery with ASP.NET AJAX&lt;/a&gt;. In the article, Dave Ward explains the connection between the ASP.NET JSON Page Method and the client side AJAX library. What had never occurred to me and what Dave pointed out was that client and the server were not inseparable. In fact you can talk quite happily with your JSON enabled Page Methods and Web Services with jQuery alone.&lt;/p&gt;
&lt;p&gt;"Great", I thought. "This is it!" I said. I started writing Ajax calls in the way Dave described, thrilled by the possibilities that laid before me. FireFox loved it, FireBug reported all's well. IE was not having it. "Aw", I thought. "Aw dear." I said. You can read up on the trials and tribulations of talking to an ASP.NET JSON Page Method on the Encosia blog, needless to say I experienced these and more. Once I had Page Methods working I had more problems with Web Services.&lt;/p&gt;
&lt;p&gt;I should mention at this point that most of these problems arose from false assumptions on my part about certain aspects of the code, specifically the need to stringify the data parameter.&lt;/p&gt;&lt;p&gt;My conclusion was that the requirements of these calls were a bit too specific for jQuery's ajax function. So to the point of my post, I have written a very simple function that works much like jQuery's ajax method but is designed solely to work with ASP.NET JSON Page Methods and Web Services. I've namespace'd it to avoid collisions with other frameworks and I believe the scripts only external dependency is on that of json2.js from &lt;a title="JSON Home Page" href="http://www.json.org/" target="_blank"&gt;json.org&lt;/a&gt;.&lt;/p&gt;
&lt;pre name="code" class="javascript"&gt;
/// &amp;lt;reference path="jquery-1.2.6.min.js"&amp;gt;
/// &amp;lt;reference path="json2.js"&amp;gt;

var k3r = new Object();
k3r.ajax = function() {}
k3r.ajax.xhr = function() {
&amp;#160;try { return new XMLHttpRequest(); } catch(e) {}
&amp;#160;try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
&amp;#160;try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
&amp;#160;return null;
}

k3r.ajax.request = function(obj) {
&amp;#160;var xhr = k3r.ajax.xhr();
&amp;#160;var loc = obj.location;
&amp;#160;var data = '';

&amp;#160;if (obj.type == 'GET') {
&amp;#160;&amp;#160;for (var i in obj.pack) {
&amp;#160;&amp;#160;&amp;#160;if (data != '')
&amp;#160;&amp;#160;&amp;#160;&amp;#160;data += '&amp;amp;';
&amp;#160;&amp;#160;&amp;#160;&amp;#160;data += i + '=' + obj.pack[i];
&amp;#160;&amp;#160;}
&amp;#160;&amp;#160;loc += '?' + data;
&amp;#160;&amp;#160;data = null;
&amp;#160;}
&amp;#160;else if (obj.type == 'POST') {
&amp;#160;&amp;#160;data = JSON.stringify(obj.pack);
&amp;#160;}

&amp;#160;xhr.open(obj.type, loc, true); //true = async
&amp;#160;xhr.onreadystatechange = function() {
&amp;#160;&amp;#160;if (xhr.readyState == 4) {
&amp;#160;&amp;#160;&amp;#160;var response;
&amp;#160;&amp;#160;&amp;#160;try {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;response = JSON.parse(xhr.responseText);
&amp;#160;&amp;#160;&amp;#160;}
&amp;#160;&amp;#160;&amp;#160;catch (err) {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;response = err;
&amp;#160;&amp;#160;&amp;#160;}

&amp;#160;&amp;#160;&amp;#160;if (xhr.status == 200 &amp;amp;&amp;amp; typeof obj.success != 'undefined')
&amp;#160;&amp;#160;&amp;#160;&amp;#160;obj.success(response, xhr.status, xhr.statusText);
&amp;#160;&amp;#160;&amp;#160;else if (typeof obj.other != 'undefined')
&amp;#160;&amp;#160;&amp;#160;&amp;#160;obj.other(response, xhr.status, xhr.statusText);
&amp;#160;&amp;#160;}
&amp;#160;}

&amp;#160;xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
&amp;#160;xhr.send(data);
}
&lt;/pre&gt;
&lt;p&gt;The method k3r.ajax.request takes an object containing 5 parameters; 'type', 'pack', 'location', 'success' and 'other'.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;type: The verb associated with the request. Only GET &amp;amp; POST are currently catered for.&lt;/li&gt;
&lt;li&gt;pack: A JSON object containing the input parameters.&lt;/li&gt;
&lt;li&gt;location: The URL of the web service method.&lt;/li&gt;
&lt;li&gt;success: Callback function if request is successful. JSON returned.&lt;/li&gt;
&lt;li&gt;other: Catch-all callback function for everything else. Error message returned.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;An example request would look like this:&lt;/p&gt;
&lt;pre name="code" class="javascript"&gt;
k3r.ajax.request({
&amp;#160;type: 'GET',
&amp;#160;pack: {id: 1},
&amp;#160;location: 'Example.aspx/GetExample',
&amp;#160;success: function(obj) {
&amp;#160;&amp;#160;console.info(obj); //FireBug required;
&amp;#160;},
&amp;#160;other: function() {
&amp;#160;}
});
&lt;/pre&gt;
&lt;p&gt;The benefits of k3r.ajax.request over the jQuery ajax function, when looking at ASP.NET JSON Web Services specifically, are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can pass the input parameters as a JSON object, no need to stringify.&lt;/li&gt;
&lt;li&gt;The IE Content-Type strangeness is taken care of behind the scenes.&lt;/li&gt;
&lt;li&gt;k3r.ajax.request is not dependant on jQuery, it should work with any library.&lt;/li&gt;
&lt;li&gt;Should work with JSON enabled ASP.NET Page Methods and Web Services straight out of the box.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;What comes next? When I have the time I'd like to explore the possibility of adding this and other ASP.NET helpers into a jQuery plugin. Also, I'm certain there is some room for improvement with my error handling.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://blog.dogma.co.uk/2008/06/bridging-aspnet-jquery.html' title='Bridging ASP.NET &amp; jQuery'/><link rel='enclosure' type='text/html' href='http://encosia.com/2008/06/05/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/' length='0'/><link rel='enclosure' type='text/html' href='http://json.org' length='0'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2253917077127539958&amp;postID=3546499294897074082' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/3546499294897074082/comments/default' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://blog.dogma.co.uk/feeds/posts/default/3546499294897074082'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2253917077127539958/posts/default/3546499294897074082'/><author><name>rich</name><uri>http://www.blogger.com/profile/02719982479905880008</uri><email>noreply@blogger.com</email></author></entry></feed>