Blog Archives

3 reasons why you should let Google host jQuery

All too often, I find code similar to this when inspecting the source for public websites that use jQuery:

<script type="text/javascript" src="/js/jQuery.min.js"></script>

If you’re doing this on a public facing* website, you are doing it wrong.

Instead, I urge you to use the Google AJAX Libraries content delivery network to serve jQuery to your users directly from Google’s network of datacenters. Doing so has several advantages over hosting jQuery on your server(s): decreased latency, increased parallelism, and better caching.

In this post, I will expand upon those three benefits of Google’s CDN and show you a couple examples of how you can make use of the service.

* None of this is relevant to internal applications served over a LAN. It would be as likely harm performance as improve it.

Decreased Latency

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.

In the case of Google’s AJAX Libraries CDN, what this means is that any users not physically near your server will be able to download jQuery faster than if you force them to download it from your arbitrarily located server.

There are a handful of CDN services comparable to Google’s, but it’s hard to beat the price of free! This benefit alone could decide the issue, but there’s even more.

Increased parallelism

To avoid needlessly overloading servers, browsers limit the number of connections that can be made simultaneously. Depending on which browser, this limit may be as low as two connections per hostname.

Using the Google AJAX Libraries CDN eliminates one request to your site, allowing more of your local content to downloaded in parallel. It doesn’t make a gigantic difference for users with a six concurrent connection browser, but for those still running a browser that only allows two, the difference is noticeable.

Better caching

Potentially the greatest (yet least mentioned) benefit of using the Google AJAX Libraries CDN is that your users may not need to download jQuery at all.

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.2.6.min.js in their browser’s cache, but those duplicate files will be ignored when they visit your site for the first time.

On the other hand, when a browser sees multiple subsequent requests for the same Google hosted version of jQuery, it understands that these requests are for the same file. Not only will Google’s servers return a 304 “Not Modified” response if the file is requested again, but also instructs the browser to cache the file for up to one year.

This means that even if someone visits hundreds of sites using the same Google hosted version of jQuery, they will only have to download it once.

Implementation

By now, you’re probably convinced that the Google AJAX Libraries CDN is the way to go for your public facing sites that use jQuery. So, let me show you how you can put it to use.

Of the two methods available, this option is the one that Google recommends:

The google.load() approach offers the most functionality and performance.

For example:

<script type="text/javascript"
        src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
  // You may specify partial version numbers, such as "1" or "1.2",
  //  with the same result. Doing so will automatically load the 
  //  latest version matching that partial revision pattern 
  //  (i.e. both 1 and 1.2 would load 1.2.6 today).
  google.load("jquery", "1.2.6");
 
  google.setOnLoadCallback(function() {
    // Place init code here instead of $(document).ready()
  });
</script>

While there’s nothing wrong with this, and it is definitely an improvement over hosting jQuery locally, I don’t agree that it offers the best performance.

Firebug image of the longer loading time caused by jsapi

As you can see, loading, parsing, and executing jsapi delays the actual jQuery request. Not usually by a very large amount, but it’s an unnecessary delay. Tenths of a second may not seem significant, but they add up very quickly.

Worse, you cannot reliably use a $(document).ready() handler in conjunction with this load method. The setOnLoadCallback() handler is a requirement.

Back to basics

In the face of those drawbacks to the google.load() method, I’d suggest using a good ‘ol fashioned <script> declaration. Google does support this method as well.

For example:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    // This is more like it!
  });
</script>

Not only does this method avoid the jsapi delay, but it also eliminates three unnecessary HTTP requests. I prefer and recommend this method.

Conclusion

According to a recent study, Google will consume 16.5% of all consumer Internet capacity in the United States during 2008. I think it’s fair to say that those guys know how to efficiently serve up some content.

The opportunity to let the pros handle part of your site’s JavaScript footprint free of charge is too good to pass up. As often as even returning users experience the “empty cache” load time of your site, it’s important to take advantage of an easy optimization like this one.

What do you think? Are you using the Google AJAX Libraries CDN on your sites? Can you think of a scenario where the google.load() method would perform better than simple <script> declaration?

I wonder why hasn’t this been done for MicrosoftAjax.js?

 

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

 

3 reasons why you should let Google host jQuery for you

CSSHttpRequest – cross browser AJAX without JSON

Because XMLHttpRequest only functions in a same-origin model, the main alternatives have been to either proxy the XML request server-side, or transfer javascript arrays via JSON (since cross-domain script calls are allowed). CSSHttpRequest is another method for performing cross-domain AJAX-style requests, but instead of running loading a remote Javascript file, CSS is used as the transport, and data is encoded inside of urls in @import statements.

A request is invoked using the CSSHttpRequest.get(url, callback) function:

    CSSHttpRequest.get(
        "http://www.nb.io/hacks/csshttprequest/hello-world/",
        function(response) { alert(response); }
    );

Data is encoded on the server into URI-encoded 2KB chunks and serialized into CSS @import rules with a modified about: URI scheme. The response is decoded and returned to the callback function as a string:

    @import url(about:chr:Hello%20World!);

CSSHttpRequest is open source under an Apache License (Version 2.0).

This is a pretty cool alternative—it seems to be a much safer way to do things than blindly executing javascript from servers not under your control. It's somewhat like what XMLHttpRequest could have offered if it weren't limited by the same-origin policy (though in a more roundabout way).

It still begs the question: why on earth is XMLHttpRequest limited by a same-origin policy, especially when it forces developers to adopt more dangerous methods for cross domain communication?

CSSHttpRequest

A Dynamic Menu For Your Dynamic Data

So I am still playing around with building a Northwind Dynamic Data web site. Tonight I thought it would be interesting to see what it would take to create a menu for navigating the tables in the site. I was particularly interested in seeing if I could get some grouping or categorization to the metadata so I could create a multi-leveled menu. It turns out it wasn’t too difficult at all (see the screen shot below – the menu is on the left). I have my tables organized into 4 categories: Sales, People, Products and Reports. And the cool thing is that this menu is completely dynamic. You can add, remove or reorganize the categories without touching the UI. And depending where you are keeping your metadata you could even do this without recompiling your app. The grouping is automatically discovered from the metadata and the menu is built solely off the it so everything ‘just works’.

Besides adding the grouping information, I also tagged each of my tables with a custom description that I am displaying under the grids title. Nothing too complicated, but still interesting. Read on if you are curious how I did this and don’t forget to check out the download.

Download

image

Adding Category and Description

When MetaTable objects are created, the Dynamic Data components automatically populate the the MetaTable’s DisplayName property from the DisplayNameAttribute that is hanging off the metadata class (if you are using the default metadata provider). This is why you see the nice ‘Products By Category’ title in the screen shot above. I have specifically told Dynamic Data to use this value because I tagged my metadata class with the DisplayName attribute and given it a value of ‘Products By Category’. Below this metadata …

[MetadataType(typeof(ProductByCategoryMetadata))]
public partial class Products_by_Category { }

[DisplayName("Products By Category")]
public class ProductByCategoryMetadata
{
    [ScaffoldColumn(false)]
    public object Discontinued { get; set; }
}

To add a category and description to the metadata, I just used the existing Category and Description attributes and added them to the metadata class as well. So now we have …

[MetadataType(typeof(ProductByCategoryMetadata))]
public partial class Products_by_Category { }

[Category("Products")]
[Description("You can use this page to view your products by category")]
[DisplayName("Products By Category")]
public class ProductByCategoryMetadata
{
    [ScaffoldColumn(false)]
    public object Discontinued { get; set; }
}

The Category and Description attributes don’t directly map to any properties on the MetaTable type. But, any extra custom attributes that are applied to in the metadata are passed through to the Attribute collection that hangs off the MetaTable class. So with a couple of pretty simple extensions methods I can add them myself (ignoring error handling for now) …

public static class MetaTableExtensions
{
    ///

    /// Gets the description for the MetaTable
    /// 

    public static string GetDescription(this MetaTable table)
    {
        return ((DescriptionAttribute)table.Attributes[typeof(DescriptionAttribute)]).Description;
    }

    ///

    /// Gets the category for the MetaTable
    /// 

    public static string GetCategory(this MetaTable table)
    {
        return ((CategoryAttribute)table.Attributes[typeof(CategoryAttribute)]).Category;
    }
}

… and now to get at the MetaTable’s description or category I can just go through these methods. So I updated the List template and added a little bit of code that generates a simple title bar generated from the MetaTables DisplayName and Description attributes.

image

and now our List pages have a nice dynamic title bar …

image

Building the Menu

To build the menu, I am using a ListView tied to a LinqDataSource that uses a Linq query to create a 2 level object structure that I can bind to. First, I wired the LinqDataSource’s Selecting event to the following bit of code that groups my tables by their category …

protected void LdsMenu_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    e.Result =
        from vt in MetaModel.Default.VisibleTables
        //  use the category to group the tables
        group vt by vt.GetCategory() into groups
        select new
        {
            CategoryName = groups.Key,
            Tables = groups
        };
}

Then I bound this data source to my ListView …

image

And that’s all it took to build my 2 level menu. Awesome!

image

Conclusion

Can Dynamic Data be used for more than admin screens and prototyping? I think it might. What about you?

That’s it. Enjoy!

How to respond with code 404 (Not Found) in ASP.NET

Suppose you configured custom 404 page in web.config file in the customErrors section. So whenever user requests non-existent aspx page, ASP.NET run-time returns well formatted message to the user.

Also you have a page that shows articles from a database according to article ID passed in the url (for example: article.aspx?id=345). But if user passes article ID that doesn’t exists the page must return code 404 (Not Found) and show the custom 404 page like in the previous situation.

Fortunately you don’t need to parse the customErrors section to get name of the custom 404 page. Just throw HttpException:

throw new HttpException(404, “Article not found”);

ASP.NET run-time will catch the exception and will redirect to the custom 404.

Cross-browser rounded vector corners

vectorcorners_20080819.jpg

As a web developer, I’ve been patiently waiting for the designer community to finally decide that rounded corners and drop shadows are out of style. I’ve been waiting since about 1999 so, uh, you know, any day now guys. I’ll just be waiting here in web developer hell trying to construct a cubic igloo.

There are a number of tricks for creating roundtangles, from nesting a bunch of divs with background images, to jQuery scripts that will dynamically build successive 1-pixel-thick divs to render the corners. Today, I came across another method which simulates the CSS 3 border-radius vector corner effect in most browsers, using a little bit of conditional HTML and a bunch of browser-specific CSS properties.

You’ll have to check the source on the linked page below to see how it’s done, but basically VML is used for IE support, and the -moz-border-radius and -webkit-border-radius properties are applied for Firefox and Safari users.

It wouldn’t be a difficult task to simplify this a bit with jQuery and roll all of the necessary markup and css tweaks inside a single class target.

HTML/CSS Vector Corners

Passing data using AJAX

The XML data is not the only way how to pass data from the server to browser. The data can be passwd as XML, HTML, just a string, or JSON.

What is JSON?

JSON is JavaScript Object Notation. It is much easy to work with JSON then parse XML data.

When you receive JSON data from the server you will need to evaluate the data into variable and access the data as structure or an array.

This is JSON data:

[ { author: 'name a', title: 'title #1' },
  { author: 'name b', title: 'title #2' },
  { author: 'name b', title: 'title #3' } ]

This is how to access this data:

var books = reval( req.responseText );
element.innerHTML = books[0].author;

This is how to modify and produce JSON stream:

books[0].author = "me";
String newJSONstream = books.toJSONString();

This is simple. Enjoy!

Hot to get an absolute location of the HTML element

The function below will give you absolute position of an element in the browser window. This you will need to move element to position relative to another element’s position.

function findPos(obj)
{
  var curleft = curtop = 0;
  if (obj.offsetParent)
  {
    curleft = obj.offsetLeft;
    curtop = obj.offsetTop;
    while (obj = obj.offsetParent)
    {
      curleft += obj.offsetLeft;
      curtop += obj.offsetTop;
    }
  }
  return [curleft,curtop];
}

Remember, when you need to set new position, the value must be in pixels.

toolTip.style.top = new_Y+"px";
toolTip.style.left = new_X+"px";
WP Like Button Plugin by Free WordPress Templates