jQuery 1.2 Released!

This is a major release for the JavaScript library that I have grown to love. Before I list the new features, it is important to note what functionality has been removed from jQuery.

Here’s the deprecated functionality:

  • These Selectors
    • XPath Descendant Selector: $(“div//p”)
    • XPath Child Selector: $(“div/p”)
    • XPath Parent Selector: $(“p/../div”)
    • XPath Contains Predicate Selector: $(“div[p]“)
    • XPath Attribute Selector: $(“a[@href]“)
  • Calling clone() with an argument: $(“div”).clone(false);
  • These Traversal Functions use the new .slice() instead):
    • $(“div”).eq(0);
    • $(“div”).lt(2);
    • $(“div”).gt(2);
  • These Ajax Functions:
    • $(“#elem”).loadIfModified(“some.php”);
    • $.getIfModified(“some.php”);
    • $.ajaxTimeout(3000);
    • $(…).evalScripts();

Thankfully a number of those don’t effect me. I’ll have to comb through my code to get rid of the .gt, .lt, and .eq traversal functions as well as a few of the selectors…but other than that, I’m good to go. To find out more about workarounds for the above removed functionality, check the jQuery 1.2 release notes

Now…on to the good stuff.

New features!

  • Selectors

    •  :has(selector)
    •  :header
    •  :animated
    • XPath Selector Plugin
  • Attributes
    • .val() Overhaul
  • Traversing
    • .map()
    • .prevAll() / .nextAll()
    • .slice()
    • .hasClass()
    • .andSelf()
    • .contents()
  • Manipulation
    • .wrapInner() / .wrapAll()
    • .replaceWith() / .replaceAll()
    • Event Cloning
  • CSS
    • .offset()
    • .height() / .width() for document and window
  • Ajax
    • Partial .load()
    • Cross-Domain getScript
    • JSONP
    • .serialize() Overhaul
    • Disable Caching
  • Effects
    • .stop()
    • %/em Animations
    • Color Animations
    • Relative Animations
    • Queue Control
    •  :animated
    • step: Function
  • Events
    • Namespaced Events
    • .triggerHandler()
  • Internals
    • Documentation Move
    • Expando Management

I have to say…it is a pretty snazzy release and I’ll begin implementing the new version shortly. w00t.

jQuery Plugin: Live Query

My hear is exploding with happiness and joy at the existence of Brandon Aaron. He has built a sweet jQuery plugin (Live Query) that reduces complexity in Ajax and general DOM manipulation coding by a great deal (when it comes to applying behaviors). First, let me tell you the problem (if you don’t already know):

Say I build a web application where I want to assign an onClick event to an <a> tag. In jQuery I’d do it like this:

First the HTML:

<a href="another.html" class="another">Grab Another!</a>

<ul>
  <li><a href="whee.html" class="whatever">Bork</a></li>
  <li><a href="whee.html" class="whatever">Bork</a></li>
  <li><a href="whee.html" class="whatever">Bork</a></li>
</ul>

Now lets do up the JavaScript:

$(document).ready(function(){
  $('a.whatever').bind('click',function(){
    alert('ZOMG Hai');
    return false;
  });
});

Simple, right? Yeah. It is. Nothing new. Now…say that I manipulate the DOM and add in another <a> tag with the class “whatever” that I want the same even applied (with or without Ajax, doesn’t matter). Here’s what I would have had to do in the past:

$(document).ready(function(){
  $('a.another').bind('click',function(){
    $('ul').append('<a href="whee.html" class="whatever">Bork</a>');

    $('a.whatever').bind('click',function(){
      alert('ZOMG Hai');
      return false;
    });

    return false;
  });
});

See that? Kinda complex. Things become quite complex when you begin doing Cross Domain Scripting via Remote JavaScript calls (which is what is heavily used in one of the apps I have done front-end development for).

The Live Query plugin is a beautiful thing as it “auto-magically” binds events to dynamically added elements within the page as they appear! So ALL of that JavaScript from both examples becomes:

$(document).ready(function(){
  $('a.whatever').livequery('click',function(){
    alert('ZOMG Hai');
    return false;
  });

  $('a.another').bind('click',function(){
    $('ul').append('<a href="whee.html" class="whatever">Bork</a>');
    return false;
  });
});

Yup. That’s it. Bind a livequery event to an element and as elements that match appear on the page…BAM! The event is applied.

There are some more advanced things you can do with the plugin and you can find those out at the Live Query site.

Internet Explorer – Web Developer Toolbar

In a world of FireFox and its beautiful extensions of web-development power, Internet Explorer has been a horrid browser to develop/debug your code.

Microsoft has a fancy FireBug clone for the bane of every web developer…Internet Explorer! They call it the Web Developer Toolbar (although it isn’t much of a toolbar and more of a tool set) and it is a blessing for finding problems in IE. Its features include:

The Internet Explorer Developer Toolbar provides several features for exploring and understanding Web pages. These features enable you to:

  • Explore and modify the document object model (DOM) of a Web page.
  • Locate and select specific elements on a Web page through a variety of techniques.
  • Selectively disable Internet Explorer settings.
  • View HTML object class names, ID’s, and details such as link paths, tab index values, and access keys.
  • Outline tables, table cells, images, or selected tags.
  • Validate HTML, CSS, WAI, and RSS web feed links.
  • Display image dimensions, file sizes, path information, and alternate (ALT) text.
  • Immediately resize the browser window to a new resolution.
  • Selectively clear the browser cache and saved cookies. Choose from all objects or those associated with a given domain.
  • Display a fully featured design ruler to help accurately align and measure objects on your pages.
  • Find the style rules used to set specific style values on an element.
  • View the formatted and syntax colored source of HTML and CSS.

The Developer Toolbar can be pinned to the Internet Explorer browser window or floated separately.

This toolbar isn’t a match for the features, look, or usability of FireBug…but it is a great start and a pretty decent tool provided by the guys at Microsoft. As many developers can attest, developing sites that work according to standards AND Internet Explorer is a pain…this tool eases that pain.

Get it here.

Oh, and once you install the toolbar, it is hard to see where to open the thing. After installing, a little blue arror will appear in the icon bar at the top of the browser. Click that and the tool will open at the bottom of the screen.

Plugin: Sexy Comments v1.4 Released!

[[innerindex]]

Introduction

This has been a long time coming and I am happy to announce the release of Sexy Comments v1.4! With this version comes a lot of changes…so be sure to read the installation section! Along with simple optimizations and general restructure, the following features are now available:

Feature List

  • Ajax comment preview (new feature)
  • Author post highlighting
  • Avatars
    • Either display/hide avatars
    • Select your avatar service of choice (Gravatar and MyBlogLog options are available)
    • Specify maximum avatar dimension (Gravatar Only)
    • Customize default/trackback avatars
  • Comment Reply-To (new feature)
  • Comment Themes (new feature)
  • CSS overriding
  • “Number of Comments” message customization
  • jQuery inclusion toggling

Installation & Upgrading

  1. Download Sexy Comments v1.4 from the WordPress plugin directory
  2. Unzip that little sucker
  3. Place sexy-comments folder in your wp-content/plugins directory (it should look like this: wp-content/plugins/sexy-comments/
  4. Log in to your WordPress plugin admin page and activate the plugin.
  5. In the plugin admin page, click the SexyComments sub-menu.
  6. Customize the settings until you have something that works for you.
  7. Locate your theme’s template file that displays comments (typically comments.php). Remove the comment output loop and replace with:
    < ?php sexycomments::show($comments); ?>
    
  8. If you plan to use the Ajax features or the Reply-To features, you will need to do two things.
    1. Enable jQuery and jQuery Form Extension via the Plugin > SexyComments administration page.
    2. Locate the template file that contains the comment submission form (typically comments.php near the bottom) and replace that chunk of code with:
      < ?php sexycomments::form(); ?>
      

    NOTE: Be sure not to touch the section that generates the form for adding comments! This plugin does not re-create the comment creation form.

  9. Lastly, consider disabling the plugin CSS and taking the example CSS provided and customize it to suit your theme’s color scheme.
  10. You should be all set, now! w00t w00t! Go make a MyBlogLog or Gravatar account if you don’t already have one and upload an avatar. Gravatar tends to be pretty flakey so I’d suggest using MyBlogLog.

FAQs

  • Q: What is this “comment loop” you speak of?

    A: Ah, yes. That thing. Well, its anatomy looks similar to this (there will be some variation from theme to theme):

    < ?php if ($comments) : ?>
    	<!-- some HTML is typically here -->
    
    	< ?php foreach ($comments as $comment) : ?>
            <!-- the output HTML of each individual comment -->
    
    	< ?php endforeach; /* end for each comment */ ?>
    	<!--...more HTML -->
     < ?php else : // this is displayed if there are no comments so far ?>
    	< ?php if ('open' == $post->comment_status) : ?>
    		<!-- typically a blank area or a place with a comment -->
    	 < ?php else : // comments are closed ?>
    		<!-- closed comments section -->
    	< ?php endif; ?>
    < ?php endif; ?>
    
    
  • Q: Ok…so I just upgraded to a new version and there is nothing in the SexyComments admin page…WTF?

    A: Yeah. Sorry about that. In this version, the directory structure has changed drastically and Sexy Comments should no longer live in wp-content/plugins/sexycomments.php OR wp-content/plugins/sexycomments/sexycomments.php, but instead it should be in wp-content/plugins/sexy-comments/. Make sure that the plugin is in the correct location of your plugins directory.

  • Q: What happened to sexycomments_print($comments)? I used to use that to get my comments to display…will it still work?

    A: Along with a directory structure overhaul, this version had a large code overhaul as well. The old function (sexycomments_print) is deprecated but will still work for the time being. I greatly urge you to move over to the new function call sexycomments::show($comments) as that is the new *impoved* function.

jQuery 1.1.3: Speed Improvements and Bug Fixes

After a long wait, jQuery 1.1.3 has been released! (Download it at the jQuery site) When I first adopted jQuery a year ago, the library boasted both faster speeds and smaller size than any other JavaScript Ajax/DOM tool. With the release of jQuery’s version 1.1.2, a number of jQuery’s operations became very slow and inefficiencient, as evidenced by MooTool’s SlickSpeed CSS Selector Test (found via Ajaxian) which crept up a few weeks ago.

This new release boasts an 800% speed improvement with a number of its selectors along with various enhancements across the board! The selector speed boost makes me one happy camper. Check out the enhancements as it compares to 1.1.2:

Browser jQuery 1.1.2 jQuery 1.1.3 % Improvement
IE 6 4890ms 661ms 740%
Firefox 2 5629ms 567ms 993%
Safari 2 3575ms 475ms 753%
Opera 9.1 3196ms 326ms 980%
Average improvement: 867%

And here’s how it now stacks up against the SlickSpeed test:

Browser Prototype jQuery Mootools Ext Dojo
IE 6 1476ms 661ms 1238ms 672ms 738ms
Firefox 2 219ms 567ms 220ms 951ms 440ms
Safari 2 1568ms 475ms 909ms 417ms 527ms
Opera 9.1 220ms 326ms 217ms 296ms 220ms

In addition to the speed enhancements, there were several other notable things:

  • Unicode Selectors: Yup…now you can use fancy non-english characters.
  • Escape Selectors: This is awesome. Now, if you use weird characters (i.e. punctuation) in a class/id name, you can now escape those characters within the selector syntax. E.g. $(“div#foo\.bar”)
  • Inequality Selector: You can now select elements where their attributes do not match a specific string of characters. E.g. $(“div[@id!=test]“)
  • :nth-child() improvements: jQuery has supported selectors like :nth-child(1) and :nth-child(odd) since the beginning of jQuery, now they’ve added advanced :nth-child selectors, such as:
    • $(“div:nth-child(2n)”)
    • $(“div:nth-child(2n+1)”)
    • $(“div:nth-child(n)”)
  • Space-separated attributes: After being removed in jQuery 1.0, this selector has now been brought back by popular demand. It allows you to locate individual items in a space-separated attribute (such as a class or rel attribute). E.g. $(“a[@rel~=test]“)
  • Animation Improvements: Animations are now significantly faster and smoother. Additionally, you can run more simultaneous animations without incurring any speed hits.
  • DOM Event Listeners: Internally, the jQuery Event system has been overhauled to use the DOM Event system, rather than the classical “onclick” style of binding event handlers. This improvement allows you to be more unobtrusive in your use of the library (not affecting the flow of other libraries around it). Additionally, it helped to resolve some of the outstanding issues that existed with binding event listeners to IFrames.
  • Event Normalization: Some great steps have been taken to normalize keyboard and mouse events. You can now access the event.which property to get most details about the specific key or button that was pressed.
  • Multiple .is(): The .is() method can now take multiple selectors, separated by a comma. This allows you to test your jQuery set against multiple selectors. E.g. $(“div”).is(“:visible, :first”)
  • Browser Version: A commonly requested feature, by plugin authors, was a way to determine what browser version their users were using. We now expose an extra property through which this information can be accessed. E.g. jQuery.browser.version

Additionally, the jQuery team has addressed 80+ bugs and has roadmapped out the next two releases (v1.1.4 and v1.2). To check out the full jQuery 1.2 roadmap, go here.

Safari 3 Beta – Finally on Windows

This year’s WWDC has brought a few interesting things: a new Apple.com website layout, the launch of the iPhone, the announcement of the near final Mac OSX Leopard, some updated Mac hardware, and last but not least (and the most surprising), Safari 3!

This time around, Mac is attempting to be a competitor for IE and Mozilla’s Firefox and delivering the browser, not only on the Mac, but on the PC as well! This is great news for developers that don’t have access to Macs as they are finally able to test a little bit on Mac’s browser.

This new release is boasting a few things:

  1. Blazing Performance – Apple claims: The fastest web browser on any platform, Safari loads pages up to 2 times faster than Internet Explorer 7 and up to 1.6 times faster than Firefox 2.
  2. Elegant User Interface – Nothing revolutionary…same old Safari interface which I’m not overly fond of
  3. Easy Bookmarks – Same old bookmarking that you see in IE and FF
  4. Pop-Up Blocking – A good feature…but basic
  5. Inline Find – A fairly sexy find feature
  6. Tabbed Browsing – Ye olde tabbed interface….it lacks the Ctrl+Tab and Shift+Ctrl+Tab that I know and love though
  7. SnapBack – SnapBack lets you instantly snap back to your original search results or to the top level of any website, even after you’ve browsed down a few levels.
  8. Forms Autofill – Nothing new
  9. Built-in RSS – Ok….Safari does handle RSS nicely.
  10. Resizable Text Fields – Cool…I guess
  11. Private Browsing – This is a nifty feature!
  12. Security – ….sure

I’m too much of a Firefox buff to switch…but it will be good to test on any box :) Thanks Apple!

Coda – Finally A Mac Development Tool I Like

Coda I’ve had a Mac for quite a while now (well…I have two and hopefully a third very soon) and sadly development tools on the Mac have been pretty lame. I began development in a Windows environment a number of years ago and grew very happy (and spoiled) with EditPlus. The features that I found myself using within that editor that I am unable to live without are:

  • Single Window Environment
  • Custom Syntax Highlighting
  • Regular Expression Find/Replace
  • Function/Method List
  • Native FTP/SFTP
  • Intuitive Remote Site Browsing
  • Remote File Reload
  • Preview Tool

My attempts at finding Mac development software that suited all those needs have turned up pretty lame results. For the past year I’ve been suffering with BBEdit. While it is a fairly decent editor, its FTP support and multi-window interface just left me wanting something more.

Enter the newly released Coda.

This is the diamond in the rough! It provides everything that EditPlus had and a bunch more, integrating Panic‘s Transmit FTP application; a Terminal window; a sexy Editor with all the features I love; a browser window (Safari); a CSS Editor (which I’ll never use, although it’s cool); and a development Book library. Wow. Awesome stuff. Or as Panic puts it:

Text editor + Transmit + CSS editor + Terminal + Books + More = Whoah.

introducing coda. grow beautiful code.

Not only is their editor a beautiful application, their website is definitely something to write home about. Stunning. What’s even cooler is the fact that because I bought a Transmit license a few months back, I received a discount when I bought my Coda license. w00t! So…if you find yourself still on the hunt for a Mac Development Tool…Coda is the answer. Heck, even if you have one you like…Coda is better :)

Faster Page Loads With Image Concatenation

[[innerindex]]

Introduction

When designing web applications, icons and images are used to enhance the user experience, give visual cues, and simply look sexy. For complex web apps, the quantity and resulting latency of icons and images used can greatly impact page load times…and developers, in most cases, generally try to reduce page load time with a sweet web app rather than increase it.

To reduce latency in my apps, I use Image Concatenation! Coupled with a bit of CSS magic, performance improves and life is great.

Image Concatenation…WTF?

The basic idea is this: Change X number of image downloads to 1 image download by making 1 big image that contains the X images.

As an example, lets say we have these icons:

help settings maximize shade grow close

While those are pretty tiny in size, on page load the user must still deal with downloading 6 individual images. Instead, we can simply concatenate those images using whatever image software that suits your fancy. Like so:

icons

Displaying Concatenated Images

Now that we have our sweet concatenated image we can’t simply drop that image into an image tag and call it good…that’ll display all icons at once. So…how do we display it?

To display the concatenated image, you need to place that image as a background on an appropriately sized DOM element using CSS to adjust the background positioning to make the appropriate image display. Now, when I say a DOM element…it could really be anything as you can plop a background image on any element with CSS pretty easily:

.whatever{
  background: url('/path/to/image.png');
}

Even though you can use any element, only a few make sense. I’ve seen spans and divs used to accomplish this task, but styling those elements to work cross-browser is flaky at best and really churns my stomach. The element that his handled pretty universally is the img tag.

Yes…yes…I know, I just said don’t place the concatenated image in an img tag. I still hold to that statement. You place the concatenated image as a background on the img tag. So what goes in the src of the img tag? Our old friend the 1 pixel by 1 pixel transparent gif, of course! This way, the image will still act as an image, can be styled like an image, and be super easy to update via CSS.

An Example

Lets say we have the following concatenated image: sidebar_icons that we want displayed in the sidebar with the appropriate links.

Lets set up the HTML first using transparent.gif (a transparent 1×1 pixel image) as the src of the image tags:

...
<ul id="sidebar">
  <li><a href="index.html" title="Home"><img src="images/transparent.gif" class="icon icon-home" alt="Home"/>Home</a></li>
  <li><a href="search.html" title="Search"><img src="images/transparent.gif" class="icon icon-search" alt="Search"/>Search</a></li>
  <li><a href="bookmarks.html" title="Bookmarks"><img src="images/transparent.gif" class="icon icon-bookmarks" alt="Bookmarks"/>Bookmarks</a></li>
</ul>
...

Note the class names on the images…those will be used in the CSS as such:

#sidebar img.icon{
  background: url('/path/to/concatenated/image.gif') no-repeat;
  height: 16px;
  margin-right: 3px;
  vertical-align: middle;
  width: 16px;
}

#sidebar img.icon-home{
  background-position: 0px 0px;
}


#sidebar img.icon-search{
  background-position: -16px 0px;
}


#sidebar img.icon-bookmarks{
  background-position: -32px 0px;
}

That’s really all there is to it. The icon class allows us to set the same image background and dimensions for all icons in the sidebar. The individual classes allow us to change the image that actually shows through.

More CSS Magic

Since CSS is being used to display the appropriate image, you can do your typical property manipulation as normal (e.g. :hover, set transparencies, etc).

A little trick I picked up at Zimbra‘s presentation (the same presentation I learned the benefit of image concatenation) at The Ajax Experience last October was how to reduce the number of images used by representing inactive icons with CSS transparency rather than using individual images for inactive icons. Like so:

#sidebar img.inactive{
  filter:alpha(opacity=50);
  -moz-opacity: 0.5;
  opacity: 0.5;
}

If you wanted to make the icons partially transparent all the time but on mouse over make them 0% transparent, you can do so like so:

#sidebar img.icon{
  filter:alpha(opacity=50);
  -moz-opacity: 0.5;
  opacity: 0.5;
}

#sidebar img.icon:hover{
  filter:alpha(opacity=100);
  -moz-opacity:1.0;
  opacity:1.0;
}

Basically, whatever CSS magic you can weave can be done.

Additional Benefits

If you are a developer working in a painful development environment, the above methods are extremely valuable. Oh…and by painful I mean: any change to the base document structure requires a restart of the application. I’ve been doing a lot of development in an XSLT/Java environment recently and this method has saved me countless restarts :)

Now, if I decide an icon should change from a “house” to a “moon” (for some strange reason) I can make that change easily in CSS without needing to change the XSLT…thus no restart needed. Beautiful.

Heck…I use this CSS method for a number of non-concatenated images as well just so I can make general image changes with ease.

What Not To Do

When using the above image concatenation methods, it is important to note that concatenating similar images is a good plan. Avoid concatenating images of vastly different sizes because the wasted space on the concatenated image increases the amount of data being downloaded which can counter-act what we are attempting to reduce by concatenation.

Drawbacks

Update: This section was added a couple of hours after posting as per someone’s suggestion.
Using this method can affect the printability of your page as background images assigned with CSS don’t show in print too well :)

Conclusion

Image concatenation can be a beautiful thing when dealing with large numbers of icons/images. But, as with anything, weigh its benefit. Thus far, I’m pretty happy with the results!

Settlers of Catan

747px-Settlers_of_Catan_-_standard_map I’m a fan of Settlers of Catan. The game is ballsy and tons of fun…as a matter of fact, I played and triumphed last night :) Anyways, for those of you out there that haven’t a clue what the game is about, here’s an excerpt from Wikipedia:

The players in the game represent the eponymous settlers, establishing a colony on the previously uninhabited island of Catan. The island itself is laid out randomly at the beginning of each game from hexagonal tiles (“hexes”) of different land types each producing one type of resource: ore, grain, wool, lumber, or brick. One hex is desert which does not produce anything.

As players establish towns and cities on the island, each settlement can receive resources for its adjacent hexes (with cities yielding more resources). The resources, represented by cards, can be used to build more roads, towns, or cities, and to obtain development cards for later use. Various achievements, such as building a town or establishing the longest road, grant a player one or more victory points. The winner is the first player to accumulate ten victory points on his turn.

Players are allowed to trade among each other the resources they have produced, and to trade “off the island” for a hefty price. It is difficult for any one player to produce all the resources necessary for progress, so astute trading is the strategic heart of the game. Player interaction is further complicated by the presence of a robber, which is used to steal from other players and hinder their production of resources. There is no combat. Apart from moving the robber, refusing to trade, and cutting off building routes, there is no way to harm other players. The settler theme and economy simulation gameplay are similar to the 1983 personal computer videogame M.U.L.E., though Teuber may have developed them independently.

Settlers of Catan has rapidly become popular in part because its mechanics are relatively simple, while its dynamics are quite complex. At a recreational level, the game is well-suited for family play. No one gets eliminated, and players who are behind can strive towards quantized goals that are within reach, such as building a city in a certain space. Home games generally take between one and two hours to complete.

The layout of the board and restrictions on building allow for a player to be boxed in through poor play or bad luck. Also, given the random component of board layout, it’s possible for players to gain a monopoly on certain resource, and demand steep trade rates from other players.

Along with the main game, you can buy a number of expansions that will really changed the game! The Americanized expansions are: Seafarers of Catan, Cities and Knights of Catan, 5-6 Players Basic, 5-6 Players Seafarers, 5-6 Players Cities and Knights. One thing that sucks in that regard is the fact that if you buy the 5-6 Player Basic expansion and the Cities and Knights Expansion…well, to play 5-6 player Cities and Knights, you need to buy another box…5-6 Player Cities and Knights. It gets a little expensive, but well worth it!

If you have the chance to try this game out…do so. Don’t be daunted by the rules as they seem complex at first, but they really are simplistic. You’ll thank me later.

JSMin: Javascript Compression

While at The Ajax Experience in October, I attended a presentation who spoke of the 3 C’s (Combine, Compress, Cache) for Ajax development. In the Compress section I was introduced to the beauty of JSMin!

What is it? Well, shut up and I’ll tell you.

Quoting Douglas Crockford (the creator of JSMin):

JSMin is a filter which removes comments and unnecessary whitespace from JavaScript files. It typically reduces filesize by half, resulting in faster downloads. It also encourages a more expressive programming style because it eliminates the download cost of clean, literate self-documentation.

As I’ve been creating more complex Javascript applications, the file size has been increasing (although the size is greatly reduced, thanks to jQuery). And, as a careful programmer should, I place comments all over my Javascript code so I don’t draw too many blanks while updating/debugging…well, those comments tend to bloat the file size, as does the whitespace. The stripping of those elements alone has dropped the file-size of a number of my scripts by 40-50%! Thats huge. What previously was an 8K file goes down to 4K. Awesome.

If you’re curious what JSMin does to your code, here’s an example that Douglas gives:
Before

// is.js

// (c) 2001 Douglas Crockford
// 2001 June 3


// is

// The -is- object is used to identify the browser.  Every browser edition
// identifies itself, but there is no standard way of doing it, and some of
// the identification is deceptive. This is because the authors of web
// browsers are liars. For example, Microsoft's IE browsers claim to be
// Mozilla 4. Netscape 6 claims to be version 5.

var is = {
    ie:      navigator.appName == 'Microsoft Internet Explorer',
    java:    navigator.javaEnabled(),
    ns:      navigator.appName == 'Netscape',
    ua:      navigator.userAgent.toLowerCase(),
    version: parseFloat(navigator.appVersion.substr(21)) ||
             parseFloat(navigator.appVersion),
    win:     navigator.platform == 'Win32'
}
is.mac = is.ua.indexOf('mac') >= 0;
if (is.ua.indexOf('opera') >= 0) {
    is.ie = is.ns = false;
    is.opera = true;
}
if (is.ua.indexOf('gecko') >= 0) {
    is.ie = is.ns = false;
    is.gecko = true;
}

After

var is={ie:navigator.appName=='Microsoft Internet Explorer',java:navigator.javaEnabled(),ns:navigator.appName=='Netscape',ua:navigator.userAgent.toLowerCase(),version:parseFloat(navigator.appVersion.substr(21))||parseFloat(navigator.appVersion),win:navigator.platform=='Win32'}
is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}

As you can see…the result is not easily read so you’ll want to keep your original script around in the event that editing is needed. Super cool. So how do you get it? Well…there’s a number of languages that JSMin logic has been ported to: zip file containing
an MS-DOS.exe file
, or you can get the C source code and build it yourself. Now in C# and Java and JavaScript and Perl and PHP and Python and Ruby.

If you haven’t thought about Javascript compression yet, you might want to start. Try it out…you’ll be happy you did. Oh, and if you are curious: the Javascript implementation of JSMin is my favorite as it gives some excellent feedback and comment options on compression.

JavaScript Shell

While at The Ajax Experience I noticed a tool that a few of the speakers made use of that was missing from my arsenal. The tool? JavaScript Shell.

This little beauty, once you’ve added the bookmark to your browser allows you to open a JavaScript Shell for any page you happen to be on! The shell lets you enter JavaScript from command-line to manipulate the page, trigger functions, analyze properties, etc. All libraries that the site has loaded are available within the Shell…so, if you use jQuery or some other toolkit, all defined functions and plugins are usable.

Here’s some features and pre-defined functions from the JavaScript Shell site

Features

  • You can enter statements and expressions at the same prompt.
  • The result of each non-void statement or expression is shown.
  • User-defined variables.
    • b = document.body
  • User-defined functions.
    • function f() { return 5; }
  • JavaScript error messages are shown in red.
  • Previous statements and expressions are available through Up and Down arrow keys.
  • Tab completion.
  • Multiline input (Shift+Enter to insert a line break).
  • If the shell is opened using a bookmarklet, JavaScript typed into the shell runs in the context of the original window.
  • Works well in Firefox, mostly works in Opera 8 and in IE 6 for Windows.

Built-in functions

  • ans: the result of the previous expression.
  • print(expr): prints expr on its own line.
    • for(i = 0; i < 6; ++i) print(i * i)
  • pr(expr): prints and returns its input, so you can use it to print intermediate results in the middle of an expression.
    • function fact(n) { return n>0 ? pr(n*fact(n-1)) : 1 }
  • blink(node) or Alt+B: makes a node blink for a second.
    • blink(document.links[3])
  • props(obj) or Alt+P: lists the methods and fields of an object.
    • props(document.body)
    • In Firefox, props also shows which properties belong to the object itself and which belong to objects in its prototype chain.

I’m a fan :D

The Ajax Experience: jQuery Toolkit

jquery I went to The Ajax Experience with high expectations of catching some great tips regarding development in an Ajax environment. At the same time, I was sure of my previous decision with the use of Prototype and Script.aculo.us was as good as it gets (without diving into the widgetized world…e.g. Dojo). I attended John Resig‘s presentation on jQuery and I became a convert.

John’s presentation was less of a presentation and more of a Q&A Demonstration, which suited me fine. As soon as I knew where to download the code, I popped open my laptop and started fiddling around with the toolkit – passively paying attention to the questions and answers, as they tended to be extremely basic questions…you see, jQuery is pretty darn intuitive.

jQuery’s mantra is “Find stuff and do stuff to it”

Yeah, I wasn’t converted because jQuery was the first toolkit to support chaining and that it executes it nicely. Nor was I converted because of its extensive plugin library. Nope. My conversion was the effecient findability of elements within the DOM! This is what really makes jQuery ballsy. The toolkit was built with findability in mind using already established standards! jQuery fully supports CSS1, CSS2, CSS3, and basic XPath when hunting for elements. For example:

Lets start with something simple:
Say I wanted to find all elements within the page that had the class: bork and hide them, I’d do:

$('.bork').hide();

Alright, say I wanted to find all anchor tags with the target set to _blank and add the class whee to it:

$('a[@target=_blank]').addClass('whee');

Now, lets say I want to find all anchor tags with the target set to _blank and add the class whee to them AND append (opens in a new window) as a sibling to the link itself.

$('a[@target=_blank]').each(
  function(){
    $(this).addClass('whee');
    $(this).after('(Opens in a new window)');
  }
);

Now, if I knew I was going to use the above a whole lot all over hell’s half acre, I could create a jQuery plugin that can be chained! Here’s how I’d create that feature and allow for the passing of class name:

jQuery.fn.opensInNewWindow = function(classname){
	return this.each(
		function(){
                        $(this).addClass(classname);
                        $(this).after('(Opens in a new window)');
		}
	);
};

Now, when I want to put Opens in a new window on a series of elements, I can do so with my newly created plugin:

$('a[@target=_blank]').opensInNewWindow('whee');

//I can do this for ANY element I want even if it isn't a link
$('span.bork').opensInNewWindow('zomg');
$('div#w00t ul.nav').opensInNewWindow('roflcopter');

Now, to make use of the chainability, you can write the plugin more simply than what I did up above. You can do this: (thanks to malsup, a commenter on this article)

jQuery.fn.opensInNewWindow = function(classname){
	return this.each(
		function(){
      $(this).addClass(classname).after('(Opens in a new window)');
		}
	);
};

Cake walk. As your proficiency in finding objects within a page increases, your code will become shorter.

jQuery currently has a very active community and mailing list (averaging at about 90 posts per day) so if you have questions regarding the toolkit, you can become a member and ask away… In addition, there’s a jQuery blog where John posts comparison code showing the difference between jQuery and other available toolkits. (here’s a Zebra striping example)

If you are still on the hunt for a JavaScript toolkit for Ajax, DOM manipulation, etc or you find your toolkit of choice too clunky, give jQuery a shot. You’ll be pleased with the results.

The Ajax Experience: Leveraging Ajax for Enterprise Application Development

[[innerindex]]

Despite the fact that AJAX is making significant inroads within the Web 2.0 community, many enterprise applications still remain either traditional web or desktop applications. However, by effectively using AJAX, enterprises can develop compelling, innovative, and useful web based applications that increase employee productivity while retaining the manageability enjoyed by traditional web applications. This session will focus on the challenges of developing enterprise AJAX applications with an emphasis on overcoming the common hurdles and problems encountered along the way.

Presenter: Conrad Damon – Zimbra

Conrad’s discussion began with an re-iteration of what Web 2.0 is and how things have changed since Web 1.0. Old news, but the re-iteration was brief.

Choosing an RIA solution

Next Conrad explained his team’s decision process on choosing Ajax as the solution for creating their Rich Internet Application, Zimbra.

Flash?
The Zimbra team turned this down early on as they didn’t want to be tied to a proprietary solution… A decision I can respect :) I’m not too keen on the use of Flash as a front end for full-blown RIAs in most cases.

Ajax Worries
There were some hesitations regarding the use of Ajax as a solution:

  • Complexity – Lets face it, adding Ajax into the mix causes the applications complexity to increase.
  • Performance – there’s a lot going on with an Ajax app client-side that can cause client performance to degrade. (mixed with the chattiness server-side)
  • Some cross-browser issues.

Ajax: The Chosen One
Overall, Zimbra’s team decided on Ajax as the pros outweighed the cons:

  • Enhanced User Experience
  • Desktop application-like feel.
  • Deployment is trivial. – No installation…the application is accessible via the web.
  • The power of mashups is where its at. Its all about SOA (Service Oriented Architecture).

Ajax Points

Conrad noted a few key points regarding Ajax, however:

  • Ajax is cheaper on the server/network
  • Ajax applications are more memory expensive client-side
  • Ajax applications are not a business model
  • Ajax applications are the means not an end

Ajax Tips

Based on the Zimbra team’s experience, Conrad gave some tips:

  • Use an Ajax Toolkit – They simplify things. What you choose is up to you, but the time saved by toolkit use is well worth it.
  • CSS is your friend – bend it to your will
  • Use JSON, not XML – Zimbra has almost fully converted all passing of XML to JSON
    • JSON is easy
    • JSON is fast. Eval’ing JSON is faster than parsing XML by a magnitude of 10!
  • Use Asynchronous XHR (XMLHttpRequest) calls
  • Combine, Compress, and Cache
  • Automate Testing – Zimbra uses QuickTest Pro from mercury to test the Zimbra client.
  • OO, MVC
  • TLS (Transport Layer Security…SSL) – Make sure you use it!
  • KISS (Keep it simple, stupid) – this applies to both code and the UI!
  • No browser lock-in – don’t program for a specific browser…keep it open to at least the A-Grade browsers
  • Test, test, test

Browser Gotchas & Tips

Next came some helpful browser-specific tips and gotchas:

  • Firefox
    • Missing Cursor – workarounds exist (surrounding the input with a div…yadda yadda)
    • Event capture – effects DnD effects
    • design mode – lets you turn the Browser into an editor…buggy
    • xmlHttpRequest – bug that pained the CPU when making synchronous calls
    • opacity (linux) – hangs browser (relationship between X11 and opacity)!!!!!!!!!!!!!!
    • scrollbar bleed (mac) – scrollbar does not respect z-index
  • IE 6
    • string concat with +… – SLOW, use Array joins instead
    • image caching is poor – hard to convince to cache image in browser…workaround: have a hidden div and load the images there first
    • JS engine can be slow
    • Memory leaks – circular reference issue. workaround: give things numeric ids and a lookup table
    • XHR ActiveX object – some memory leaking issues
    • DOM attribute access is slow
  • IE 7
    • ActiveX opt-in
    • CSS fixes
    • Native XHR
    • memory leaks appear to be fixed
  • Safari
    • No design mode
    • DOM API not fully implemented
    • Debugging difficult (not entirely true)

The 3 C’s

By far the most useful section of Conrad’s presentation was on Zimbra’s 3 C’s; Combine, Compress, and Cache.

Combine
Zimbra uses this technique to minimize the sheer amount of files downloaded by the client which speeds up load time! Conrad suggests:

  • Concatenate your JS files and CSS files – Order matters (remember)! Zimbra uses the “Jammer” ANT task to do this dirty work.
  • Merge Images – Images are expensive! If your application uses a large number of icons, try merging them into a single image and use background-positioning on elements for the display of icons. For disabled icons, use opacity at 20-50% rather than creating a whole new icon.

Compress
Compression makes things smaller in size…smaller “things” are quicker to download!

  • Strip comments and whitespace – use JSMin or ShrinkSafe
  • GZIP your Javascript! – All of the A-Grade browsers support gzipping which reduces file size!

Caching
Set proper headers for appropriate browser caching. Avoid redundant downloads. Period.

Conclusion

I respect the Zimbra team and their decisions; their application is solid, functional, and quite sexy. All in all, this was a pretty solid presentation with a nice amount of data. As I mentioned earlier, the 3C’s were the most valuable tid-bits of information for me…although there were a few browser gotchas that I wasn’t aware of.

The Ajax Experience: Plan of Attack

The Ajax Experience is next Monday (although I arrive Sunday afternoon) through Wednesday and I’ve prepared my plan of attack:

Monday

10:00am-11:30am: Leveraging Ajax for Enterprise Application Development – Conrad Damon
12:30pm-1:15pm: Keynote: Towards a Service-Oriented Applications Stack – Matt Quinn
1:30pm-3:00pm: Simplify Ajax development with Apache XAP – Bob Buffone
3:30pm-5:00pm: Ruining the User Experience – Aaron Gustafson
5:15pm-6:45pm: Scriptaculous – Justin Gehtland
8:00pm-9:30pm: Expert Panel Discussion

Tuesday

8:30am-10:00am: Intro to Dojo – Alex Russell
10:30am-12:00pm: Yahoo! Experiences with Accessibility, DHTML, and Ajax in Rich (Dunno what Rich is…probably the start of “Rich Internet Applications” [RIA], probably) – Nate Koechley
1:00pm-1:45pm: Keynote: Ajax from AOL’s Perspective – William Morris
2:00pm-3:30pm: RAD 2.0: Working with symfony (PHP) – Dustin Whittle
4:00pm-5:30pm: Markup & CSS for Developers: Empowering the Application Developer with Front End Magic – Molly Holzschlag
7:00pm-7:45pm: Keynote: The Once & Future Web – Chris Wilson
9:00pm-10:30pm: Expert Panel Discussion

Wednesday

9:30am-10:30am: Designing for Ajax – Bill Scott
11:00am-12:30pm: Dojo Cookbook – Dustin Machi

My schedule is subject to change based on buzz or sudden interest in other presentations. I look forward to seeing what they have to offer and will be blogging along the way!

Prototype Changes

I found this article via Ajaxian regarding a nice block of Prototype updates.

  • Shorter syntax for event handling
    $('element').observe('click', function(e) {  alert(e); });
    
  • Make destructive Element, Form, and Form.Element methods return their first argument, so that multiple calls can be chained together.
    $(“sidebar”).addClassName(“selected”).show();

    The following methods now return their first argument: Element.toggle, Element.hide, Element.show, Element.remove, Element.update, Element.replace, Element.addClassName, Element.removeClassName, Element.observe, Element.stopObserving, Element.cleanWhitespace, Element.scrollTo, Element.setStyle, Element.makePositioned, Element.undoPositioned, Element.makeClipping, Element.undoClipping, Form.reset, Form.disable, Form.enable, Form.focusFirstElement, Form.Element.focus, Form.Element.select, Form.Element.clear, Form.Element.activate, Form.Element.disable, Form.Element.enable.

  • Form and Form.Element methods mixed in to $ and $$
  • For consistency, Element.toggle, Element.show, and Element.hide no longer take an arbitrary number of arguments.

    !! BACKWARDS COMPATIBILITY CHANGE !!

    If you have code that looks like this: Element.show(‘page’, ‘sidebar’, ‘content’); You need to replace it with code like this: [‘page’, ‘sidebar’, ‘content’].each(Element.show);

  • Mix in Form and Form.Element methods to forms and form field elements with $() and $$(). Closes #4448. [Dan Webb, sam]
  • Add Object.clone
  • Add Form.Element.disable and Form.Element.enable. Closes #4943.
  • Field is now simply an alias for Form.Element.
  • Add Element.Methods.getElementsByClassName and Element.Methods.getElementsBySelector. Closes #4669.
  • Avoid race condition when stopping an Ajax.PeriodicalUpdater. Closes #4809.
  • Improve support for synchronous requests. Closes #5916.
  • Add serialization and observation support for input type=search. Closes #4096.
  • Properly decode query components in String.prototype.toQueryParams. Closes #3487.
  • Add Array.prototype.reduce:
    • [1, 2].reduce() // [1, 2]
    • [1].reduce() // 1]
    • [].reduce() // undefined]
  • Add Object.keys and Object.values
  • Simulate non-GET/POST requests by POSTing with a _method parameter set to the actual verb
  • Make Element.update() handle TABLE-related elements with the DOM API because of IE’s missing .innerHTML property on them
  • Sync to script.aculo.us unittest.js library as of 2006/08/29
  • Add additional unit tests to test/unit/dom.html for testing Element.update and $().update in various enviroments
  • Prevent possible exceptions on unloading the page in IE

I’m psyched!