<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://scottonwriting.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Scott On Writing.NET : jQuery</title><link>http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx</link><description>Tags: jQuery</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20423.869)</generator><item><title>Creating a Currency Masked TextBox with On-the-Fly Currency Formatting</title><link>http://scottonwriting.net/sowblog/archive/2011/06/25/creating-a-currency-masked-textbox-with-on-the-fly-currency-formatting.aspx</link><pubDate>Fri, 24 Jun 2011 23:21:54 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:189984</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=189984</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/06/25/creating-a-currency-masked-textbox-with-on-the-fly-currency-formatting.aspx#comments</comments><description>&lt;p&gt;By default, a user can enter any character into a textbox. Masked textboxes help reduce user input error by limiting what characters a user can type into a textbox. Masked textboxes have been a standard user input element in desktop applications for decades, but are less common in web applications for a variety of reasons. However, it’s not terribly difficult to implement masked textboxes. All that’s required is a touch of JavaScript and a sprinkle of jQuery.&lt;/p&gt;  &lt;p&gt;In a recent project the client wanted a masked textbox for the textboxes on the page collecting currency information. Moreover, he wanted the user’s input to automatically be displayed as a formatted currency value in the textbox after entering their value. (Check out &lt;a href="http://jsfiddle.net/CBDea/1/"&gt;a live demo&lt;/a&gt; of my script…) But first things first, let’s see how to create a currency masked textbox.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Allowing Only Currency-Related Characters In a TextBox&lt;/h2&gt;  &lt;p&gt;There are a number of existing masked input plugins for jQuery. After trying some out I decided to roll my own JavaScript functions. I intend to come back to these and turn them into jQuery plugins, but for now they’re just JavaScript functions. As you can see in the script below, I created four functions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;numbersOnly&lt;/strong&gt; – allows just number inputs, whether they are from the letters at the top of the keyboard or from the number pad.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;numbersAndCommasOnly &lt;/strong&gt;– allows number inputs and commas.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;decimalsOnly&lt;/strong&gt; – allows numbers, commas, and periods (either from the main keyboard or the number pad).&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;currenciesOnly&lt;/strong&gt; – allows numbers, commas, periods, and the dollar sign.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In addition to the allowed characters discussed above, the functions also permit “special character key codes,” namely Delete, Backspace, left arrow, right arrow, Home, End and Tab. What keycodes are valid are listed in the variables at the top of the script; see &lt;a href="http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx"&gt;Javascript Char Codes&lt;/a&gt; for a table listing the keys and their corresponding key codes.&lt;/p&gt;  &lt;p&gt;Here is the script of interest:&lt;/p&gt;  &lt;pre class="brush: js;"&gt;// JavaScript I wrote to limit what types of input are allowed to be keyed into a textbox 
var allowedSpecialCharKeyCodes = [46,8,37,39,35,36,9];
var numberKeyCodes = [44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105];
var commaKeyCode = [188];
var decimalKeyCode = [190,110];

function numbersOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0);

    if (legalKeyCode === false)
        event.preventDefault();
}

function numbersAndCommasOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, commaKeyCode) &amp;gt;= 0);

    if (legalKeyCode === false)
        event.preventDefault();
}

function decimalsOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, commaKeyCode) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, decimalKeyCode) &amp;gt;= 0);

    if (legalKeyCode === false)
        event.preventDefault();
}

function currenciesOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, commaKeyCode) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, decimalKeyCode) &amp;gt;= 0);

    // Allow for $
    if (!legalKeyCode &amp;amp;&amp;amp; event.shiftKey &amp;amp;&amp;amp; event.keyCode == 52)
        legalKeyCode = true;

    if (legalKeyCode === false)
        event.preventDefault();
}&lt;/pre&gt;

&lt;p&gt;My script is, admittedly, very US-centric. I have not tested the key codes with a non-English keyboard and for currencies I only allow a dollar sign. For the project I wrote this script for this is (currently) a non-issue since it is used within the corporate firewall and all sales are domestic, but clearly the above script would not work as well for international settings.&lt;/p&gt;

&lt;h2&gt;Applying the Currency Masking Script to a TextBox on the Page&lt;/h2&gt;

&lt;p&gt;With the above script in place you can have a textbox on the page mask its input by having the appropriate function called in response to the &lt;strong&gt;keydown&lt;/strong&gt; event. The following jQuery syntax wires up this logic to all single-line textboxes that have the CSS class &lt;strong&gt;currenciesOnly&lt;/strong&gt;.&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(document).ready(function () {
    $(&amp;quot;input[type=text].currenciesOnly&amp;quot;).live('keydown', currenciesOnly);
});&lt;/pre&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;h2&gt;Formatting the Just-Entered Currency&lt;/h2&gt;

&lt;p&gt;Another requirement my client had was to format the just-entered number as a currency. That is, to change the user’s input – say, 45000 – to a formatted value like $45,000.00 immediately after their tabbed out of the textbox. To accomplish this I used &lt;a href="http://www.bendewey.com/blog/"&gt;Ben Dewey&lt;/a&gt;’s &lt;a href="http://code.google.com/p/jquery-formatcurrency/"&gt;jQuery Format Currency Plugin&lt;/a&gt;, which you can see a demo of at &lt;a href="http://www.bendewey.com/code/formatcurrency/demo/"&gt;http://www.bendewey.com/code/formatcurrency/demo/&lt;/a&gt;. This plugin adds a &lt;strong&gt;formatCurrency&lt;/strong&gt; function that you can call on a set of elements returned by a jQuery selector.&lt;/p&gt;

&lt;p&gt;To use this plugin I updated the &lt;strong&gt;$(document).ready&lt;/strong&gt; event handler shown above to also call the &lt;strong&gt;formatCurrency&lt;/strong&gt; function on &lt;strong&gt;blur&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(document).ready(function () {
    $(&amp;quot;input[type=text].currenciesOnly&amp;quot;).live('keydown', currenciesOnly)
                        .live('blur', 
                                 function () { 
                                     $(this).formatCurrency(); 
                                 }
                              );
});&lt;/pre&gt;

&lt;p&gt;In short, whenever a textbox with a CSS class of &lt;strong&gt;currenciesOnly&lt;/strong&gt; is blurred, the just-blurred textbox’s inputs are formatted as a currency thanks to the &lt;strong&gt;formatCurrency&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;And that’s all there is to it, folks.&lt;/p&gt;

&lt;p align="center"&gt;&lt;font size="5"&gt;To see a live demo of the above code, check out this jsfiddle script: &lt;/font&gt;&lt;a href="http://jsfiddle.net/CBDea/1/"&gt;&lt;font size="5"&gt;http://jsfiddle.net/CBDea/1/&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=189984" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>Select a textbox’s text on focus using jQuery</title><link>http://scottonwriting.net/sowblog/archive/2011/02/01/select-a-textbox-s-text-on-focus-using-jquery.aspx</link><pubDate>Tue, 01 Feb 2011 00:23:20 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:177347</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=177347</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/02/01/select-a-textbox-s-text-on-focus-using-jquery.aspx#comments</comments><description>&lt;p&gt;A fellow ASP.NET developer asked me today how he could have the text in a TextBox control automatically selected whenever the TextBox received focus.&lt;/p&gt;  &lt;p&gt;In short, whenever any textbox on the page receives focus you want to call its &lt;strong&gt;select()&lt;/strong&gt; function. (The JavaScript &lt;strong&gt;select()&lt;/strong&gt; function is the function that actually selects the textbox’s text, if any.) Implementing this functionality requires just one line of JavaScript code, thanks to jQuery:&lt;/p&gt;  &lt;pre class="brush: js;"&gt;$(&amp;quot;input[type=text]&amp;quot;).focus(function() { $(this).select(); });&lt;/pre&gt;

&lt;p&gt;In English, the above line of code says, “For any &lt;strong&gt;&amp;lt;input&amp;gt;&lt;/strong&gt; element with a &lt;strong&gt;type=”text” &lt;/strong&gt;attribute, whenever it is focused call it’s &lt;strong&gt;select()&lt;/strong&gt; function.” If you only wanted certain textboxes on the page to auto-select their text on focus you’d update the selector syntax accordingly. For example, the following modification only auto-selects the text for those textboxes that use a CSS class named &lt;strong&gt;autoselect&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(&amp;quot;input[type=text].autoselect&amp;quot;).focus(function() { $(this).select(); });&lt;/pre&gt;

&lt;p&gt;That’s all there is to it! You can view the complete script and try a working demo at &lt;a title="http://jsfiddle.net/ScottOnWriting/Kq7A4/2/" href="http://jsfiddle.net/ScottOnWriting/Kq7A4/2/"&gt;http://jsfiddle.net/ScottOnWriting/Kq7A4/2/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One final comment: if one or more of the textboxes you want to auto-select exist within an UpdatePanel control then consider using jQuery’s &lt;a href="http://api.jquery.com/live/"&gt;&lt;strong&gt;live() &lt;/strong&gt;function&lt;/a&gt;. The &lt;strong&gt;live()&lt;/strong&gt; function maintains the event bindings even when the HTML is regenerated due to a partial page postback; for more information, see my article – &lt;a href="http://www.4guysfromrolla.com/articles/090810-1.aspx"&gt;Rebinding Client-Side Events After a Partial Page Postback&lt;/a&gt;. For more information on jQuery, see &lt;a href="http://dotnetslackers.com/articles/ajax/Using-jQuery-with-ASP-NET.aspx"&gt;Using jQuery with ASP.NET&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EDIT [2011-03-29]:&lt;/strong&gt; To get this to work in Safari / Chrome you will need to add a &lt;strong&gt;mouseup&lt;/strong&gt; event handler and disable the default event, as the &lt;strong&gt;onmouseup&lt;/strong&gt; event is causing the textbox to be unselected. For more details, see this Stackoverflow post: &lt;a href="http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome"&gt;Selecting text on focus using jQuery not working in Safari and Chrome&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="brush: sql;"&gt;$(&amp;quot;input[type=text].autoselect&amp;quot;).focus(
    function() { 
         $(this).select(); 
    }
 )
 .mouseup(
    function(e) {
        e.preventDefault();
    }
 );
    &lt;/pre&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=177347" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>jQuery Usage Among Top Sites</title><link>http://scottonwriting.net/sowblog/archive/2011/01/06/jquery-usage-among-top-sites.aspx</link><pubDate>Wed, 05 Jan 2011 21:11:31 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:175821</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=175821</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/01/06/jquery-usage-among-top-sites.aspx#comments</comments><description>&lt;p&gt;If you use &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; on your website two things to consider are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;What version of jQuery to use, and&lt;/li&gt;    &lt;li&gt;How should the jQuery library be referenced from your website&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Concerning the first question…&lt;/strong&gt; Ideally everyone would use the latest and greatest version of jQuery. With each new version, the guys and gals building jQuery fix bugs, add new and useful features, and improve the library’s performance. But with any updated product there are potentially breaking changes with each new release, so upgrading carries with it some friction in the form of regression testing your script (and any plug-ins you are using). So then the question really becomes, when does the benefits of the new version outweigh the cost of upgrading – and that is a question you’ll have to answer for yourself.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Concerning the second question…&lt;/strong&gt; Rather than hosting the jQuery library locally, public facing websites should use a &lt;em&gt;Content Delivery Network (CDN)&lt;/em&gt;. In his blog post, &lt;a href="http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/"&gt;3 reasons why you should let Google host jQuery for you&lt;/a&gt;, &lt;a href="http://encosia.com/"&gt;Dave Ward&lt;/a&gt; provides an excellent summary of what a CDN is and why you should use one:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;A CDN — short for Content Delivery Network — distributes your static content across servers in various, diverse physical locations. When a user’s browser resolves the URL for these files, their download will automatically target the closest available server in the network. … &lt;/p&gt;    &lt;p&gt;Potentially the greatest (yet least mentioned) benefit of using … a CDN is that &lt;strong&gt;your users may not need to download jQuery at all&lt;/strong&gt;.&lt;/p&gt;    &lt;p&gt;No matter how aggressive your caching, if you’re hosting jQuery locally then your users must download it at least once. A user may very well have dozens of identical copies of jQuery-1.3.2.min.js in their browser’s cache, but those duplicate files will be ignored when they visit your site for the first time.&lt;/p&gt;    &lt;p&gt;On the other hand, when a browser sees multiple subsequent requests for the same … hosted version of jQuery, it understands that these requests are for the same file. … This means that even if someone visits hundreds of sites using the same hosted version of jQuery, &lt;strong&gt;they will only have to download it once&lt;/strong&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;(As an aside, a common concern I hear from clients when I suggest using a CDN is the fear that if the CDN goes offline then their site will break. The good news is that you can use a CDN as your primary source for jQuery and provide a local, fall-back version should the CDN be down. This Stackoverflow question - &lt;a href="http://stackoverflow.com/questions/1014203/best-way-to-use-googles-hosted-jquery-but-fall-back-to-my-hosted-library-on-goo"&gt;Best way to use Google's hosted jQuery, but fall back to my hosted library on Google fail&lt;/a&gt; – shows a couple of ways to accomplish this.)&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Dave Ward’s jQuery CDN Survey&lt;/h2&gt;  &lt;p&gt;In September 2010, Dave Ward ran an interesting experiment – he wrote some software that crawled the 200,000 most popular websites (as reported by &lt;a href="http://www.alexa.com/topsites"&gt;Alexa&lt;/a&gt;) and examined how they referenced the jQuery library (if at all) and to answer questions like:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Did they use a CDN? &lt;/li&gt;    &lt;li&gt;If so, which CDN? &lt;/li&gt;    &lt;li&gt;And so on.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In &lt;a href="http://encosia.com/2010/09/15/6953-reasons-why-i-still-let-google-host-jquery-for-me/"&gt;6,953 reasons why I still let Google host jQuery for me&lt;/a&gt; Dave shares his results, which I’ve summarized here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Only one top 1,000 ranked Alexa site uses the &lt;a href="http://www.asp.net/ajaxlibrary/cdn.ashx"&gt;Microsoft jQuery CDN&lt;/a&gt; (Microsoft.com)&lt;/li&gt;    &lt;li&gt;47 of the top 1,000 ranked Alexa sites use the Google CDN&lt;/li&gt;    &lt;li&gt;6,953 of the top 200,000 sites use the Google CDN&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The lesson to take away from Dave’s study is that you should use the Google CDN to host the jQuery library because using that CDN gives you the greatest likelihood that your visitors already have that version of the jQuery in their browser cache.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Repeating Dave’s Study&lt;/h2&gt;  &lt;p&gt;I decided to repeat Dave’s study so that I could see what interesting unreported information lie in the data. So I whipped up my own application to crawl the 13,247 top rated Alexa sites using the &lt;a href="http://htmlagilitypack.codeplex.com/"&gt;Html Agility Pack&lt;/a&gt; to grab all &lt;strong&gt;&amp;lt;script&amp;gt;&lt;/strong&gt; elements with an &lt;strong&gt;src&lt;/strong&gt; attribute, saving the &lt;strong&gt;src&lt;/strong&gt; path if it contained the substring “jquery”. Before showing you my data, let me repeat the same considerations/warnings Dave noted with regard to &lt;a href="http://encosia.com/2010/09/15/6953-reasons-why-i-still-let-google-host-jquery-for-me/"&gt;the accuracy of his survey&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I’ll be the first to admit that my approach is fraught with inaccuracies:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;Alexa&lt;/strong&gt; – Alexa itself isn’t a great ranking mechanism. It depends on toolbar-reported data and individual rankings must be taken with a grain of salt. However, I believe that aggregate trends across its top 200,000 sites represents a useful high-level view.&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;HTTP errors&lt;/strong&gt; – About 10% of the URLs I requested were unresolvable, unreachable, or otherwise refused my connection. A big part of that is due to Alexa basing its rankings on domains, not specific hosts. Even if a site only responds to www.domain.com, Alexa lists it as domain.com and my request to domain.com went unanswered.&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;jsapi&lt;/strong&gt; – Sites using Google’s jsapi loader and &lt;strong&gt;google.load()&lt;/strong&gt; weren’t counted in my tally, even though they do eventually reference the same googleapis.com URL. Both script loading approaches do count toward the same critical mass of caching, but my crawler’s regex doesn’t catch &lt;strong&gt;google.load()&lt;/strong&gt;.&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;Internal usage&lt;/strong&gt; – It’s not uncommon for sites to pare their landing pages down to the absolute bare minimum, only introducing more superfluous JavaScript references on inner pages that require them. Since I only analyzed root documents, I undercounted any sites taking that approach and using the Google CDN to host jQuery on those inner pages.&lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;That’s a very thorough way of saying, These results are not definitive, but are meant to give a general overview or understanding of the jQuery and CDN usage landscape.&lt;/p&gt;  &lt;p&gt;I leave you with what I found to be some interesting statistics…&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;Resurrecting the Microsoft CDN Bit By Bit&lt;/h3&gt;  &lt;p&gt;For die-hard supporters of the Microsoft CDN, you’ll be happy to know that there is now more than one top 1,000 ranked site that uses the CDN! In addition to Microsoft.com (rank 24), SparkStudios.com (rank 359) and XBox.com (rank 650) now also use the Microsoft CDN. However, none of these three sites (nor &lt;a href="http://www.asp.net"&gt;www.asp.net&lt;/a&gt; – rank 1,226) use &lt;a href="http://www.asp.net/ajaxlibrary/cdn.ashx#ajaxmicrosoftcom_renamed_to_ajaxaspnetcdncom_8"&gt;the suggested CDN URL&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The CDN used to use the microsoft.com domain name and has been changed to use the aspnetcdn.com domain name. This change was made to increase performance because when a browser referenced the microsoft.com domain it would send any cookies from that domain across the wire with each request. By renaming to a domain name other than microsoft.com performance can be increased by as much to 25%. &lt;strong&gt;Note ajax.microsoft.com will continue to function but ajax.aspnetcdn.com is recommended.&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Only two sites in my survey actually use the &lt;strong&gt;ajax.aspnetcdn.com&lt;/strong&gt; - wwwwwwwwwww.net (rank 7,542) and mmajunkie.com (rank 8,057). A total of 20 websites in my survey use &lt;strong&gt;ajax.microsoft.com&lt;/strong&gt;.&lt;/p&gt;  &lt;h3&gt;The Ten Most Popular Websites That Host jQuery at Google’s CDN&lt;/h3&gt;  &lt;p&gt;Here are the ten most popular sites that use jQuery hosted at the Google CDN, along with which version of jQuery they use:&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="125" align="center"&gt;         &lt;p align="center"&gt;&lt;strong&gt;Alexa Rank&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="144" align="center"&gt;&lt;strong&gt;Domain&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="129" align="center"&gt;&lt;strong&gt;jQuery Version&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="123" align="center"&gt;10&lt;/td&gt;        &lt;td valign="top" width="145" align="center"&gt;twitter.com&lt;/td&gt;        &lt;td valign="top" width="129" align="center"&gt;1.3.0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="122" align="center"&gt;98&lt;/td&gt;        &lt;td valign="top" width="146" align="center"&gt;fileserve.com&lt;/td&gt;        &lt;td valign="top" width="129" align="center"&gt;1.3.2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="122" align="center"&gt;111&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;taringa.net&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;117&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;twitpic.com&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;123&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;xtendmedia.com&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;145&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;stumbleupon.com&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;174&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;guardian.co.uk&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;175&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;stackoverflow.com&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;187&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;imgur.com&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="121" align="center"&gt;204&lt;/td&gt;        &lt;td valign="top" width="147" align="center"&gt;reference.com&lt;/td&gt;        &lt;td valign="top" width="128" align="center"&gt;1.4.2&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h3&gt;jQuery Version Popularity&lt;/h3&gt;  &lt;p&gt;The following graph shows the popularity of different versions of jQuery. The bar height represents the total number of sites in my survey that use the particular jQuery version, whereas the red portion indicates the number that host jQuery on the Google CDN.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://nbaweblog.com/images/sowblog/jQueryVersionUsage_4B832FA7.gif"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="jQueryVersionUsage" border="0" alt="jQueryVersionUsage" src="http://nbaweblog.com/images/sowblog/jQueryVersionUsage_thumb_75832DCF.gif" width="465" height="361" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Note that my method for determining the jQuery version was by examining the URL itself and did &lt;em&gt;not&lt;/em&gt; actually search for the version in the actual &lt;strong&gt;jQuery&lt;/strong&gt; file. Google’s CDN uses URLs that embed the version number. Microsoft’s CDN embeds the version number in the file name. For those that hosted jQuery locally (or with some other CDN), I searched both the URL and file name for a version string. The vast majority of sites that self-host jQuery did not include any version identification in the URL or filename (e.g., the file was hosted at a path like &lt;strong&gt;/scripts/jquery.min.js&lt;/strong&gt;) and therefore aren’t represented in this graph. However, I think the pattern here can be extrapolated to those site’s where the version number isn’t part of the URL/file name. Namely, version 1.3.2 and 1.4.2 are the most used.&lt;/p&gt;  &lt;p&gt;For the record, there are only two sites in my survey that use version 1.3.0 – Twitter.com (rank 10) and MagicBricks.com (rank 4,324).&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;jQuery Usage in Aggregate&lt;/h3&gt;  &lt;p&gt;Of the 13,247 sites surveyed, more than 35% of the sites (4,689) use jQuery…&lt;/p&gt;  &lt;p&gt;Of these 4,689 sites…&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Only 18% of these sites use the Google or Microsoft CDNs…&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;22 use the Microsoft CDN&lt;/li&gt;      &lt;li&gt;826 use the Google CDN&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=175821" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>Resetting Form Field Values in an ASP.NET WebForm</title><link>http://scottonwriting.net/sowblog/archive/2010/12/23/resetting-form-field-values-in-an-asp-net-webform.aspx</link><pubDate>Wed, 22 Dec 2010 23:14:13 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:174805</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=174805</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2010/12/23/resetting-form-field-values-in-an-asp-net-webform.aspx#comments</comments><description>&lt;p&gt;A recent question on Stackoverflow.com asked if there was &lt;a href="http://stackoverflow.com/questions/4504999/general-method-to-clearform-in-asp-net"&gt;a general method to clear a form in ASP.NET&lt;/a&gt;. The person asking the question had a form with many TextBox and DropDownList controls and wanted some way to be able to “reset” all of those values; specifically, the TextBoxes would be cleared out and the DropDownLists would have their first item selected.&lt;/p&gt;  &lt;p&gt;At first blush, this seems like a job for the &lt;em&gt;reset button&lt;/em&gt;. HTML has long supported the ability to reset a form by clicking a reset button, which is a button of type reset.&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;input type=&amp;quot;reset&amp;quot; value=&amp;quot;Reset Form!&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;The reset button’s functionality can also be invoked from JavaScript by calling the &lt;strong&gt;form&lt;/strong&gt; object’s &lt;strong&gt;reset&lt;/strong&gt; function. The following snippet of script checks to see if there is at least one form in the document and, if so, calls its &lt;strong&gt;reset&lt;/strong&gt; function:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;if (document.forms &amp;amp;&amp;amp; document.forms[0])
    document.forms[0].reset();&lt;/pre&gt;

&lt;h2&gt;&lt;/h2&gt;

&lt;h2&gt;The Problem with Reset…&lt;/h2&gt;

&lt;p&gt;However, there is a potential issue when resetting form values in an ASP.NET WebForms application using this approach. The issue arises because the reset button (or &lt;strong&gt;reset&lt;/strong&gt; function) does not clear out textboxes and return drop-down lists to their first value, but instead returns the forms fields &lt;em&gt;to their initial values&lt;/em&gt;. That is, if you have a page with a textbox whose markup contains a &lt;strong&gt;value&lt;/strong&gt; attribute, like:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;input type=&amp;quot;text&amp;quot; value=&amp;quot;Hello, World!&amp;quot; ... /&amp;gt;&lt;/pre&gt;

&lt;p&gt;And then a user changes the textbox’s text to “Goodbye!” and then clicks the reset button, the textbox does not go blank – rather, it reverts to “Hello, World!” In an ASP.NET WebForm application anytime there is a postback on the page – such as if there is a DropDownList whose &lt;strong&gt;AutoPostBack&lt;/strong&gt; property is set to True – the page’s markup is re-rendered and the text values and DropDownList selections made by the user are remembered because the re-rendered markup includes the user-entered values. Long story short, if you use the reset button approach described above and have a form where there are postbacks going on, if a user enters values into textboxes (or drop-downs), then does a postback, then clicks the reset button, the form fields will be reset to their values immediately after the postback and &lt;em&gt;not&lt;/em&gt; to empty textboxes.&lt;/p&gt;

&lt;h2&gt;jQuery to the Rescue!&lt;/h2&gt;

&lt;p&gt;The good news is that with just a couple of lines of jQuery code we can implement the reset functionality we desire, regardless of postbacks. The following two lines of script set the value of &lt;em&gt;all&lt;/em&gt; textboxes on the page to an empty string and set the &lt;strong&gt;selectedIndex&lt;/strong&gt; of &lt;em&gt;all&lt;/em&gt; drop-down lists on the page to be 0, which selects the first item:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(&amp;quot;input[type=text]&amp;quot;).val(&amp;quot;&amp;quot;);
$(&amp;quot;select&amp;quot;).attr('selectedIndex', 0);&lt;/pre&gt;

&lt;p&gt;That’s all there is to it! You could tinker with the selector syntax to limit the affected textboxes and drop-downs to those in a specific &lt;strong&gt;&amp;lt;div&amp;gt;&lt;/strong&gt; or form or whatnot; likewise, you could add additional lines of code if you need to reset checkboxes, radio buttons, or other input fields.&lt;/p&gt;

&lt;h2&gt;A Server-Side Approach…&lt;/h2&gt;

&lt;p&gt;If the client-side approach doesn’t cut it for you, you can opt to reset form fields using server-side logic. You could, of course, set the &lt;strong&gt;Text&lt;/strong&gt; property of each TextBox control to an empty string and clear the selections of all DropDownLists, but a more general approach is possible using recursion. Each ASP.NET control has a &lt;strong&gt;Controls&lt;/strong&gt;&amp;#160; property that contains its children controls. Put together, the controls in an ASP.NET page form a &lt;em&gt;control hierarchy&lt;/em&gt;. We can recurse through this control hierarchy, examining each control and modifying any TextBoxes and DropDownLists we come across.&lt;/p&gt;

&lt;p&gt;The following code snippet illustrates such a recursive method, &lt;strong&gt;ClearInputs&lt;/strong&gt;. Note that &lt;strong&gt;ClearInputs&lt;/strong&gt; is passed in a &lt;strong&gt;ControlCollection&lt;/strong&gt; object. This collection is enumerated and checked for TextBoxes and DropDownLists. If a TextBox is found, its &lt;strong&gt;Text&lt;/strong&gt; property is set to &lt;strong&gt;string.Empty&lt;/strong&gt;; if a DropDownList is found its &lt;strong&gt;ClearSelection&lt;/strong&gt; method is invoked. Finally, the &lt;strong&gt;ClearInputs&lt;/strong&gt; method is called again and passed the current control’s &lt;strong&gt;Controls&lt;/strong&gt; collection for it to be examined.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;void ClearInputs(ControlCollection ctrls)
{
    foreach (Control ctrl in ctrls)
    {
        if (ctrl is TextBox)
            ((TextBox)ctrl).Text = string.Empty;
        else if (ctrl is DropDownList)
            ((DropDownList)ctrl).ClearSelection();

        ClearInputs(ctrl.Controls);
    }
}&lt;/pre&gt;

&lt;p&gt;To reset &lt;em&gt;all&lt;/em&gt; TextBox and DropDownList values you’d call this method like so:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;ClearInputs(Page.Controls);&lt;/pre&gt;

&lt;p&gt;To reset the TextBoxes and DropDownLists in a particular control (such as a Panel), you’d call &lt;strong&gt;ClearInputs&lt;/strong&gt; passing in that control’s &lt;strong&gt;Controls&lt;/strong&gt; collection.&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=174805" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>Checking All CheckBoxes in a GridView Using jQuery</title><link>http://scottonwriting.net/sowblog/archive/2010/12/04/checking-all-checkboxes-in-a-gridview-using-jquery.aspx</link><pubDate>Fri, 03 Dec 2010 23:41:59 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:172968</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=172968</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2010/12/04/checking-all-checkboxes-in-a-gridview-using-jquery.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;How do I love thee, &lt;a href="http://en.wikipedia.org/wiki/Jquery"&gt;jQuery&lt;/a&gt;? Let me count the ways.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;In May 2006 I wrote an article on &lt;a href="http://www.4guysfromrolla.com/"&gt;4GuysFromRolla.com&lt;/a&gt; titled &lt;a href="http://www.4guysfromrolla.com/articles/053106-1.aspx"&gt;&lt;em&gt;Checking All CheckBoxes in a GridView Using Client-Side Script and a Check All CheckBox&lt;/em&gt;&lt;/a&gt;, in which I showed how to add a column of checkboxes to a GridView along with a checkbox in that column’s header that enabled the user to check/uncheck all checkboxes in one fell swoop. This check/uncheck all functionality was accomplished using JavaScript. &lt;/p&gt;  &lt;p&gt;While the JavaScript presented in the article worked then (and still works today, of course), it is a less than ideal approach for a couple of reasons. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;First, each checkbox in the grid is programmatically assigned a client-side &lt;strong&gt;onclick&lt;/strong&gt; event handler in the GridView’s &lt;strong&gt;DataBound&lt;/strong&gt; event handler that calls a function that determines whether to check or uncheck the checkbox in the head – having a client-side event handler defined directly in an HTML element violates the design goal of &lt;a href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript"&gt;unobstrusive JavaScript&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Second, because programmatically assigned client-side attributes are not remembered across postbacks and because these client-side attributes are only assigned when data is bound to the grid, the script is lost when there is a postback that &lt;em&gt;doesn’t&lt;/em&gt; cause the grid to have its data re-bound to it. Long story short, the check/uncheck all functionality stops working after such postbacks. I provide a workaround for this, but it’s extra steps, extra script, and another thing that you have to remember to do. &lt;/li&gt;    &lt;li&gt;Third, the solution entails quite a bit of script, much more than is necessary using modern JavaScript libraries. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;When I authored the article jQuery had not yet been released. Fortunately, today we have jQuery (and other JavaScript libraries) at our fingertips. &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; is a free, open-source JavaScript library created by &lt;a href="http://ejohn.org/"&gt;John Resig&lt;/a&gt;. In a nutshell, jQuery allows us to accomplish common client-side tasks with terse, readable script. With jQuery, I can rewrite the entire GridView check/uncheck all functionality with zero lines of server-side code and a scant 25 or so lines of JavaScript.&lt;/p&gt;  &lt;p&gt;To demonstrate jQuery’s power, consider a GridView with the following markup:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;asp:GridView ID=&amp;quot;gvProducts&amp;quot; runat=&amp;quot;server&amp;quot; ...&amp;gt;
    &amp;lt;Columns&amp;gt;
        &amp;lt;asp:TemplateField&amp;gt;
            &amp;lt;HeaderTemplate&amp;gt;
                &amp;lt;asp:CheckBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;chkAll&amp;quot; /&amp;gt;
            &amp;lt;/HeaderTemplate&amp;gt;
            &amp;lt;ItemTemplate&amp;gt;
                &amp;lt;asp:CheckBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;chkSelected&amp;quot; /&amp;gt;
            &amp;lt;/ItemTemplate&amp;gt;
        &amp;lt;/asp:TemplateField&amp;gt; 
        ...
    &amp;lt;/Columns&amp;gt;
&amp;lt;/asp:GridView&amp;gt;&lt;/pre&gt;

&lt;p&gt;Note the TemplateField – this is where the two CheckBox controls live. The CheckBox control in the HeaderTemplate (&lt;strong&gt;chkAll&lt;/strong&gt;) is the check/uncheck all checkbox, while the CheckBox control in the ItemTemplate (&lt;strong&gt;chkSelected&lt;/strong&gt;) is the checkbox that appears in each of the grid’s data rows.&lt;/p&gt;

&lt;p&gt;Now, I need script that does the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When one of the &lt;strong&gt;chkSelected &lt;/strong&gt;checkboxes is checked or unchecked, I need to determine whether the all option needs to be checked or unchecked. In the case where &lt;em&gt;all&lt;/em&gt; &lt;strong&gt;chkSelected &lt;/strong&gt;checkboxes are checked, I want to check &lt;strong&gt;chkAll&lt;/strong&gt;. Likewise, in the case when &lt;em&gt;any&lt;/em&gt; &lt;strong&gt;chkSelected &lt;/strong&gt;checkbox is &lt;em&gt;un&lt;/em&gt;checked, I want to uncheck &lt;strong&gt;chkAll&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;When &lt;strong&gt;chkAll&lt;/strong&gt; is checked or unchecked, I need to check or uncheck all &lt;strong&gt;chkSelected &lt;/strong&gt;checkboxes. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To address the first concern I created a function named &lt;strong&gt;CheckUncheckAllCheckBoxAsNeeded&lt;/strong&gt;. This function determines the total number of &lt;strong&gt;chkSelected&lt;/strong&gt; checkboxes in the grid and the number of checked &lt;strong&gt;chkSelected&lt;/strong&gt; checkboxes. If the two numbers match then &lt;strong&gt;chkAll&lt;/strong&gt; is checked, otherwise it’s unchecked.&lt;/p&gt;

&lt;pre class="brush: js;"&gt;function CheckUncheckAllCheckBoxAsNeeded() {
    var totalCheckboxes = $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkSelected']:checkbox&amp;quot;).size();
    var checkedCheckboxes = $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkSelected']:checkbox:checked&amp;quot;).size();

    if (totalCheckboxes == checkedCheckboxes) {
        $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkAll']:checkbox&amp;quot;).attr('checked', true);
    }
    else {
        $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkAll']:checkbox&amp;quot;).attr('checked', false);
    }
}&lt;/pre&gt;

&lt;p&gt;This function is executed whenever one of the &lt;strong&gt;chkSelected &lt;/strong&gt;checkboxes is checked or unchecked. This event wiring is handled in the &lt;strong&gt;$(document).ready&lt;/strong&gt; event handler. Also, the &lt;strong&gt;CheckUncheckAllCheckBoxAsNeeded &lt;/strong&gt;function is called right off the bat in case the grid’s checkboxes are already all checked when the page loads.&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(document).ready(function () {
    $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkSelected']:checkbox&amp;quot;).click(CheckUncheckAllCheckBoxAsNeeded);

    ...

    CheckUncheckAllCheckBoxAsNeeded();
});&lt;/pre&gt;

&lt;p&gt;Finally, we need to check/uncheck all &lt;strong&gt;chkSelected &lt;/strong&gt;checkboxes when &lt;strong&gt;chkAll&lt;/strong&gt; is checked or unchecked. This logic is also in the &lt;strong&gt;$(document).ready&lt;/strong&gt; event handler (where the ellipsis is positioned in the above snippet).&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkAll']:checkbox&amp;quot;).click(function () {
    if ($(this).is(':checked'))
        $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkSelected']:checkbox&amp;quot;).attr('checked', true);
    else
        $(&amp;quot;#&amp;lt;%=gvProducts.ClientID%&amp;gt; input[id*='chkSelected']:checkbox&amp;quot;).attr('checked', false);
});&lt;/pre&gt;

&lt;p&gt;Pretty neat and a whole heck of a lot simpler than the technique I initially showcased in &lt;a href="http://www.4guysfromrolla.com/articles/053106-1.aspx"&gt;&lt;em&gt;Checking All CheckBoxes in a GridView Using Client-Side Script and a Check All CheckBox&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt; A more detailed look at this code, along with a downloadable working example, will be on 4Guys within the next couple of weeks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE [2010-12-07]:&lt;/strong&gt; A 4Guys article that provides much more detail and screen shots and a downloadable demo is now available: &lt;em&gt;&lt;a href="http://www.4guysfromrolla.com/articles/120810-1.aspx"&gt;Checking All Checkboxes in a GridView Using jQuery&lt;/a&gt;&lt;/em&gt;. Also, special thanks to &lt;a href="http://elijahmanor.com/"&gt;Elijah Manor&lt;/a&gt;, who offered a number of suggestions on how to improve and tighten up my jQuery script.&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=172968" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>Use jQuery to Open “External” URLs in a New Browser Window</title><link>http://scottonwriting.net/sowblog/archive/2010/09/15/use-jquery-to-open-external-urls-in-a-new-browser-window.aspx</link><pubDate>Tue, 14 Sep 2010 23:24:14 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:169548</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=169548</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2010/09/15/use-jquery-to-open-external-urls-in-a-new-browser-window.aspx#comments</comments><description>&lt;p&gt;As any web developer knows, the HTML anchor element (&lt;strong&gt;&amp;lt;a&amp;gt;&lt;/strong&gt;), when used in the following form:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;a href=&amp;quot;http://www.scottonwriting.net&amp;quot;&amp;gt;Click Me!&amp;lt;/a&amp;gt;&lt;/pre&gt;

&lt;p&gt;creates a hyperlink with the text “Click Me!” that, when clicked, whisks the user to the specified &lt;strong&gt;href&lt;/strong&gt; value, in this case my blog, &lt;a href="http://scottonwriting.net/sowblog/"&gt;ScottOnWriting.NET&lt;/a&gt;. By default, clicking a link opens the specified URL in the user’s existing browser window; however, using the &lt;strong&gt;&amp;lt;a&amp;gt;&lt;/strong&gt; tag’s &lt;strong&gt;target&lt;/strong&gt; attribute it is possible to open the URL in a new window. Adding &lt;strong&gt;target=”_blank”&lt;/strong&gt; to the &lt;strong&gt;&amp;lt;a&amp;gt;&lt;/strong&gt; element will cause the browser to open the link in a new browser window:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;a target=&amp;quot;_blank&amp;quot; href=&amp;quot;http://www.scottonwriting.net&amp;quot;&amp;gt;Click Me!&amp;lt;/a&amp;gt;&lt;/pre&gt;

&lt;p&gt;Some websites like to have all links to “external” web pages open in a new browser window, while having “internal” links open in the same browser window. I use the words external and internal in quotes here because their definitions can depend on the website. Some websites would consider URL that specifies a hostname in the &lt;strong&gt;href &lt;/strong&gt;to be “external” – such as &lt;a href="http://www.4guysfromrolla.com/ScottMitchell"&gt;http://www.4guysfromrolla.com/ScottMitchell&lt;/a&gt; – while URLs that lack a hostname would be “internal” – such as &lt;a href="http://scottonwriting.net/sowblog/archive/2010/09.aspx"&gt;/sowblog/archive/2010/09.aspx&lt;/a&gt;. Other websites might want links to partner websites to still be considered “internal,” even though they include a hostname.&lt;/p&gt;

&lt;p&gt;I recently worked on a project where the client wanted this kind of behavior. He had hundreds of existing web pages, each with dozens of links, all of which lacked a &lt;strong&gt;target&lt;/strong&gt; attribute. He didn’t want to have to go through the pages and links, one at a time, adding the &lt;strong&gt;target&lt;/strong&gt; attribute where needed. To help address this problem I wrote a very simple &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; plugin that can be used to automatically add a &lt;strong&gt;target&lt;/strong&gt; attribute to “external” URLs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; &lt;/font&gt;&lt;font color="#000000"&gt;I know just enough JavaScript and jQuery to be dangerous, so please don’t presume my plugin is in any way an example of best practices. In fact, if you have any feedback or suggestions on how to improve it, please let me know in the comments!&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The plugin defines a single function, &lt;strong&gt;UrlTarget([whiteList], [targetName])&lt;/strong&gt;. The following line of code (which you’d place in &lt;strong&gt;$(document).ready&lt;/strong&gt;, presumably) will add a &lt;strong&gt;target=”_blank”&lt;/strong&gt; attribute to all “external” links. Without specifying a &lt;em&gt;whiteList&lt;/em&gt;, all URLs that start with &lt;strong&gt;http://&lt;/strong&gt; or &lt;strong&gt;https://&lt;/strong&gt; are considered external, whereas all that don’t are considered internal:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(&amp;quot;a&amp;quot;).UrlTarget();&lt;/pre&gt;

&lt;p&gt;If you want certain hostnames to be considered “internal,” simply specify one or more regular expressions in an array as the &lt;em&gt;whiteList&lt;/em&gt;. If the hostname for a hyperlink matches on any of the regular expressions then it is considered “internal” and the &lt;strong&gt;target&lt;/strong&gt; attribute is &lt;em&gt;not&lt;/em&gt; added. For instance, to have all URLs that point to 4GuysFromRolla.com or ScottOnWriting.NET considered “internal,” you’d specify the following &lt;em&gt;whiteList&lt;/em&gt; value:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(&amp;quot;a&amp;quot;).UrlTarget([
    '^(www\.)?4guysfromrolla\.com$',
    '^(www\.)?scottonwriting\.net$'
]);&lt;/pre&gt;

&lt;p&gt;If you specify a &lt;em&gt;targetName&lt;/em&gt; value, the &lt;strong&gt;target&lt;/strong&gt; attribute added to external URLs is assigned that &lt;em&gt;targetName&lt;/em&gt;. If this input parameter is omitted then the target value “_blank” is used. Also, note that if a hyperlink with an external URL already has its &lt;strong&gt;target&lt;/strong&gt; attribute set then it is not overwritten by &lt;strong&gt;UrlTarget&lt;/strong&gt;. Likewise, if a hyperlink with an internal URL has a &lt;strong&gt;target&lt;/strong&gt; attribute set, it is not removed.&lt;/p&gt;

&lt;p&gt;To use my plugin you’ll need to download the script at &lt;a title="http://scottonwriting.net/sowblog/CodeProjectFiles/urlTarget.js" href="http://scottonwriting.net/sowblog/CodeProjectFiles/urlTarget.js"&gt;http://scottonwriting.net/sowblog/CodeProjectFiles/urlTarget.js&lt;/a&gt;, save it to your website, and then reference it via a &lt;strong&gt;&amp;lt;script&amp;gt;&lt;/strong&gt; tag. I’ve got a demo online available at &lt;a title="http://scottonwriting.net/sowblog/CodeProjectFiles/JQueryLinksDemo.htm" href="http://scottonwriting.net/sowblog/CodeProjectFiles/JQueryLinksDemo.htm"&gt;http://scottonwriting.net/sowblog/CodeProjectFiles/JQueryLinksDemo.htm&lt;/a&gt;, which has the following JavaScript:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;urlTarget.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
        $(document).ready(function() {
            $(&amp;quot;a&amp;quot;).UrlTarget([
                '^(www\.)?4guysfromrolla\.com$',
                '^(www\.)?scottonwriting\.net$'
            ]);
        });
&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;p&gt;Note that both the jQuery and &lt;strong&gt;urlTarget.js&lt;/strong&gt; libraries must be referenced.&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=169548" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>Adding a RESTful Service to My Boggle Solver</title><link>http://scottonwriting.net/sowblog/archive/2010/09/11/adding-a-restful-service-to-my-boggle-solver.aspx</link><pubDate>Fri, 10 Sep 2010 22:47:20 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:169410</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=169410</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2010/09/11/adding-a-restful-service-to-my-boggle-solver.aspx#comments</comments><description>&lt;p align="center"&gt;&lt;font color="#ff0000" size="5"&gt;This blog post has been deprecated. Please see &lt;a href="http://www.4guysfromrolla.com/articles/112410-1.aspx"&gt;Updating My Online Boggle Solver Using jQuery Templates and WCF&lt;/a&gt; for an updated discussion on the solver service, the data it returns, and how to call it from a web page.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;My immediate and extended family enjoys playing games, and one of our favorites is Boggle. &lt;a href="http://en.wikipedia.org/wiki/Boggle"&gt;Boggle&lt;/a&gt; is a word game trademarked by Parker Brothers and Hasbro that involves several players trying to find as many words as they can in a 4x4 grid of letters. At the end of the game, players compare the words they found. During this comparison I've always wondered what words we may have missed. Was there some elusive 10-letter word that no one unearthed? Did we only discover 25 solutions when there were 200 or more?&lt;/p&gt;  &lt;p&gt;To answer these questions I created a Boggle solver web application (back in 2008) that prompts a user for the letters in the Boggle board and then recursively explores the board to locate (and display) all available solutions. This &lt;a href="http://fuzzylogicinc.net/Boggle/"&gt;Boggle solver&lt;/a&gt; is available online - &lt;a href="http://fuzzylogicinc.net/Boggle/"&gt;fuzzylogicinc.net/Boggle&lt;/a&gt;. My family uses it every time we get together and play Boggle. For more information on how it works and to get your hands on the code, check out my article, &lt;a href="http://www.4guysfromrolla.com/articles/040208-1.aspx"&gt;Creating an Online Boggle Solver&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Recently, I’ve been working on some projects that have involved creating &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_services"&gt;RESTful web services&lt;/a&gt; using &lt;a href="http://msdn.microsoft.com/en-us/netframework/aa663324.aspx"&gt;WCF&lt;/a&gt;. Being Friday, I decided to have a little fun and add a RESTful interface to the Boggle solver. This was actually quite easy to do and took all of 5 minutes.&lt;/p&gt;  &lt;h2&gt;Creating the Boggle Solver Service&lt;/h2&gt;  &lt;p&gt;I started by adding a new item to my website of type WCF Service, naming it &lt;strong&gt;Solver.svc&lt;/strong&gt;. This created three files:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Solver.scr &lt;/li&gt;    &lt;li&gt;ISolver.cs &lt;/li&gt;    &lt;li&gt;Solver.cs &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In the contract (&lt;strong&gt;ISolver.cs&lt;/strong&gt;) I added a single method, &lt;strong&gt;Solve&lt;/strong&gt;, that accepts two inputs: a string representing the board and a string indicating the minimum number of letters for a word to be considered a solution. (Boggle rules allow for words of three letters or more, but house rules only count words that are four letters or longer.) I then used the &lt;strong&gt;WebGet&lt;/strong&gt; attribute to indicate that the board and length input parameters would be specified via the querystring fields &lt;strong&gt;BoardID&lt;/strong&gt; and &lt;strong&gt;Length&lt;/strong&gt;, and that the resulting output should be formatted as &lt;a href="http://json.org/"&gt;JSON&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;[ServiceContract]
public interface ISolver
{
    [OperationContract]
    [WebGet(UriTemplate = &amp;quot;?BoardID={board}&amp;amp;Length={length}&amp;quot;, ResponseFormat=WebMessageFormat.Json)]
    BoggleWordDTO[] Solve(string board, string length);
}&lt;/pre&gt;

&lt;p&gt;Note that the &lt;strong&gt;Solve&lt;/strong&gt; method returns an array of &lt;strong&gt;BoggleWordDTO&lt;/strong&gt; objects. This is a new class I created to represent the data to transmit from the service. This class has two properties:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Word&lt;/strong&gt; – a string value that represents a word found in the Boggle board, and &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;Score&lt;/strong&gt; – the score for that solution. According to the official rules, three and four letter words are worth 1 point, five letter words are worth 2, six letter words worth 3, seven letter words worth 5, and eight letter words and longer worth 11. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Solve&lt;/strong&gt; method implementation (&lt;strong&gt;Solver.cs&lt;/strong&gt;) is pretty straightforward. It starts with a bit of error checking to ensure that the passed in board and letter information is kosher. Next, it creates a &lt;strong&gt;BoggleBoard&lt;/strong&gt; object, specifying the minimum number of letters for a solution and the board contents. Then the BoggleBoard object’s &lt;strong&gt;Solve&lt;/strong&gt; method is invoked, which performs the recursion and computes the set of solutions (as an object of type &lt;strong&gt;BoggleWordList&lt;/strong&gt;). The solutions are then converted into an array of &lt;strong&gt;BoggleWordDTO&lt;/strong&gt; objects, which is then returned to the client.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public BoggleWordDTO[] Solve(string board, string length)
{
    ...

    // Create the BoggleBoard
    BoggleBoard bb = new BoggleBoard(
                        letters,
                        board[0].ToString(), ..., board[15].ToString()
                    );

    // Solve the Boggle board
    var solutions = bb.Solve();

    // Populate and return an array of BoggleWordDTO objects
    return solutions
                .Select(s =&amp;gt; new BoggleWordDTO()
                {
                    Word = s.Word,
                        Score = s.Score
                })
                .ToArray();
}&lt;/pre&gt;

&lt;p&gt;Because the service is configured to return the data using JSON, the results are serialized into a JSON array.&lt;/p&gt;

&lt;p&gt;In addition to creating the Solver-related files and writing the code I noted, I also had to add &lt;strong&gt;&amp;lt;system.serviceModel&amp;gt;&lt;/strong&gt; configuration to &lt;strong&gt;Web.config&lt;/strong&gt; to permit HTTP access to the service &lt;strike&gt;and to enable ASP.NET compatibility. The reason I had to enable ASP.NET compatibility is because the dictionary used by the solver is a text file stored on disk, and the solver gets the path to that text file using &lt;strong&gt;Server.MapPath&lt;/strong&gt; (namely, &lt;strong&gt;HttpContext.Current.Server.MapPath(“…”)&lt;/strong&gt;). Without ASP.NET compatibility, &lt;strong&gt;HttpContext.Current&lt;/strong&gt; is null when the service attempts to solve and then the call to &lt;strong&gt;Server.MapPath&lt;/strong&gt; blows up.&lt;/strike&gt; Also, I had to specify the &lt;strong&gt;Factory&lt;/strong&gt; attribute in the &lt;strong&gt;&amp;lt;%@ ServiceHost %&amp;gt; &lt;/strong&gt;directive of the &lt;strong&gt;Solver.svc&lt;/strong&gt; file. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[UPDATE: 2010-09-10]&lt;/strong&gt; &lt;a href="http://allben.net/"&gt;Ben Amada&lt;/a&gt; posted a helpful comment pointing me to the existence of the &lt;strong&gt;HostingEnvironment.MapPath&lt;/strong&gt; method, which does the same work as &lt;strong&gt;Server.MapPath&lt;/strong&gt; but doesn’t require an &lt;strong&gt;HttpContext&lt;/strong&gt; object. I updated this code accordingly. I also updated the code that cached the dictionary in memory, replacing the use of &lt;strong&gt;HttpContext.Current.Cache&lt;/strong&gt; with &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpruntime.cache.aspx"&gt;HttpRuntime.Cache&lt;/a&gt;, which I &lt;a href="http://weblogs.asp.net/pjohnson/archive/2006/02/06/437559.aspx"&gt;probably should have been using all along&lt;/a&gt;&lt;strong&gt;&lt;/strong&gt;. The code has been updated. Thanks, Ben!&lt;/p&gt;

&lt;h2&gt;Using the Boggle Solver Service&lt;/h2&gt;

&lt;p&gt;To use the service, just point your browser (or your code/script) to:&amp;#160; &lt;strong&gt;&lt;a href="http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=board&amp;amp;Length=length"&gt;http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=&lt;em&gt;board&lt;/em&gt;&amp;amp;Length=&lt;em&gt;length&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt;. The &lt;em&gt;board&lt;/em&gt; value should be entered as a string of the characters in the Boggle board, starting from the upper left corner and reading to the right and down. For example, if you had the board:&lt;/p&gt;

&lt;pre&gt;r e i b
t m f w
i r a e
r h s t &lt;/pre&gt;

&lt;p&gt;You would use a &lt;em&gt;board&lt;/em&gt; value of &lt;strong&gt;reibtmfwiraerhst&lt;/strong&gt;. &lt;em&gt;letter&lt;/em&gt; should be a number between 3 and 6, inclusive.&lt;/p&gt;

&lt;p&gt;So, to find all solutions to the above board that are four or more letters, you’d visit: &lt;a title="http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=reibtmfwiraerhst&amp;amp;Length=4" href="http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=reibtmfwiraerhst&amp;amp;Length=4"&gt;http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=reibtmfwiraerhst&amp;amp;Length=4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Doing so would return the following (abbreviated) JSON:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[{&amp;quot;Score&amp;quot;:1,&amp;quot;Word&amp;quot;:&amp;quot;amir&amp;quot;},{&amp;quot;Score&amp;quot;:2,&amp;quot;Word&amp;quot;:&amp;quot;amirs&amp;quot;},{&amp;quot;Score&amp;quot;:1,&amp;quot;Word&amp;quot;:&amp;quot;awes&amp;quot;},{&amp;quot;Score&amp;quot;:1,&amp;quot;Word&amp;quot;:&amp;quot;bier&amp;quot;},{&amp;quot;Score&amp;quot;:1,&amp;quot;Word&amp;quot;:&amp;quot;ears&amp;quot;},{&amp;quot;Score&amp;quot;:1,&amp;quot;Word&amp;quot;:&amp;quot;east&amp;quot;},...]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The above JSON represents an array of objects, where each object has two properties, &lt;strong&gt;Score&lt;/strong&gt; and &lt;strong&gt;Word&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So how can this service be used? Well, with a bit of JavaScript you can call the service from a browser and display the results dynamically. I’ve included a rudimentary example in the download (which you can find at the end of this blog post) that prompts the user to enter the 16 characters for the board and the minimum number of letters. It then uses &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;’s &lt;a href="http://api.jquery.com/jQuery.getJSON/"&gt;&lt;strong&gt;getJSON&lt;/strong&gt; function&lt;/a&gt; to make a call to the service and get the data back. The JSON array is then enumerated and a series of list items are constructed, showing each solution in a bulleted list.&lt;/p&gt;

&lt;p&gt;Here is the web page when you visit it and enter a boggle board and the minimum number of letters (but before you click the “Find All Words!” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://nbaweblog.com/images/sowblog/BoggleBoard2_0C860A56.gif"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="BoggleBoard2" border="0" alt="BoggleBoard2" src="http://nbaweblog.com/images/sowblog/BoggleBoard2_thumb_209F26DF.gif" width="547" height="312" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Clicking the “Find All Words!” button executes the following jQuery script:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$.getJSON(
    &amp;quot;Solver.svc&amp;quot;,
    {
        &amp;quot;BoardID&amp;quot;: $(&amp;quot;#board&amp;quot;).val(),
        &amp;quot;Length&amp;quot;: $(&amp;quot;#length&amp;quot;).val()
    },
    function (words) {
        var output = &amp;quot;No solutions exists!&amp;quot;;

        if (words.length &amp;gt; 0) {
            output = &amp;quot;&amp;lt;h2&amp;gt;&amp;quot; + words.length + &amp;quot; Solutions!&amp;lt;/h2&amp;gt;&amp;lt;ul&amp;gt;&amp;quot;;

            var score = 0;

            $.each(words, function (index, word) {
                score += word.Score;
                output += &amp;quot;&amp;lt;li&amp;gt;&amp;quot; + word.Word + &amp;quot; (&amp;quot; + word.Score + &amp;quot; points)&amp;lt;/li&amp;gt;&amp;quot;;
            });

            output += &amp;quot;&amp;lt;/ul&amp;gt;&amp;lt;p&amp;gt;Total score = &amp;quot; + score + &amp;quot; points!&amp;lt;/p&amp;gt;&amp;quot;;
        }

        $(&amp;quot;#solutions&amp;quot;).html(output);
    }
);&lt;/pre&gt;

&lt;p&gt;Note that the above script calls the &lt;strong&gt;Solver.svc&lt;/strong&gt; service passing in the BoardID and Length querystring parameters. The textbox where the user enters the board has an &lt;strong&gt;id&lt;/strong&gt; of &lt;strong&gt;board&lt;/strong&gt; while the minimum letter drop-down list has an &lt;strong&gt;id&lt;/strong&gt; of &lt;strong&gt;length&lt;/strong&gt;. The function defined in the call is what is executed when the result comes back successfully. Here, the jQuery &lt;a href="http://api.jquery.com/each/"&gt;&lt;strong&gt;each &lt;/strong&gt;function&lt;/a&gt; is used to enumerate the array and build up a string of HTML in a variable named &lt;strong&gt;output&lt;/strong&gt; that produces a bulleted list of solutions. The total number of solutions and total number of points is also included in &lt;strong&gt;output&lt;/strong&gt;. Finally, the contents of &lt;strong&gt;output&lt;/strong&gt; are dumped to a &lt;strong&gt;&amp;lt;div&amp;gt;&lt;/strong&gt; on the page with an &lt;strong&gt;id&lt;/strong&gt; of &lt;strong&gt;solutions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the page after clicking the “Find All Words!” button. Nothing fancy, of course, and not nearly as useful or eye-pleasing as &lt;a href="http://fuzzylogicinc.net/Boggle/EnterBoard.aspx?BoardID=reibtmfwiraerhst&amp;amp;Length=4"&gt;the website’s results page&lt;/a&gt;, but it does illustrate one way you can use the Boggle &lt;strong&gt;Solver.svc&lt;/strong&gt; service.&lt;/p&gt;

&lt;p align="center"&gt;&lt;a href="http://nbaweblog.com/images/sowblog/BoggleBoard3_71D96E3C.gif"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="BoggleBoard3" border="0" alt="BoggleBoard3" src="http://nbaweblog.com/images/sowblog/BoggleBoard3_thumb_1EEE5B0B.gif" width="353" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;Download the Code!&lt;/h2&gt;

&lt;p&gt;You can download the complete Boggle solver engine, web application, and WCF RESTful service from &lt;a title="http://aspnet.4guysfromrolla.com/code/BoggleSolver.zip" href="http://aspnet.4guysfromrolla.com/code/BoggleSolver.zip"&gt;http://aspnet.4guysfromrolla.com/code/BoggleSolver.zip&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Programming, and Happy Boggling!&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=169410" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><category domain="http://scottonwriting.net/sowblog/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><category domain="http://scottonwriting.net/sowblog/archive/tags/Web+Services/default.aspx">Web Services</category><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item><item><title>I’m Teaching Two Upcoming Training Classes in San Diego</title><link>http://scottonwriting.net/sowblog/archive/2010/08/19/i-m-teaching-two-upcoming-training-classes-in-san-diego.aspx</link><pubDate>Thu, 19 Aug 2010 17:45:32 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:168128</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=168128</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2010/08/19/i-m-teaching-two-upcoming-training-classes-in-san-diego.aspx#comments</comments><description>&lt;p&gt;Once a year (or so) I teach a handful of one-day, four hour classes in San Diego on various ASP.NET topics. I’ve got &lt;a href="http://www.fuzzylogicinc.net/InDepth/Outline.aspx"&gt;two such classes&lt;/a&gt; lined up for Saturday, September 11:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;&lt;a href="http://fuzzylogicinc.net/InDepth/Outline.aspx?coid=25ccc9a6-bdef-4265-888e-7111cc5660ca"&gt;Get Started with ASP.NET MVC&lt;/a&gt;&lt;/strong&gt; – &lt;em&gt;8 AM to Noon       &lt;br /&gt;&lt;/em&gt;Traditionally, ASP.NET websites have been designed using the Web Forms model; &lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC&lt;/a&gt; is an alternative model that uses the Model-View-Controller pattern. In a nutshell, ASP.NET MVC gives developers much finer control over the markup rendered by their web pages, a greater and clearer separation of concerns, better testability, and cleaner, more SEO-friendly URLs. This four hour class introduces ASP.NET MVC, explores how to build ASP.NET MVC applications, covers key differences between Web Forms and ASP.NET MVC, and highlights the benefits of ASP.NET MVC. During the class, we will build a real-world ASP.NET MVC application from start to finish.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;a href="http://fuzzylogicinc.net/InDepth/Outline.aspx?coid=bfb9f765-b5ca-4886-a8e6-b4d80668e18f"&gt;Build Responsive Web Applications with Ajax, jQuery, and ASP.NET&lt;/a&gt;&lt;/strong&gt; – &lt;em&gt;1 to 5 PM       &lt;br /&gt;&lt;/em&gt;Ajax-enabled web applications use JavaScript and streamlined client/server communications to offer a highly interactive and responsive user experience. &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; is a free, popular and powerful JavaScript library that ships with Visual Studio 2010 and greatly simplifies building Ajax-enabled web applications. This four hour class examines key Ajax concepts and techniques and walks through building a real-world Ajax-enabled web application using jQuery and ASP.NET.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Each class is $249 per student, but there is an ongoing early bird special price of $199 (available until August 28th). Students receive electronic access and printed copies of the training materials. Coffee, snacks and lunch are provided. The classes are held at the Sorrento Mesa Center (&lt;a href="http://fuzzylogicinc.net/InDepth/Directions.aspx"&gt;directions&lt;/a&gt;), which is located in Sorrento Valley and has free parking.&lt;/p&gt;  &lt;p&gt;If you are interested in signing up or would like detailed course outlines, visit &lt;a href="http://www.fuzzylogicinc.net/InDepth"&gt;www.fuzzylogicinc.net/InDepth&lt;/a&gt;. If you have any questions about the class, material, or logistics, shoot me an email at &lt;a href="mailto:mitchell@4guysfromrolla.com"&gt;mitchell@4guysfromrolla.com&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Hope to see you there!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Signup: &lt;/strong&gt;&lt;a href="http://www.fuzzylogicinc.net/InDepth"&gt;www.fuzzylogicinc.net/InDepth&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=168128" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><category domain="http://scottonwriting.net/sowblog/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category></item></channel></rss>