Skip navigation.
Home

YUI Blog

Syndicate content
News and Articles about Designing and Developing wiht Yahoo! Libraries.
Updated: 6 hours 49 min ago

Writing Effective JavaScript Unit Tests with YUI Test

Mon, 2009-01-05 18:38

One of the biggest under-the-radar movements in JavaScript development during 2008 was the reemergence of an interest in unit testing. YUI Test, YUI’s unit testing framework, reached GA status in February and other libraries either introduced their own unit testing frameworks or started publicizing existing ones. As a result, there’s a lot more documentation regarding the creation of unit tests for JavaScript. Simply having JavaScript unit tests isn’t enough, though; if your tests are written improperly, they can lead to a lot of lost time. Learning to write effective JavaScript unit tests will save you time and headaches in the future.

What are you testing?

The key to writing effective unit tests is to understand the word "unit." In testing terms, a unit is an isolated part of code that can be tested independent of other pieces of code. In an object-oriented language like JavaScript, each method is considered to be a unit. Proper OO design typically entails nicely encapsulated methods that serve a single purpose and are therefore easy to test.

Traditional unit testing is designed to test the implementation of an interface, so private methods don’t get tested explicitly. This is called black box testing. The idea is that you can swap out the implementation of an interface and the unit tests will all still pass because they are completely agnostic to the underlying implementation. All the tests know is a set of constraints that must be met; they don’t care how those constraints are met.

Writing tests

As I said in my talk, unit tests should test inputs and outputs. Inputs can be named method arguments or changes in globally accessible variables that the method depends upon to function correctly. Outputs can be return values, changes in the state of variables, and even thrown errors. For each input-output set, there should be a single unit test. Each test should explicitly state, "given these inputs, I expect these outputs." Any deviation from that statement is a failed test.

Each test should be as simple as possible and test only one input-output set; combining sets into a single test minimizes the effectiveness of the unit test. For example, consider the following test of a function called trim():

var testCase = new YAHOO.tool.TestCase({ name: "trim() Tests", testTrim: function(){ var result1 = trim(" Hello world"); YAHOO.util.Assert.areEqual("Hello world", result1, "Leading white space should be stripped."); var result2 = trim("Hello world "); YAHOO.util.Assert.areEqual("Hello world", result2, "Trailing white space should be stripped."); } });

Here, the testTrim() method of the test case is actually testing two different input-output sets:

  1. Input string has leading white space; return value has no leading white space.
  2. Input string has trailing white space; return value has no trailing white space.

The problem is that these two sets have literally no relation to one another, yet if the first input-output set fails to produce the correct result, the second set will never be tested. This is a situation where one failure masks another. It is more effective to separate out these input-output sets into two tests:

var testCase = new YAHOO.tool.TestCase({ name: "trim() Tests", testTrimWithLeadingWhiteSpace: function(){ var result = trim(" Hello world"); YAHOO.util.Assert.areEqual("Hello world", result, "Leading white space should be stripped."); }, testTrimWithTrailingWhiteSpace: function(){ var result = trim("Hello world "); YAHOO.util.Assert.areEqual("Hello world", result, "Trailing white space should be stripped."); } });

This code now properly tests the trim() function’s input-output sets, keeping them separate.

Unit tests are always written as if the code being tested works correctly. Good software design involves mapping out these input-output sets ahead of time so that you know exactly what the result should be in each case. In this way, unit tests become a type of technical requirement document in addition to actual code.

Effective assertions

One of the most important parts of writing unit tests is proper assertion definition. Each assertion specifies a condition that, if not met, indicates that the functionality isn’t behaving appropriately. It’s important to use only as many assertions as necessary to properly test the code output. Too many assertions can lead to false failures while too few can lead to false passes.

In the previous example, each test contains a single assertion because that is all that’s needed. I know exactly the value that to be returned and so I test specifically for that. The tests may both look very simple, but they get the job done. Again, there’s no rule about the number of assertions that make a good test, just make sure you’re testing every expected output of the code for the given input.

To make test failures more coherent, you should include a failure message with each assertion. In YUI Test, this is always the last argument of any assertion method. A failure message should tell you what should have happened, not what did happen. Some examples:

//Bad failure message YAHOO.util.Assert.areEqual("Hello world", result, "The result wasn't 'Hello world'"); //Good failure message YAHOO.util.Assert.areEqual("Hello world", result, "Leading white space should be stripped.");

Note the difference between the bad and good failure messages: the bad tells you what happened and the good tells you what was expected. When running your tests, a failure already indicates that something unanticipated happened, so there’s no need to simply repeat that something unanticipated happened. It’s more helpful to know what should have happened because it is an exact representation of your requirement. By taking this approach, failures end up being a list of unfulfilled requirements that you can go back over and evaluate.

Working with the DOM

JavaScript is unique to other languages in that it frequently has ties to the environment, the DOM. Methods that interact heavily with the DOM are difficult to unit test because the entire environment must be setup in order for the method to execute completely. Further complicating matters is the tendency of JavaScript to be triggered by a user action such as a mouse click. YUI Test provides event simulation to aid in creating tests for methods that are reliant on DOM interaction, however, this starts to cross over into the area of functional testing.

Functional testing, as opposed to unit testing, is designed to test the user’s experience with the product rather than input-output sets for code. If you find yourself wanting to test that the user interface responds in a specific way due to user interaction, then you really want to write some functional tests rather than unit tests. YUI Test can be used to write some basic functional tests, but the most popular (and quite good) tool for such testing is Selenium.

The best way to determine if something is a unit test is to ask if it can be written before the code that it’s designed to test actually exists. Unit tests, as part of test-driven development, are actually supposed to be written ahead of the actual code as a way to guide development efforts. Functional tests, on the other hand, cannot exist ahead of time because they are so tied to the user interface and how it changes in response to user interaction.

Structuring test hierarchies

YUI Test, just like other unit testing frameworks, supports a hierarchy of test cases and test suites. Each test suite can contain other test suites as well as test cases; only test cases can contain actual tests (methods beginning with the word "test"). The best way to organize your test hierarchy is to follow a very simple pattern:

  • Create one test suite for every object you’re going to test.
  • Create one test case for every method of an object you’re going to test and add it to the object’s test suite.
  • Create one test in each test case for each input-output set.

In this way, your test hierarchy mirrors the code you’re testing and it’s easier to figure out where new tests should be created.

Run your tests!

Perhaps the most important part of unit testing is to run your tests frequently. Testing is only effective when done on a regular basis. At a minimum, you should be running your unit tests before checking in changes to source control. Optimally, you’d also run the tests automatically on a regular basis to validate any changes after they’ve been committed to source control. This is how you’ll get the biggest benefit of unit testing: quick discernment, and hopefully prevention, of regressions.

Further information

Tags: , , , , , ,

Configuring Your Machine For Testing With A Screen Reader

Wed, 2008-12-31 00:32

When developing using the WAI-ARIA Roles and States, you need to test your code in a screen reader to ensure everything is working as you expect. As a follow up to my presentation on Developing Accessible Widgets with ARIA and in the interest of helping other developers test their code, I thought I would provide some tips on how to configure your development environment for screen reader testing.

Step 1: Install A Virtual Machine

Before I install and configure screen readers I start by installing a virtual machine. (This is mostly out of necessity because I use a Mac and the most-popular screen readers run on Windows.) Using a virtual machine provides a couple of benefits when testing with a screen reader: To start, a virtual machine provides a sandboxed environment, so I am protected if anything goes awry when I am installing and configuring each screen reader. (So as not to give the impression that screen readers are unstable pieces of software, this is definitely the exception more than the rule.)

The second benefit to using a virtual machine is that they allow you to save and restore state. This is an especially helpful feature for efficiently testing and re-testing specific pieces or states of complex web applications. So, using a virtual machine can help save you time when testing.

Which virtual machine to use? If you use Windows, you can download and install Microsoft Virtual PC for free. As a Mac user, I have found both VMware Fusion and Parallels Desktop work well.

Step 2: Install Browsers

It is important to remember that to work, ARIA requires a team effort between the browser and the screen reader. To test ARIA you’ll need to install browsers that both support ARIA and are supported by screen readers that also support ARIA. For example, Opera has support for ARIA, but is not supported by screen readers. Currently only Internet Explorer 8 and Firefox 3 have support for ARIA, and are supported by several screen readers for Windows that also offer support for ARIA.

After installing each browser, be sure to save the state of the virtual machine. That way you’ll be able to quickly revert back to a clean, working state should anything go wrong during the screen reader installation.

Step 3: Install & Configure Screen Readers

With the browsers installed the next step is to install and configure each screen reader. The two most-popular screen readers for Windows, JAWS and Window-Eyes support ARIA and work with both Internet Explorer 8 and Firefox 3. Free, trial versions of both products are available for download from Freedom Scientific’s and GW Micro’s websites. The open-source screen reader NVDA also has excellent ARIA support and currently works with Firefox 3. Knowing that most visually impaired users use more than one screen reader, I recommend installing all three for testing.

As a sighted person I disable a couple of features of each screen reader and change some configurations so that I can test more efficiently. For example, most screen readers are configured to startup automatically when you start your computer. This is obviously not desirable when you have multiple screen readers installed, so I turn off that feature. Additionally, every screen reader uses a different keyboard shortcut for toggling the virtual buffer on and off. To avoid having to remember the keyboard shortcut for each screen reader, I configure them all to be the same: Ctrl + Shift + Space. (For more on the virtual buffer, read Making Ajax Work with Screen Readers.)

The following sections provide step-by-step instructions for configuring JAWS, Window-Eyes and NVDA.

Configuring JAWS Changing The Virtual Buffer Toggle Keyboard Shortcut
  1. Open the “Keyboard Manager” dialog by selecting “Utilities” -> “Keyboard Manager” in the JAWS application menubar.
  2. Select the “default” profile in the left, “Profile” pane.
  3. In the right pane, sort by the “Script Name” column, then find and select the item named “VirtualPCCursorToggle”.
  4. Open the “Change Keystroke” dialog by either right clicking on the “VirtualPCCursorToggle” item, or by pressing Ctrl + H.
  5. In the “Change Keystroke” dialog, choose the new keystroke by pressing the desired keys. (I use Ctrl + Shift + Space.) JAWS will warn you if the keystroke you choose in already in use.
  6. Press the “OK” button to close the dialog.
Disabling JAWS From Starting Automatically
  1. Open the “Basic Settings” dialog by selecting “Options” -> “Basics” in the JAWS application menubar.
  2. In the “Basic Settings” dialog, make sure the checkbox labeled “Automatically start JAWS” in not checked.
Configuring Window-Eyes Changing The Virtual Buffer Toggle Keyboard Shortcut
  1. Open the “Browse Mode Hot Key Definitions” dialog by selecting “Hotkeys” -> “Browse Mode…” in the Window-Eyes application menubar.
  2. In the “Browse Mode Hot Key Definitions” dialog, scroll down to the item named “Browse Mode” in the scrollable “Keys” list.
  3. Select the “Browse Mode” item and then press the “Capture Key” button.
  4. Press the keyboard combination you want to use. (I use Ctrl + Shift + Space.)
  5. Press the “OK” button to close the dialog.
  6. Save the configuration by selecting “File” -> “Save” -> “Set File and All Dictionaries” in the Window-Eyes application menubar.
Disabling The Mouse Voice

By default Window-Eyes will speak in response to some mouse gestures. For example, when you press the left mouse button, Window-Eyes will say “left”. As a sighted person I find this feature unnecessary, so I disable this feature.

  1. Open the “Mouse Voice” dialog by selecting “Mouse” -> “Voice” in the Window-Eyes application menubar.
  2. Select the “Off” item.
  3. Press the “OK” button to close the dialog.
  4. Save the configuration by selecting “File” -> “Save” -> “Set File and All Dictionaries” in the Window-Eyes application menubar.
Disabling Window-Eyes From Starting Automatically
  1. Open the “Startup Options” dialog by selecting “File” -> “Starup Options…” in the Window-Eyes application menubar.
  2. In the “Startup Options” dialog:
    • Uncheck the checkbox labeled “Run Window-Eyes at the Login Screen”.
    • Uncheck the checkbox labeled “Run Window-Eyes after login for all users”.
    • Select the radio button labeled “Never” under “After login for Current User, Run Window-Eyes”.

  3. Press the “OK” button to close the dialog.
  4. Save the configuration by selecting “File” -> “Save” -> “Set File and All Dictionaries” in the Window-Eyes application menubar.
Configuring NVDA General Settings For Efficiency
  1. Uncheck the checkbox labeled “Show this dialog when NVDA starts” that pops up the first time NVDA starts
  2. Disable the confirmation dialog that pops up when you exit the application:
    1. Open the “General settings” dialog by right clicking on the NVDA system tray icon and selecting to “Preferences” -> “General settings” in the context menu.
    2. In the “General settings” dialog, uncheck the checkbox labeled “Warn before exiting NVDA”.
    3. Right click on the NVDA icon in the system tray and select the “Save configuration” menu item in the context menu.
Disabling the Mouse Voice

Like Window-Eyes, by default NVDA will speak in response to some mouse gestures. For example, when you move the mouse NVDA will play tones to help the user track the position of the mouse. As a sighted person I find this feature unnecessary, so I disable this feature.

  1. Open the “Mouse settings” dialog by right clicking on the NVDA icon in the system tray and selecting “Preferences” -> “Mouse settings” from the context menu.
  2. In the “Mouse settings” dialog, uncheck both “Report text under the mouse” and “play audio coordinates when the mouse moves”.
  3. Right click on the NVDA icon in the system tray and select the “Save configuration” menu item in the context menu.
Changing The Virtual Buffer Toggle Keyboard Shortcut
  1. Shut down NVDA - right click on the system track icon and choose “Exit” from the context menu.
  2. Navigate to the path “C:\Program Files\NVDA\appModules”.
  3. Open the file named “_default_desktop.kbd”.
  4. Find the line: “NVDA+space=toggleVirtualBufferPassThrough”.
  5. Change to: “Control+Shift+space=toggleVirtualBufferPassThrough”.
  6. Save the file.
  7. Restart NVDA.
Step 4: Restart Windows & Save State

With all of the screen readers installed and configured, restart Windows. Once Windows is restarted, take another snapshot of the virtual machine’s state. If you are using the free, trial versions of JAWS and Window-Eyes they will require you to restart Windows after using either product for ~30 minutes. Using the virtual machine, you can revert back to using JAWS and Window-Eyes more quickly than you would if you had to restart Windows.

Steps Summary

That’s it. The steps for configuring your development environment for testing using a screen reader can be summarized as follows:

  1. Install virtualization software
  2. Install browsers & take a snapshot of that state
  3. Install and configure screen readers
  4. Restart the virtual machine & take a snapshot of that state
Resources & Further Reader

YUI Theater — Douglas Crockford: "Ajax Performance"

Tue, 2008-12-23 16:07

Douglas Crockford returns to YUI Theater with another chapter in his evolving lecture series. This session, “Ajax Performance,” debunks common misconceptions about the relationship between JavaScript and performance and gives engineers a core focus for improving the performance of web apps: Reduce the value of n. Because DOM interactions are generally slow, leveraging Ajax to reduce the number of DOM operations, Douglas argues, is often the most important optmization you can make. In fact, it usually dwarfs other techniques in terms of its impact on the actual experience of using a website.

This talk joins an extensive library of Douglas’s lectures now available on YUI Theater, including his popular series on JavaScript.

Douglas Crockford: "Ajax Performance" @ Yahoo! Video

download (m4v)

In Case You Missed…

Some other recent videos from the YUI Theater series:

Subscribing to YUI Theater:

YUI Theater — Nicole Sullivan: "Design Fast Websites (Don’t Blame the Rounded Corners)"

Tue, 2008-12-23 16:04

Nicole Sullivan is a website performance specialist and a former member of Yahoo’s Exceptional Performance Team. She is currently writing a book for O’Reilly with Stoyan Stefanov on performance optimization and she and Stoyan are the creators of Smushit, an engine for crushing images.

Nicole visited Yahoo last week to do an encore of her "Design Fast Websites" talk in which she outlines a set of practical guidelines for building websites that are supremely fast and visually rich. Her advice is to know your craft, to engage your designers, and to make sure that your collaboration with designers works intelligently in the service of users. She was kind enough to let us record the talk and share it with you here on YUI Theater.

Nicole Sullivan: "Design Fast Websites" @ Yahoo! Video

download (m4v)

In Case You Missed…

Some other recent videos from the YUI Theater series:

Subscribing to YUI Theater:

Implementation Focus: pulpTunes

Wed, 2008-12-17 21:41

Alejandro Pedraza got his degree in Economics and was quickly bored to death in a regular office job for a couple of months. He realized he should follow his true life’s calling and turn night-and-weekend programming into something that would pay the bills, too. A failed startup and a couple of jobs later as lead developer, he’s been concentrating on building apps on the LAMP stack and Java and contributing to many open source projects during his free time. He is the author of pulpTunes, a new way of accessing your iTunes library via a Web browser. pulpTunes makes extensive use of YUI.

What got you interested in building a web interface to iTunes? Or is that a dumb question?

(No, not a dumb question :)) I’ve got a sizable song collection in my iTunes. An app for providing myself with web access seemed like a nice thing to have, and it would give me the opportunity to play with web and desktop technologies in the same application.

You chose YUI for many of the UI elements in your app. What specific YUI components are you using, and for what purposes?

YUI’s consistency and reusage of components accross the whole ecosystem lets you easily pick up on any new component you might need as the project advances. So I’ve been trying to stick with YUI-only, and I had to look elsewhere just for the flash song player, for obvious reasons.

pulpTunes produces a single web page, whose layout is declared through the Grids CSS lib. No need of nasty CSS hacks, and you can guarantee your page will look the same in all major browsers. This is one of my favorite YUI libraries, because of the huge time savings and peace of mind it provides.

The songs list is a DataTable accompained by a Paginator, fed through an XHR connection. Customizing the table and pagination looks was really easy by just overriding some CSS rules from the Sam skin, which is very well commented. The custom formatter for the Rating column is a 3-liner javascript code. The table (and the playlist section to the left) make use of the menu component to show a context menu to perform operations on a song or playlist.

I’m using a Slider component to adjust the player’s buffer. With it you point at which point in download progress you want the song to start playing.

There are few popup messages and dialogs in the app, that are rendered using the Container component.

Most of the YUI components I used (there are 12) are fetched from yui.yahooapis.com in a single request through the very convenient YUI Loader. And of course, I’m using the YUI compressor to compress to 15k the one javascript file that holds all the app’s logic.

You’re using Dav Glass’s Effects Package in addition to YUI. What functionality are you drawing from Dav’s collection specifically?

Coming from a Prototype+Scriptaculous world, I was very relieved to find that somebody had already ported to YUI all the great effects from Scriptaculous. And [because Dav is a member of the] YUI team, I could rest assured about its quality. I’m using the BlindDown and BlindUp effects to show and hide the songs cover art.

One of the main elements of your app is the DataTable that you use to display the songlists. What was your experience like building an XHR-fed DataTable with JSON data? What lessons did you learn that are worth sharing with other developers?

The XHR feeding part was pretty straightforward. Although I remembered trying to return some HTML in the JSON response which didn’t work, but that looked like a browser bug.

Pagination and sorting was easy as well, but I had to provide a custom generateRequest function because, if I recall correctly, YUI assumes the records should be sorted since the first request to the server, and in my case I wanted to wait till the user actually clicked on a column header to start returning sorted records.

I also had some trouble at first when trying to retrieve specific records in the table, but then I realized the existance of a whole bunch of helper methods just for that, like getTrEl() and getRecord() that are not mentioned in the general docs. So my obvious advice is that your read the entire API for any component you’ll be doing heavy work on.

pulpTunes is a SourceForge project. Are you looking to build a community of developers to work on the project with you?

Yes, that’s the idea. I’m also using SourceForge to track bugs and feature requests, so any kind of feedback from users is also welcomed. Graphical designers are invited as well, if they want to provide additional skins for the app.

What’s next for pulpTunes?

It’s been just a few days since the first stable release is out, and the response has been tremendous. I think I have already a pretty good idea of the major features for the next version: user authentication, search, shuffle and repeat buttons, and ability to rate songs.

In the Wild for December 12, 2008

Sat, 2008-12-13 00:22

This will be our last “In the Wild” post for 2008. It’s been a fun year, filled with a lot of exciting implementations and other developments in the YUI world. Here are the once we’ve noted lately:

  • YUI Sightings — PulpTunes: Here’s the elevator pitch for PulpTunes: “You’ve got a huge music collection in your iTunes at home.  You want to access that music from the office, at a friend’s party, or let other people hear it from anywhere in the world.  Install PulpTunes and access your music from anywhere, through a web browser.”  Check out the demo (filled with Creative Commons-licensed tunes) and see what a fantastic job Alejandro Pedraza has done in making a web-based jukebox app powered by a variety of YUI components.
  • Visual Event for YUI and JQuery: Visual Event is the brainchild of Allan Jardine.  Here’s how he describes it: “When working with events in Javascript, it is often easy to loose track of what events are subscribed where. This is particularly true if you are using a large number of events, which is typical in a modern interface employing progressive enhancement. Javascript libraries also add another degree of complexity to listeners from a technical point of view, while from a developers point of view they of course can make life much easier! But when things go wrong it can be difficult to trace down why this might be.  It is due to this I’ve put together a Javascript bookmarklet called Visual Event which visually shows the elements on a page that have events subscribed to them, what those events are and the function that the event would run when triggered. This is primarily intended to assist debugging, but it can also be very interesting and informative to see the subscribed events on other pages.”  Visual Event supports jQuery and YUI (version 2.6.0 has been tested, but others work as well).
  • YUI Sighting — G-Snap!: G-Snap is a new service that let’s you tap into ad-hoc communities that form around real-time events — say, an NFL game or a political rally.  Events are called snapcasts, and you can join them or create them on the fly, from your desktop or by phone.  The snapcast UI relies heavily on YUI, incorporating most of the utility foundation and several widgets.
  • Music Startup Bandcamp Using YUI: Oddpost co-founder Ethan Diamond has created Bandcamp as a means of providing bands with a means of distributing and promoting their music.
  • A Review of (and Tutorial For) YUITest: Fredrik Kalseth recently published on his blog an entry titled JavaScript is Code Too: Test It!. It’s well worth a read. After quickly summarizing why unit testing is important he walks through the steps necessary to create a unit test for a simple edit-in-place behavior. (Note that his edit-in-place code is written in jQuery; YUITest will test any type of JavaScript - the JS to be tested need not be written using YUI.) He concludes with his overall impressions of YUITest. Full source code for his demo test is available for download.
  • New YUI Controls Added at YUIAsp.Net: The YUIAsp.Net project has released another batch of YUI controls into the mix.  It now supports: AutoComplete, Button, Calendar, Charts, ColorPicker, DataTable, Editor, Logger, Menu, Paginator, Slider, TabView, and TreeView.  It’s now easier than ever to use YUI in your .Net projects.
  • YUI Sightings — WishAHome.com, Indian Real Estate Site: WishAHome.com is a real estate portal, according to its authors, that targets “Indian users [and] that tries to provide property listings in a unique and innovative way. The information provided by the site is to-the-point and extra care has been taken to ensure that the information posted by users is accurate.”  The site makes extensive use of YUI, including a nicely-skinned implementation of Matt Sweeney’s YUI TabView Control on the home page.
  • Creating a TextBox Calendar with YUI: Ryan Moore of Toolbox.com has been exploring YUI, and he’s posted one of the fruits of his early exploration — an adaptation of the YUI Calendar ControlWrites Ryan: “This class is based on code posted by DavGlass, which was for YUI .12 - it allows you to pop up a YUI Calendar Control when you click on a text box, and then populate the text box with the calendar’s value when a date is selected.”
  • Todd Kloots on CodeTalks ARIA Theatre: The fantastic CodeTalks site, dedicated to web accessibility, has an ARIA Theatre section to which YUI accessibility specialist Todd Kloots’s recent video has been added.  This video archive should become a valuable resource for front-end engineers as it aggregates tech talks on the art and science of building accessible web applications.
  • BlueGriffon Adds Support for YUI CSS Grids-based Layouts: Daniel Glazman from the BlueGriffon project has added support for Nate Koechley’s YUI CSS Grids.  BlueGriffon is a web page editor based on the Gecko rendering engine that powers Firefox.
  • Text Area Character Throttle: Some people (I’m not naming names, although “Miraglia” is a long name) tend to run on and on if you give them an open text field, so it’s sometimes necessary to throttle their otherwise undisciplined input in hopes that they’ll remove redundant, repetitive adjectives before submitting your form.  Lustr.nl has a YUI-based solution for you with its textarea character throttle.
  • YUI in DreamWeaver CS4: YUI founder Thomas Sha has been working with Adobe to improve YUI support in the new DreamWeaver CS4.  He’ll have more to say about this soon on the blog, but the question came up in the forums and we wanted to point you to Thomas’s response.  If you’re already using CS4, check out Thomas’s notes on how to get started with the new YUI extensions.
  • YUI Sightings — Montagraph: Montagraph is a fun site that allows you to create photo montages quickly from existing templates or to create your own template for sharing with others.  A number of YUI components, including Dav Glass’s ImageCropper Control, are in use on the site.
  • YUI Sightings — Life Log: Writes Life Log’s author, Haitao Li: “What were you doing ten years ago today? You would know if you used Life Log. Log your life, your work, or take meeting notes with tags. It even works as shared clipboard across computers.”  Life Log uses a variety of YUI components, including Matt Sweeney’s YUI TabView Control. (Original source.)
  • Make a YUI Menu of Your WordPress Pages: Chris McAfferty shows you how to load all your WordPress pages into a YUI Menu for compact, accessible access.  He gives you the WP code and notes that you need to load YUI Menu yourself; load it from Yahoo’s servers in two files (one for CSS and one for JS).

As always, please let us know what we missed by leaving a comment below.

YUI 3.0 PR2 Now Available: Widget and Plugin Infrastructure, Sample Widgets, and More

Wed, 2008-12-10 00:48

We’re pleased today to announce the second preview release of the new YUI 3.x codeline. This release adds significantly to PR1, providing an all-new widget foundation, two sample widgets, a new plugin architecture, a new ultralight plugin for menu-style navigation, and enhancements throughout the library. We’ve ported YUI Test and Profiler from 2.6.0, moving two steps closer to parity with the YUI 2.x core and utility platform. YUI 3.0 PR2 is available for download immediately from YUILibrary.com; you can discuss the release with the YUI community in the YUI3 forum on Yahoo Groups.

A key part of our focus in YUI 3.x is to provide more granularity so that you can fine-tune your implementation to include only the features that you’re actually using for a given component (watch the 3.x overview video for more on the larger goals for this codeline). Each 3.x component ships with a small functional core, and advanced features are added in the form of plugins or optional submodules. The submodule pattern was illustrated in PR1. In PR2, we’re adding in the Widget infrastructure, designed to promote maximal modularity and code reuse, along with two reference widgets. We’re also debuting the Plugin infrastructure. Plugins can be written to supplement a simple Node or to add features to a widget in a lightweight, a la carte fashion.

Here are the highlights of PR2:

  1. Widget Infrastructure: The biggest addition in PR2 is the debut of the Widget infrastructure. PR2 delivers the base Widget class for YUI 3.x, which will be the foundation class for all formal YUI widgets. (In 2.x, we called these components "controls" in order to avoid confusion with Yahoo/Konfabulator widgets, but in 3.x we are standardizing on "widgets.") The Widget class extends Base, which was part of PR1. If you’re interested in exploring the Widget infrastructure, we recommend reviewing Node, Event, Base, Widget, and Overlay (in that order) to get a sense how these pieces fit together.
  2. Slider, Overlay, Console Widgets: Slider, Overlay and Console (what was LogReader in 2.x) are provided as the initial set of widget implementations for YUI 3.x, along with examples leveraging the Widget infrastructure. Overlay will be of particular interest to those of you who want to study the inner workings of the modular Widget system. It is constructed by combining the core Widget module with WidgetPosition (basic xy positioning), WidgetPositionExt (extended positioning: align, center), WidgetStdMod (standard module support) and WidgetStack (zIndex, shim support) extensions, which can be mixed and matched as required to provide other custom implementations. These initial widgets are meant to establish and confirm the concepts we’re promoting in 3.x with respect to granular, reusable code. The widgets are likely to change as we move toward the GA for 3.x, but they should give you a good sense of how the library’s new core is performing.
  3. Plugin Infrastructure: Plugins provide atomic pieces of functionality that can be mixed and matched with other plugins to modify or add functionality on an existing widget (or Node). For example overlay.plug({fn:StdModIOPlugin, cfg:pluginCfg}) instantiates the StdModIOPlugin class and adds it to the host widget as the io property (the namespace defined by the plugin), adding input/output capabilities. In addition to adding completely new functionality, plugins may also modify existing functionality on the host by listening for events or by injecting code before or after the execution of methods on the host. For example, an Animation plugin might provide configurable animation effects that modify the base widget’s native hide and show methods.
  4. Node Plugins: The MenuNav Node Plugin provides a lightweight but feature-rich navigation menu as a simple one-line plugin to Node, with content/functionality driven entirely through markup/CSS. MenuNav, and Node plugins in general, are ideal choices for light implementations that don’t need programmatic (API/event) access to the control once instantiated. MenuNav is the first such Node plugin implementation for YUI 3.x, and it replicates the most commonly used functionality from the YUI 2.x Menu Control in under 5KB (gzipped) JavaScript and CSS.
  5. Event Updates: Event simulation (the ability to programatically fire events) has been moved into the Event utility in 3.0PR2; event simulation was previously part of YUI Test. The subscribe/publish methods have been expanded to support subscribing to or publishing mutliple events in a single call. Supplementary global events (available, contentready, focus, blur) and keyboard event support has been added.
  6. IO Updates: The IO utility adds form-mining and file upload support, available as optional sub-modules. Existing queue and cross-domain request (XDR) support have been broken out into optional submodules to increase the granularity of the component. Now, users not interested in the advanced features (queuing, XDR, form-mining, file upload), can use the lighter io-base module.
  7. Developer Tool Updates: The YUI Test framework, Profiler, and the Console widget are now available in the PR2 release. YUI Test adds support for mock objects. Mock objects allow you to isolate your tests from dependent code by defining objects that behave in predictable ways. Create mocks of XMLHttpRequest, document, or any other object on which your code depends without depending on the actual implementation.

Again, we’re eager for your feedback and hope you enjoy checking out this second Preview Release.

YUI Doc: A New Tool for Generating JavaScript API Documentation

Tue, 2008-12-09 00:11

We’re pleased today to release the first public version of YUI Doc, a python-based documentation tool that generates API documentation for JavaScript code. YUI Doc was developed by Adam Moore, one of the principal engineers on the YUI project since its inception, to support YUI’s API-level documentation.

Those familiar with JavaDoc, JSDoc, or the JsDoc Toolkit (the latter superceded JSDoc, which no longer sees active development) will find YUI Doc’s conventions familiar. It is a comment-driven system in which documentation is parsed from comment blocks that describe the structure of your code. Unlike some analagous systems, YUI Doc is designed to work purely from comments; as a result, there is no idiom or code pattern with which the tool is incompatible.

YUI Doc’s principal organizational structures are these:

  • Project: The project is the top-level bucket into which a set of documentation is grouped. In the case of YUI’s documetnation, YUI itself is the project.
  • Module: A module is used to group pieces of code that relate to a functional unit. For example, in YUI the Drag and Drop Utility is a module; the AutoComplte Control is a module; etc. Modules can depend on one another and can be further subdivided into submodules (in YUI 3, we make extensive use of submodule structures to deliver the smallest possible code payloads).
  • Class: Classes (and inner classes) are used to describe objects that function as instantiable or static classes in JavaScript. YUI Doc also supports concepts like augmentation, allowing you to document the inheritance structures that characterize your object-oriented applications.
  • Methods and Properties: Methods and properties are used in the conventional sense to document class members.
  • Events: We’ve added the event construct to YUI Doc to support YUI’s Custom Event infrastructure. Where you are building modules that publish events with well known parameters, YUI Doc can help you expose that information through this construct. (As a simple example, when a date is selected in the YUI Calendar Control, the selectEvent is fired.

YUI Doc is most likely to be of interest to those who are building library-style code to be used by other developers. Because it requires in-line documentation, it is only appropriate to use YUI Doc in combination with a minification tool (like Douglas Crockford’s JSMin or Julien Lecomte’s YUI Compressor). A common scenario would be to incorporate YUI Doc into an existing continuous-build process to generate and publish documentation at build time; your code might be concatenated and version-stamped by Ant, verified by JSLint, documented by YUI Doc, and then minified by YUI Compressor.

YUI Doc joins YUI Compressor in the portfolio of build-time processes that we’re making available as part of the YUI project. We look forward to your feedback on this beta release. The source code for YUI Doc has been published on GitHub; if you’d like to get involved in YUI Doc development, we invite you to check out the source (instructions here), sign a CLA, and join us in making this the best documentation engine available for serious frontend engineers.

Footnote: We’re hard at work prepping the YUI 2.x and 3.x code repositories for GitHub deployment as well. We’ll have more to share with you on that front in the near future.

YUI Theater — Todd Kloots: “Developing Accessible Widgets with ARIA”

Mon, 2008-12-08 14:35

The Accessible Rich Interet Applications (ARIA) specification is in working-draft form in the W3C. It provides a framework for implementating rich web-applications that convey improved semantics to screen reader software as a user interacts with a page. ARIA is patterned after the more established desktop experience, but it also provides a set of tools that allows room for invention.

In this talk, delivered at Yahoo! on December 3, 2008, YUI engineer and accessibility specialist Todd Kloots introduces you to ARIA and provides some insights gleaned from his work in bringing ARIA support to a host of YUI widgets.

Slides for Todd’s talk can be downloaded here (180MB ppt includes screencaptures of ARIA scenarios as experienced with a screen reader).

A full transcript of this video is available here.

Todd Kloots: "Developing Accessible Widgets with ARIA" @ Yahoo! Video

download (m4v)

In Case You Missed…

Some other recent videos from the YUI Theater series:

Subscribing to YUI Theater:

Image Optimization, Part 5: AlphaImageLoader

Mon, 2008-12-08 13:48

About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript.

This is part 5 in an ongoing series. You can read the other parts here:

This installment of the image optimization series is about the IE-proprietary AlphaImageLoader CSS filter, which developers often use as a workaround to solve transparency issues with truecolor PNGs in IE. The problem with AlphaImageLoader is that it hurts page performance and, therefore, hurts user experience. I argue that AlphaImageLoader should be avoided when at all possible.

Quick Refresher

As mentioned in a previous article, PNGs come in several different types but can roughly be divided into:

  • Indexed (palette), also referred to as PNG8 which have up to 256 colors.
  • Truecolor PNG, also referred to as PNG32 or PNG24.

Both formats support alpha (variable) transparency and, while PNG8 images degrade to a GIF-like non-variable transparency in IE6 (example, source), truecolor PNGs show an uglyish background in place of the transparent pixels (source W3C).

The AlphaImageLoader fix

IE6 (and older versions of IE) provides a solution to the problem through its proprietary filter CSS property. The following code will display the proper image cross-browser:

#some-element { background: url(image.png); _background: none; _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='crop'); }

As you can see, the underscore CSS hack is used to target IE < 7 and

  1. “undo” the background; and
  2. load the same image, using Microsoft’s AlphaImageLoader filter.

The reason to target IE prior to version 7 is that IE7 supports the alpha transparency natively without the need for filters. (IE8 does too and it actually changes the filter syntax completely.)

It’s interesting to note that the filter doesn’t change the image; rather, it changes the HTML element this style is applied to. The other interesting thing is that each element is processed synchronously in a single UI thread. The process applying the filter takes some resources for each element and the more “filtered” elements you have, the worse it gets, even if you use the same image for all the elements.

The question is: How does this affect the overall performance of the page?

Freeze! Side Effect #1

Here’s a simple experiment: Create a page that has a CSS filter and then simulate (and exaggerate) network latency by delaying the image used in the filter by ten seconds. The result? Not only is nothing rendered (blank page) for ten seconds, but the browser freezes, meaning you cannot interact with it, click its icons or menus, type in the URL…you can’t even close it.

Here’s a test example.

In the example, I didn’t use the underscore hack so you can see the (d)effect in IE7 too, even in IE8 in “compatibility mode”.

While the effect is exaggerated for demo purposes, network latencies are a fact of life and this is probably the worst user experience you can deliver: Someone comes to your page and their browser freezes.

Note that parallel downloads are not blocked. The browser still downloads the other page components in the background, but there’s no progressive rendering. You can think of it this way — since IE will not render anything until the very last bit of CSS comes down the wire (more info), and your because CSS has a dependency on a filtered image, the rendering is blocked until the dependency is satisfied.

What if you have several AlphaImageLoader filters on the page? They are processed synchronously one after the other so the problem is multiplied. If you have 5 images, each delayed 2 seconds on the server, then the browser freezes for a total of 10 seconds.

Time and Memory — Side Effects #2 and #3

Another negative effect of using the AlphaImageLoader is the increase of the amount of memory required to process and apply the filters. These days we might be tempted to think our visitors’ computers have a virtually indefinite supply of memory, but for older computers (those more likely to run IE6 and under) this may not be the case.

And at the end of it, it’s the performance we’re most interested in, performance as measured by the time it takes for the page to load in the browser. Let’s do a test to measure how much time and memory is required by the filters.

First, let’s have a baseline page — one that has a hundred <div>s with the same non-filtered background image. Then let’s have a second page with a filter applied to the divs (all 100 divs use the same). A hundred elements with filtered backgrounds is unlikely to be found in a normal page, but a little exaggeration will help with the measurements.

The time is measured from the start of the page to the onload event of the page, after the images have been cached, thus eliminating the time required to download the page and the images. The memory consumption is measured with the help of the ProcessExplorer tool and given as the before/after delta of the private bytes measurement, showing the “price” of rendering the page.

Here are the median results from 10 runs in IE6 on a PC with a dual 2GHz CPU and 500M RAM. On a less powerful computer, the load times are likely to be even worse.

td.number{text-align:right} AlphaImageLoader test results test page time, seconds memory, MB Test #1 - no filters 0.031 0.6 Test #2 - with filters 0.844 46.8

As you can see, the AlphaImageLoader effect is pretty bad — our test page loads 27 times slower and eats up 78 times more memory. These results are, of course, highly speculative — it’s just one image tested on just one PC (relatively powerful and underworked). With different images, applied to a different number of elements and on different machines, results may vary considerably, especially when there’s less RAM or CPU, or if you throw network latency (side effect #1) into the mix. But this example illustrates the important concepts:

  • AlphaImageLoader is slow and requires more memory
  • It’s applied per element, not per image

If you have a sprite image and you use it for different elements (sprites with alpha filters are trickier, but doable), you’ll pay the penalty for each element the sprite is used on.

Yahoo! Search Case Study

Using lab tests like the one above can give us some idea of the AlphaImageLoader “price,” and you might be tempted to test and calculate approximately how much you pay for each filtered element, but there’s nothing better than a real life test with millions of requests coming form different parts of the world with different browsers, computers and bandwidth.

Yahoo!’s search results page used to have a truecolor PNG sprite and employed AlphaImageLoader to achieve the transparency (an older version of the sprite is still around if you’re curious). Replacing the truecolor PNG with a gracefully degrading PNG8 (discussed previously) decreased the pageload time by 50-100ms for the users of IE 5 and 6. 100ms may not seem like much, but for a page that loads under a second, it’s at least 10%. Also, according to an Amazon study, 100ms slower means 1% fewer sales (even for their content-heavy pages). Earning 1% more by just replacing an image doesn’t look like a bad deal at all.

So Now What?

The best thing would be to avoid AlphaImageLoader completely and, like Y!Search, take the time to create PNG8 images that degrade nicely in IE6 and look good in all other browsers. How do you create a gracefully degrading PNG8? Well, create a GIF-like image first, one that has only fully transparent or fully opaque pixels. After making sure it looks acceptable (it will look like this in IE6), proceed to enhancing the image with semi-transparent pixels which will smooth any rounded corners or other parts that would benefit from transparency. Unfortunately, as far as I know, Fireworks is currently the only image processing software capable of handling alpha transparency in PNG8. You can also try command line tools such as pngnq and pngquant, although automated truecolor-to-palette PNG conversion might not always yield satisfactory results and you might need to pick the fully opaque pixels manually.

There might be cases when you won’t be able to get by with a PNG8 and absolutely need to use AlphaImageLoader — for example when most or all pixels are semi-transparent (imagine a “play” button over a video thumbnail). Dave Artz of AOL has some other cases where PNG8 will not be good enough. In such cases (but only after you try your best to persuade the designer to reconsider the use of transparency), make sure you use the underscore hack (_filter) so that you don’t penalize IE7 users.

Sometimes instead of PNG8 people use GIF for IE6 and truecolor PNG for the others, but that’s not necessary; with one PNG8 you achieve both binary and alpha transparency.

Additional benefits from using a PNG8 are:

  1. PNG8 is usually smaller than truecolor PNG,
  2. only one image to maintain for all browsers
  3. cleaner CSS with no hacks, branches or proprietary tags
  4. ability to repeat background
Transparency with VML

Using VML is yet another option in IE to make a truecolor PNG transparent, and it solves several problems: alpha transparency, performance, and background repeat. Unfortunatelly, it comes with the price of extra non-standard markup (or dependency on JavaScript to generate it if you want your initial markup clean) and more propritary CSS. Here’s an example on how to implement it.

If, for example, you have an empty div, you need to wrap it in one VML :rect (or :shape) and one :fill element, like this:

<v:rect> <v:fill type="tile" src="alphatest.png"> <div>&nbsp;</div> </v:fill> </v:rect>

Somewhere in the markup before that you also need to declare a VML namespace:

<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />

And in your stylesheet you need:

v\:rect { behavior:url(#default#VML); width: 100px; height: 100px; display: block; } v\:fill { behavior:url(#default#VML); }

A test page with 100 VML rect elements loads in 0.094 seconds (almost 10 times faster than using filters) and the memory usage is under 4Mb (10 times less than the filtered page).

As you can see this solution adds more markup and proprietary CSS, but it’s still a solution and doesn’t have the penalties of the AlphaImageLoader.

(Thanks go to this post by Drew Diller and also HTML Remix, who accidentally found this side effect while working on another problem — rounded corners with VML, via snook.ca)

P.S. …and What about Other Filters

AlphaImageLoader is not the only filter that exists. Another popular one is the opacity filter.

For example, for 50% element opacity developers use the properties:

  • opacity: 0.5 (standard),
  • -moz-opacity: 0.5 (early Mozilla versions, before Firefox 0.9), and
  • for IE, filter: alpha(opacity=50).

A quick test in IE6 shows that the opacity filter is not nearly as slow as the AlphaImageLoader, but it’s still making the page slower and takes the same amount of memory. This test uses color background, not an image, but even with an image the results are pretty much the same.

opacity filter test results test page time, seconds memory, MB Test #3 - 100 divs, no opacity 0.016 0.2 Test #4 - 100 divs with opacity 0.093 46.7

Image Optimization, Part 4: Progressive JPEG…Hot or Not?

Fri, 2008-12-05 16:23

About the Author: Stoyan Stefanov is a Yahoo! web developer working for the Exceptional Performance team and leading the development of the YSlow performance tool. He also an open-source contributor, conference speaker and technical writer: his latest book is called Object-Oriented JavaScript.

This is part 4 in an ongoing series. You can read the other parts here:

In the previous article, the progressive JPEGs were briefly mentioned as a possible option when optimizing JPEGs. This post now diggs into this option a little deeper with the results of an optimization experiment involving over 10,000 images.

Baseline vs. progressive JPEGs

Baseline are the “normal” JPEGs, the type of JPEG that all image programs write by default. The browsers load them top-to-bottom as more of the image information comes down the wire.

Loading a baseline JPEG, click to enlarge

Progressive JPEGs are another type of JPEGs, they are rendered, as the name suggests, progressively. First you see a low quality version of the whole image. Then, as more of the image information arrives over the network, the quality gradually improves.

Loading a progressive JPEG, click to enlarge

From usability perspective, progressive is usually good, because the user gets feedback that something is going on. Also if you’re on a slow connection, progressive JPEG is preferable because you don’t need to wait for the whole image to arrive in order to get an idea if it is what you wanted. If not, you can click away from the page or hit the back button, without waiting for the (potentially large) high quality image.

A reason against progressive JPEGs I’ve heard is that they look a bit old school and that users might be underimpressed, if not irritated, by the progressive rendering. I am not aware of a user study that focuses on this issue, please comment if you have heard or conducted such a experiment.

There is controversial information in blogs and books whether progressive JPEGs are bigger or smaller than the baseline JPEGs in terms of file size. So, as part of the never-ending quest for smaler file sizes and lossless optimization, here is an experiment that attempts to answer this question.

The experiment

One of the many free APIs that Yahoo! provides is the image search API. I used it to find images that match a number of queries, such as “kittens”, “puppies”, “monkeys”, “baby”, “flower”, “sunset”.. 12 queries in total. Once having the image URLs, I downloaded all the images and cleaned up 4xx and 5xx error responses and non-jpegs (turned out sometimes sites host PNGs or even BMPs renamed as .jpg). After the cleanup there were 10360 images to work with, images of all different dimensions and quality, and best of all, real life images from live web sites.

Having the source images, I ran them through jpegtran twice with the following commands:

> jpegtran -copy none -optimize source.jpg result.jpg

and

> jpegtran -copy none -progressive source.jpg result.jpg

The first one optimizes the Huffman tables in the baseline JPEGs (details discussed in the previous article). The second command converts the source JPEGs into progressive ones.

Let’s see what the result file sizes turn out to be.

Results

The Census report, like most such surveys, had cost an awful lot of money and didn’t tell anybody anything they didn’t already know — except that every single person in the Galaxy had 2.4 legs and owned a hyena. Since this was clearly not true the whole thing had eventually to be scrapped.

Douglas Adams — “So Long, and Thanks for All the Fish”

The median JPEG returned in this experiment was 52.07 Kb, which is probably not the most useful statistic. The important thing is that the median saving when using jpegtran to optimize the image losslessly as a baseline JPEG is 9.04% of the original (the median image becomes 47.36 Kb) and when using a progressive JPEG, it’s 11.45% (46.11 Kb median).

So it looks like progressive JPEGs are smaller on average. But that’s only the average, it’s not a hard rule. In fact in more than 15% of the cases (1611 out of the 10360 images) the progressive JPEG versions were bigger. Since it’s difficult to predict when an image will be smaller as progressive by just looking at it (or for automated processing without even looking at it), an idea of how the image will perform based on its dimensions or file size would be really helpful.

Looking for a relationship, I plotted all the results on a graph where:

  • Y is the difference in the savings “baseline minus progressive”, so negative numbers will mean cases when baseline is smaller

  • X is the file size of the original image

The graph shows how the results are all over the place, but there seems to be a trend — the bigger the image, the better it is to save it as a progressive JPEG.

“Zooming” into the area of smaller file sizes to see where progressive JPEGs get less effective, let’s only consider the images that are 30K and under. Then using the trendline feature of Excel, we can see where the line is drawn (for a clearer trendline mouse over or focus or click the image).

src="http://yuiblog.com/assets/2-progressive-jpeg.png"
id="progressive-jpeg-chart"
alt="Progressive vs baseline JPEG for smaller images"
/>

(function(){ new Image().src = \'http://yuiblog.com/assets/3-progressive-jpeg.png\'; var i = document.getElementById(\'progressive-jpeg-chart\'); var a = i.parentNode; a.onmouseover = a.onfocus = function() {i.src = \'http://yuiblog.com/assets/3-progressive-jpeg.png\';}; a.onmouseout = a.onblur = function() {i.src = \'http://yuiblog.com/assets/2-progressive-jpeg.png\';}; })();

Summary

The take-home messages after looking at the graphs above:

  • when your JPEG image is under 10K, it’s better to be saved as baseline JPEG (estimated 75% chance it will be smaller)
  • for files over 10K the progressive JPEG will give you a better compression (in 94% of the cases)

So if your aim is to squeeze every byte (and consitency is not an issue), the best thing to do is to try both baseline and progressive and pick the smaller one.

The other option is have all images smaller than 10K as baseline and the rest as progressive. Or simply use baseline for thumbs, progressive for everything else.

IE and progressive JPEGs

“Oh, not IE again!” is probably what you’re thinking, but it’s not so bad actually. It’s just that IE doesn’t render progresive JPEGs progressively. It displays the image just fine, but only when it arrives completely. So in IE, the baseline JPEGs display more progressively (top-to-bottom is still progress) than the progressive JPEGs.

A word on ImageMagick

ImageMagick is a an impressive set of command-line image tools, which you can also use to optimize files. Unlike most other image software, by default ImageMagick writes optimized baseline JPEGs (as if using the -optimize switch in jpegtran).

ImageMagick can also strip meta data and write progressive JPEGs, so I repeated the experiment outlined above but using ImageMagick instead of jpegtran. The commands used were:

>convert -strip source.jpg result.jpg // baseline JPG >convert -strip -interlace Plane source.jpg result.jpg // progressive JPEG

Observations from the ImageMagick experiment:

  • The baseline vs. progressive trendline is the same: images 10K or bigger are better optimized when using progressive encoding
  • The overall compression is better: the median is 10.85% optimization for baseline JPEGs (jpegtran saved 9.04%) and 13.25% for progressive JPEGs (11.45% with jpegtran)
  • There is some quality loss. ImageMagick doesn’t perform fully lossless operations. Inspecting random images visually I couldn’t tell any difference but using an image diff utility shows that pixel information in the images has been modified.

And the last set of stats gleaned from the experiment has to do with the speed of writing JPEGs. Here’s how jpegtran and ImageMagick performed while optimizing the 10k+ images on my laptop (Windows XP, 2GHz dual CPU, 500Mb RAM). From fastest to slowest:

  1. jpegtran baseline (11 images per second),
  2. jpegtran progressive (9 images/s),
  3. ImageMagick baseline (7 images/s),
  4. ImageMagick progressive (5.5 images/s)

Getting Started with JavaScript Unit Testing and YUI Test

Mon, 2008-12-01 16:34

For a long time, the web has been a wild west of technology. It’s only been within the past five years that any sort of rigor has been applied to web development and technologies such as HTML, CSS and JavaScript. JavaScript development has been the most affected, bringing discipline from other types of programming into what previously was a free-for-all of copy-paste code. Of the traditional programming techniques, unit testing has just started to make its way into JavaScript.

The purpose of unit testing is to test an individual part of a program (a "unit"). Testing the smallest part of a program and ensuring that it works gives some indicating as to the overall correctness/completeness of the entire program. In object oriented programming, this typically means testing each method individually, ensuring that certain inputs result in certain outputs. Having a suite of tests to run whenever you make changes can give you a measure of confidence that the changes didn’t unintentionally introduce additional bugs or regressions.

YUI Test is our framework for unit testing JavaScript. The goal of YUI Test is to make creating JavaScript unit tests fast and easy. We know from experience that developers’ main complaint about unit testing is that it takes too long, so everything about YUI Test is designed to make this process easier. Here’s how you can get started:

Step 1: Create an HTML file and include required files

Add in the YUI Test required files. These are outlined in the documentation:

<!--CSS--> <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/logger/assets/logger.css <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/yuitest/assets/testlogger.css"> <!-- Combo-handled YUI JS files: --> <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/logger/logger-min.js&2.6.0/build/yuitest/yuitest-min.js"></script> Step 2: Include your JavaScript

After including the default YUI Test files, you’ll need to include the JavaScript that you want to test. The best approach is to include individual JavaScript files that encapsulate the functionality to test. If your JavaScript requires some markup or CSS on the page to work correctly, you may want to include those as well.

Step 3: Create a test case

Test cases are created via the YAHOO.tool.TestCase constructor. The constructor accepts a single argument, which is an object that has at least a name property and one or more methods. If a method begins with the word "test" (all in lowercase), then it is considered a test to be run; all other methods are considered to be helpers.

To test your JavaScript, create one or more tests in the test case object. Each test should have at least one assertion. Assertions are used to indicate the expected result of an operation and are expressed as methods on YAHOO.util.Assert, YAHOO.util.ArrayAssert, YAHOO.util.DateAssert, and YAHOO.util.ObjectAssert. The most frequently used assertion is YAHOO.util.Assert.areEqual(), which is used to determine if two values are equivalent. The first argument is the expected value and the second is the value you’re testing. For example:

var testCase = new YAHOO.tool.TestCase({ name: "trim() Tests", testTrimWithLeadingWhiteSpace: function(){ var result = trim(" Hello world!"); YAHOO.util.Assert.areEqual("Hello world!", result); } });

This code tests a trim() function be sure that it removes leading white space from a string. A test string is passed through trim() and then the actual result is compared against the expected result. If the two don’t match, then an assertion failure is thrown and testTrimWithLeadingWhiteSpace() is marked as failed. You can have multiple assertions in a single test if necessary, but it’s generally a good idea to keep the number of assertions small so that you’re not testing too much in a single test.

Each test case must be added to the test runner before it can be executed, so each test case should be added like this:

YAHOO.tool.TestRunner.add(testCase);

Test cases are executed in the order in which they are added to the test runner.

Step 4: Execute tests

You can begin running tests once all of the test cases have been added to the test runner. This is generally done once the page has finished loading and so the onload event handler is a good place to begin:

window.onload = function(){ //create the logger var logger = new YAHOO.tool.TestLogger("testLogger"); //run the tests YAHOO.tool.TestRunner.run(); };

This code creates a new instance of the TestLogger, which outputs the results of the tests, and then runs all of the tests. This snippet of code can be used verbatim in any file to begin execution of the tests. As tests execute, the results are displayed in the TestLogger, which passes displayed in green and fails displayed in red.

All of this should be saved in a single HTML file. You need only load the file into your browser to see the results. For more, check out the examples or take a look in the tests directory of the YUI zip file.

Wrap-up

That’s all it takes to get started writing unit tests for your JavaScript. Keep in mind that your JavaScript doesn’t need to use YUI at all to take advantage of unit testing with YUI Test. The framework can be used to test any JavaScript code.

More information Video: Nicholas C. Zakas on Test-Driven Development and YUI Test:

Nicholas C. Zakas: "Test-Driven Development with YUI Test" @ Yahoo! Video

In the Wild for November 26, 2008

Wed, 2008-11-26 21:56

Needless to say, one thing all of us here at YUI headquarters are thankful for is the chance to work with all of you who have made the YUI community such a vibrant, challenging, inspiring place over the last three years. So, thanks from us. We hope your holidays are peaceful and full of happiness.

Here are some of the things we’ve seen in just the last week or so that have reminded us how much we love working on YUI:

  • Matt Snider’s Element Editor Class: Writes Matt: “The ultimate goal of the project is to develop a widget that can be used to dynamically update the content of any DOM node, by inserting an editable form field (input, textarea, select, etc.). In version 1, ‘Element Editor’ can replace a DOM node with a textarea or an input, allowing a client to replace the text inside of the DOM node. The widget contains a singleton Custom Event (1 Custom Event shared by all ‘ElementEditor’ instances), which can be subscribed to, that fires each time a user changes the DOM node content.”
  • YUI-based “Lava Lamp Menu” from Nicora.net: This is a really nice implementation of a nav menu that may be appropriate for sites that are looking for a smooth, richly finished feel.  Calling it a lava-lamp menu may be a little extreme — what it really does is animate the mouseover effect from one nav item to the next in a smooth, graceful way.  Not right for every site, but a sweet addition to the YUI Menu Control for sites where this kind of animation suits your design ethos. (Original source.)
  • Google Support for YUI on ajax.googleapis.com: As we announced on YUIBlog on November 19, Google is now hosting YUI files on its content distribution network (CDN), adding a second worldwide CDN from which to choose if you want to offload your YUI bandwidth and improve performance.  Better still, Google’s CDN provides SSL support, which means those of you hosting your own YUI implementations to run in secure environments can now move to a CDN solution if you wish.  Currently, combo-handling remains a Yahoo CDN-only optimization.  Head over to the Dependency Configurator if you’d like to set up an implementation drawn from Google’s network, or check out the Google Ajax Search API Blog’s writeup. (The Google Inside blog has an upbeat take on this development as well.)
  • Event Simulation Using YUI: More from Matt Snider: “Some browsers have begun to support event emulation allowing engineers to trigger client events, but most are incomplete and there is no standard x-browser way to simulate events. Fortunately, JavaScript Frameworks have come to the rescue, allowing us to simulate client events. YUI has the YUI Test Utility, which allows for the emulation of 7 mouse events and 3 keyboard events: click, dblclick, mousemove, mousedown, mouseup, mouseover, mouseout, keydown, keyup, and keypress. So by using YUI there actually is a standard, x-browser way to emulate events.”
  • YUI Sightings — Globber: There’s not much we don’t like about Globber, which is a slick portlet based on YUI.  It’s cute, well-designed, has sheep in the header, and shows a light-hearted, well-implemented take on the My Yahoo/Google IG genre.  If you’re looking for some inspiration for your YUI Drag and Drop based app, here’s a good place to start.
  • Asvin Balloo’s Event Delegation/Bubble Menu Exploration: Asvin Balloo (on his newly redesigned HTML Blog) writes: “Event delegation refers to the use of a single event listener on a parent object to listen for events happening on its children (or deeper descendants). Event delegation allows developers to be sparse in their application of event listeners while still reacting to events as they happen on highly specific targets. This proves to be a key strategy for maintaining high performance in event-rich web projects, where the creation of hundreds of event listeners can quickly degrade performance.…This post illustrates the use of event delegation to create a “bubble” menu, inspired by Bedrich Rios’ post on Nettuts.
  • YUI Carousel, Simple Pie for Blog Aggregation: Veeru makes another “In the Wild” appearance with a nice implementation of Gopal Venkatesan’s YUI Carousel Control: “Recently was looking at aggregating a few blogs — basically the need is to show all the latest posts from a list of pre-defined blogs — mostly food related. I started with zero knowledge on this one, but fortunately was able to figure out how to do it. This is what I have used: YUI Carousel to display the blog elements in a decent way, Simple Pie to read contents from atom feeds and rss feeds.”  Check out the example here.
  • Fresh Baked Goodness with the YUI Cookie Utility: Dan Wellman has posted another excellent tutorial on DMXZone, this one treating Nicholas C. Zakas’s YUI Cookie Utility.  Writes Dan: “The YUI provides us with an easy way of setting and getting cookie data, which abstracts away the strict syntax and dramatically shortens our scripts – which is a very good thing considering even the most basic functions for getting and setting cookie data are often in excess of 20 lines of plain-vanilla JavaScript, even without error checking that prevents an error being thrown if document.cookie is empty.  Throughout this tutorial I’m going to be assuming that you’ve worked with cookies before the old fashioned way and understand the principles behind their use. Even if you’ve never worked directly with cookies before however you should still be able to use the YUI Cookie Utility without any difficulties.”  You can download the full resource for $3.20 here.
  • YUI Sightings — Washginton State University Course Catalog: Go Cougs!  Jeff Craig, working among the beautiful rolling hills of Eastern Washington’s Palouse country in Pullman, Washington, has remade the WSU Catalog using YUI.  You’ll find ten YUI components being leveraged in Jeff’s implementation.
  • Sun Releases NetBeans 6.5 with Improved YUI Support: From the blog post: “We did a lot of work in NetBeans 6.5 around formalizing how we include various community-supported JavaScript libraries and toolkits. We bundle many of the popular ones, including JQuery, YUI, script.aculo.us, and Dojo. Those are now easily consumable right form within the IDE: You can just start using those inside a project. If you have your own JavaScript library, it’s very easy to add that through the library manager to create a library reference, pointing to your library. Once you pull a library into a project, all of the JavaScript editor features become available to you.”
  • YUI Sightings — The Consumerist: We’ve mentioned before the adoption YUI has seen among media sites.  It’s good to know in these difficult economic times that you can find YUI under the hood, too, at The Consumerist, so you can get some YUI goodness with your economic doom and gloom.
  • A Drap & Drop Example Using YUI Drag & Drop’s Ineraction Groups: Jorge at “A Developer’s Journal” writes: “I recently explored the drag-and-drop features of the YUI JavaScript library. I particularly liked the Interaction Groups example. While trying out the example, it occurred to me how perfectly suited it is for the user interface of a web-based board game. To test this idea, I created a proof of concept board game using YUI.” Check out the code and the game on his blog.
  • CSS Tip #1: Resetting Your Styles with CSS Reset: 6 Revisions, one of the most popular web-design blogs, has a detailed article out from Nov. 18 about the importance of CSS reset resources (like Nate Koechley’s YUI Reset CSS).  Writes Jacob Gube: “Resetting your styles, commonly referred to as CSS Reset or Reset CSS is the process of resetting (or more accurately - setting) the styles of all elements to a baseline value so that you avoid cross-browser differences due to their built-in default style settings. By resetting your styles, you avoid defaulting to the browser’s built-in styles, which differs from browser to browser.”
  • YUI Sightings — Tagz: Tagz is a new social-bookmarking site from India which, according to its authors, “also borrows voting and commenting from social news sites. Tagz was inspired by delicious and reddit.”  Major YUI usage can be found under the hood, including a dozen distinct components.
  • YUI Sightings — ConPA Financial Tool: ConPA is a nifty financial tool that is also a nice proof-of-concept of what you can do tying lots of YUI components together.  This tool, which helps you optimize your portfolio balance based on a set of stocks, leverages DataTable, Charts, AutoComplete and more than a dozen other YUI components.
  • YUI Wrapper for Yahoo Search Term Extraction API: Eric put together a simple 1KB script that, in combination with a server-side proxy, provides a JavaScript interface to the Yahoo! Search Term Extraction web service that pulls key terms out of any block of content.  Check out the blog post, the functional example, or the API docs for more details.
  • MiaCMS Updated with YUI 2.6.0 Support: Chad Auld and the Mia team recently released MiaCMS 4.8 with support for the latest version of YUI (2.6.0). (Original source.)
  • YUI Sightings — Interfete Web Club: The Interfete Web Club is a new site based on the e107 CMS that makes heavy use of YUI CSS and JavaScript. (Original source.)
  • YUI Sightings — IProtein: The iProtein site makes beautiful use of Todd Kloots’s Menu Buttons, among many other YUI components, in its new interface. (Original source.)
  • YUI Sightings — Footprints MySpace App: Navaneeth Krishnan’s Footprints is a collaborative geo-tagging application available on Myspace that makes use of YUI TabView and other controls in a Google Maps mashup. (Original source.)
  • YUI Sightings — Semmel, a YUI-based Interactive Community Engine: Semmels are community spaces that are easy for community members to manipulate and customize.  The richly interactive framework makes heavy use of YUI under the hood. (Original source.)
  • YUI Sightings — Viewies.com and DuckDuckGo.com Search Engines: Eric Powers contributed Viewies to the Yahoo! Gallery, combining YUI with the Yahoo Search APIs.  Writes Eric: “viewies.com is a Web Search Portal with Instant Search Views. [You can] nstantly view search results as full pages.”  This is a pretty cool take on one of the directions search interfaces can explore. A more traditional take on search is DuckDuckGo.com, a search engine that combines human edited results with search engine results in an attempt to improve the user interface. DuckDuckGo uses several YUI components, inlcuding Matt Mlinac’s YUI ImageLoader to improve performance. (Original source.)
  • YUI Sightings — RadCribs.com Real Estate Tours: RadCribs.com uses a variety of YUI components to provide in-page exploration of real-estate virtual tour information. (Original source.)

That’s a lot, but we’re sure we missed some great YUI implementations and discussions — please let us know what we missed in the comments.

Google Hosting YUI Files on ajax.googleapis.com

Thu, 2008-11-20 01:23

Update: It should be added that Google’s CDN provides SSL support whereas Yahoo’s does not. If you were previously hosting your own set of YUI files to use in a secure environment, the Google CDN may be a way to offload that bandwidth and improve performance.

Google has been hosting some of the popular AJAX libraries for awhile, and we’re pleased to announce that YUI has now been added to that roster. Now, you can choose between yui.yahooapis.com and ajax.googleapis.com when you evaluate your hosting options for YUI files. We’ve added Google as an option in the CDN section of the Dependency Configurator; it’s easy to configure your implementation and switch the generated URLs from one source to the other.

There are two things to keep in mind in working with the Google CDN, particularly if you’re currently using Yahoo’s CDN:

  1. Combo-handling: Combo-handling (the on-the-fly aggregation of files to reduce HTTP requests) is supported on Yahoo’s CDN but not on Google’s;
  2. Versions: Google’s CDN contains the current version of YUI (2.6.0) and will get future versions as they become available; legacy versions of YUI are not available from the Google CDN.

If you’re using YUI Loader to bring in your YUI files, it’s a simple thing to switch to Google’s servers using YUI Loader’s base configuration option. Here’s what you would do to pull the YUI DataTable and its dependencies from the Google CDN using YUI Loader:

<!--Include YUI Loader: --> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/yui/2.6.0/build/yuiloader/yuiloader-min.js"> </script> <!--Use YUI Loader to bring in your other dependencies: --> <script type="text/javascript"> // Instantiate and configure YUI Loader: (function() { var loader = new YAHOO.util.YUILoader({ base: "http://ajax.googleapis.com/ajax/libs/yui/2.6.0/build/", require: ["datatable"], onSuccess: function() { //instantiate your DataTable here... } }); // Load the files using the insert() method. loader.insert(); })(); </script>

The Dependency Configurator will generate this script for you; simply load this configuration and switch to the “Dynamic Loading with YUI Loader” tab.

Thanks to Vadim Spivak at Google and Dion Almaer (now at Mozilla) for helping to make this additional option available to the YUI developer community. We love that Google