We liked PPK’s solution and decided to answer his call and be, in his words, “…one of those frightfully clever JavaScript librar[ies to] use this technique…”. So for version 2.6 we’ve rolled PPK’s solution into two methods of the Event Utility: addFocusListener and addBlurListener (or onFocus and onBlur for short). These two new methods encapsulate the nitty gritty of supporting this technique in all our A-Grade browsers, while delivering the sugar you’ve come to expect from the addListener method of the Event Utility. The signatures of these new methods are as follows:
onFocus(el, fn, obj, override)
oBlur(el, fn, obj, override)
The arguments for both methods are as follows:
Here are several ways we’ve made use of the new onFocus and onBlur methods in YUI 2.6:
To support modality, a Dialog widget needs to direct focus back to itself when an element that is not one of its children receives focus. Previously this was accomplished by registering focus event listeners on every focusable element in the document when a modal Dialog was made visible, and removing those listeners when it has was hidden, a process that proved to be expensive and slow. Using PPK’s technique we’ve been able to boost the time it takes to initially display a modal Dialog by over 50% in most browsers, and boost the time it takes to hide a modal Dialog by over 90%. To test, we used a page with 250 focusable elements. Here is how the numbers break out for each browser:
| Browser | YUI 2.5.2 | YUI 2.6.0 | % Faster |
|---|---|---|---|
| FF 3 Mac OS 10.4 | 245 | 107 | 56 |
| FF 3 Win XP | 158 | 88 | 44 |
| FF 2 Mac OS 10.4 | 368 | 161 | 56 |
| FF 2 Win XP | 320 | 131 | 59 |
| Opera 9.5 Mac OS 10.4 | 103 | 93 | 10 |
| Opera 9.5 Win XP | 71 | 60 | 15 |
| IE 7 | 200 | 70 | 65 |
| IE 6 | 220 | 121 | 45 |
| Safari 3.1 | 53 | 18 | 66 |
| Browser | YUI 2.5.2 | YUI 2.6.0 | % Faster |
|---|---|---|---|
| FF 3 Mac OS 10.4 | 65 | 1 | 98 |
| FF 3 Win XP | 57 | 1 | 98 |
| FF 2 Mac OS 10.4 | 198 | 2 | 99 |
| FF 2 Win XP | 221 | 0 | 100 |
| Opera 9.5 Mac OS 10.4 | 531 | 1 | 100 |
| Opera 9.5 Win XP | 380 | 0 | 100 |
| IE 7 | 381 | 30 | 92 |
| IE 6 | 371 | 40 | 89 |
| Safari 3.1 | 48 | 1 | 98 |
In keeping with the WAI-ARIA Best Practices for Menus, the Menu widget uses the new onFocus method to listen for focus at the document level, so that when a popup Menu is hidden focus can be restored to the element in the DOM that had focus before it was made visible.
The new Carousel widget skins its next and previous buttons by wrapping each <input type="button"> elements in a <span>. The <input> elements are then positioned off screen and a background image is applied to each <span>. While this technique allows the next and previous buttons to remain accessible to users of screen readers, with the actual next and previous buttons hidden off screen, sighted users don’t receive any feedback from the UI when either button is focused. To fix this problem, Carousel uses the onFocus method to apply a class to the next and previous buttons that highlights focused buttons with an outline.
Of course, these are just a few places where we’ve used onFocus and onBlur — we think it will prove so useful in YUI and in YUI-based applications that we’ve added it to our Core, making it available to any application you build on top of YUI’s Event Utility.
If you’re in London, please join us for a YUI meetup on October 16 at 6:15 p.m. at the Yahoo! UK office on Shaftesbury Avenue.
Sophie Major and Christian Heilmann from the Yahoo Developer Network will be the hosts on the London side, and YUI engineers Matt Sweeney, Adam Moore and Satyen Desai will be participating by videoconference to give you a tour of (and progress report on) YUI’s upcoming 3.0 release.
Like meetups we had here in California last month, this event will be small and informal — it’s a good opportunity for us to get feedback from you on the 3.0 work, and likewise it’s a good chance for you to hear directly from some of the project’s principal developers. We hope to see you there.
After the YUI 3.x discussion via video conference, Christian and Sophie will be heading off to a local pub for more discussion and socializing.
]]>
Using the YUI ARIA Plugins is easy. Simply include the source file(s) for the ARIA plugin after the
widget source file(s) as indicated on the widget’s landing page. That’s it. Currently, the source
files for each plugin are available in the
YUI 2.6 package on SourceForge, and can
also be downloaded from the YUI blog
sandbox. In a future release of YUI, the plugins will be served from our CDN.
All YUI ARIA Plugins require the user’s browser and AT support the WAI-ARIA Roles and States.
Currently only Firefox 3 and
Internet Explorer
8 have support for ARIA and are supported by several screen readers for
Windows that also offer ARIA support. Opera also has support for ARIA as of version 9.5, but
unfortunately isn’t supported by any screen readers. For this reason the YUI ARIA Plugins are only
enabled by default for Firefox 3 and IE 8. To enable the ARIA plugin for other browsers, simply the set
the usearia configuration property to true. For example:
var oMenu = new YAHOO.widget.Menu("menu-1", { usearia: true });
Rather than integrate ARIA directly into a widget, we chose to deliver this functionality as a
plugin for two main reasons:
The following table illustrates which YUI widgets currently have an ARIA plugin, along with their
corresponding WAI-ARIA Roles.
| Widget | ARIA Role(s) |
|---|---|
| Button | checkbox, radio, radiogroup |
| Carousel | toolbar, button, listbox, option |
| Container | dialog, alertdialog, tooltip |
| Menu | menu, menubar, menuitem |
| TabView | tablist, tab, tabpanel |
We’d love the community to help us test these plugins, find bugs and suggest enhancements. As mentioned above, each plugin requires AT that supports ARIA. Two of the leading screen readers for Windows, JAWS and Window-Eyes, support ARIA. Free, trial versions of both are available for download, but require Windows be restarted every 40 minutes. For that reason, the open-source NVDA Screen Reader is the best option for developers looking to test the YUI ARIA Plugins as it is both free and provides excellent support for ARIA.
]]>2.6.0 introduces a new Carousel Control, offers the Paginator Control for general use (it was previously bundled with DataTable), includes more than 450 total fixes, enhancements and optimizations, graduates eight components out of “beta,” and now ships with more than 290 functional examples.
The YUI Carousel Control, contributed by Gopal Venkatesan (and based on the Carousel originally created by former Yahoo Bill Scott), provides a widget for browsing among a set of like objects arrayed vertically or horizontally in an overloaded page region. Like most YUI controls, Carousel can consume content from page markup using progressive enhancement techniques or be created, configured, and populated entirely via script. It has built-in support for the lazy-loading of content via XMLHttpRequest (aka Ajax) using YUI’s Connection Manager. And be sure to notice that Carousel’s ARIA Plugin example makes it easy to use the WAI-ARIA Roles and States with the Carousel control.

The YUI Paginator Control addresses the navigation aspect of chunked content, offering a set of controls that it can render into your UI to allow users to navigate through logical sections of local or remote data. It’s a great tool for managing page load times by reducing the amount of markup or data needed per page. In combination with Connection Manager or DataSource, paging through large sets of server side data is easy and can avoid the need for full page loads.
The simplicity of the getting started example risks hiding Paginator’s power, so be sure to explore the choices for configuring the Paginator. Plus, it’s built on a UI component architecture that allows implementers to easily create custom Paginator controls that will work automatically.
The Paginator Control was introduced with DataTable in version 2.5.0, but it has been broken out as an optional dependency for general use as of version 2.6.0.

You can view 2.6.0’s comprehensive change log of fixed bugs and concatenated release notes for the entire library, or keep reading for highlights.
Prolific YUI contributor (and YUI Community Awards winner) Satyam has given TreeView a significant overhaul with support for progressive enhancement, state retrieval, JSON-base construction, focus, keyboard navigation, and node editing. 2.6.0 should be fully backward-compatible with 2.5.2 and earlier implementations. More details in the upgrade notes for TreeView.
Thanks to Satyen Desai, the Calendar Control received significant accessibility improvements in 2.6.0 including the addition of text to the previous-month, next-month, and close icons for improved screen-reader interaction.
Dav Glass added the often requested Undo and Redo capabilities to the Rich Text Editor Control.
If you’ve struggled with making Drag & Drop work well over troublesome content such as iFrames, you’ll welcome the introduction of a hidden shim that now makes such traversals effortless.
Uploader has been updated to work with Flash Player 10, a sign of our continued commitment to emerging technologies. But because of security changes in the upcoming Flash Player 10, the UI for invoking the “Browse” dialog has to be contained within the Flash player. Because of that, this new version of the Uploader is NOT BACKWARDS COMPATIBLE with the code written to work with the previous version (it is, however, compatible with Flash Player 9). Do not upgrade to this version without carefully reading the documentation and reviewing the new examples.
There has been significant work on DataTable in this 2.6.0 release. (See the README for the full manifest.) Amongst the changes, DataTable introduces the ScrollingDataTable and CellEditor classes, the Paginator widget is now offered as a standalone component, and significant changes have been applied to DataTable’s pagination and sorting architectures. While backward compatibility has been maintained whenever possible, the Paginator widget is now an optional dependency, and custom extensions to inline cell editing or server-side pagination and/or sorting will likely need to be updated to be compatible with the new models. Implementers who are upgrading from an earlier version are strongly advised to read the Upgrades Notes.
As of the 2.6.0 release, AutoComplete has been migrated to use YAHOO.util.DataSource, which is now a new required dependency. The YAHOO.widget.DataSource class, which used to be packaged with the AutoComplete control has been removed. While backward compatibility has been maintained whenever possible, implementers who are upgrading from an earlier version are strongly advised to read the Upgrades Notes to smooth the transition.
The Container family of controls have enhanced positioning, height, and modality support in 2.6.0 via new preventcontextoverlap, context, and autofillheight configuration properties.
Concurrent with the initial YUI release in February 2006, Yahoo! released the Yahoo! Design Patterns Library. Design Patterns describe an optimal solution to a common problem within a specific context. Today we’re happy to strengthen the relationship between these two sibling libraries by offering YUI code for two existing patterns: The Pagination Design Pattern and the Carousel Design Pattern.
We’ve continued to work hard to make YUI accessible. The Carousel, Button, Menu, TabView, and Container all have enhanced accessibility support in addition to what’s otherwise noted in this blog post. We continue to count accessibility amongst our highest priorities; stay tuned for a few more blog posts on the topic in the coming days and weeks.
The following seven YUI components have graduated from beta as of 2.6.0:
removeSub() method and two parsing improvements.useShim config and a series of bug fixes.(Note that the ProfileViewer developer tools, the Element and Selector utilities, and the Carousel and ImageCropper controls remain designated as beta.)
We’re proud of this 2.6.0 release and want to thank the entire community for their contributions, guidance, and continued support. We hope you enjoy all the new power and easy of use reflected in 2.6.0, and we look forward to your feedback in the comments below and on the YUI mailing list.
Thank you again on behalf of the entire development team, Adam Moore, Dav Glass, Eric Miraglia, George Puckett, Jenny Han Donnelly, Luke Smith, Matt Sweeney, Satyen Desai, Thomas Sha, and Todd Kloots; and contributors: Caridy Patiño, Dwight “Tripp” Bridges, Julien Lecomte, Matt Mlinac, Allen Rabinovich, Satyam, Gopal Venkatesan, and Nicholas C. Zakas
]]>This is why I thought of writing a small script that can be used as a bookmarklet to cover the screen with a dark overlay and only shows a few lines at a time. That way you can concentrate on the bit you are reading at the moment and the rest of the screen does not bother you too much.
Following are two screenshots of the same site with and without reading blinds:


So how to build that?
The task of building a tool like that is actually pretty easy:
Then I thought that I should be able to move the highlight on the page. For this I needed a bit more sophistication:
I could have had a go at it myself, but I don’t want to end in browser inconsistency hell, hence I use YUI.
Here’s the code:
var readingblinds = function(){
var visible = true;
var y,top,bottom;
var info = true;
var size = 70;
function generate(){
top = document.createElement('div');
bottom = document.createElement('div');
document.body.appendChild(top);
document.body.appendChild(bottom);
styleTopBottom();
var message = document.createElement('div');
var note = document.createTextNode(
'Reading Blinds - ' +
'move mouse to highlight section to read. '
);
message.appendChild(note);
top.appendChild(message);
styleMessage(message);
YAHOO.util.Event.on(document, "mousemove", move);
};
function move(e){
y = YAHOO.util.Event.getXY(e);
if(y[1] > size){
render(y);
}
};
function render(y){
var real = y[1]-YAHOO.util.Dom.getDocumentScrollTop();
YAHOO.util.Dom.setStyle(top,'height',real-size+'px');
var h = YAHOO.util.Dom.getViewportHeight()-real+size;
YAHOO.util.Dom.setStyle(bottom,'top',real+size+'px');
YAHOO.util.Dom.setStyle(bottom,'height',h + 'px');
};
function styleMessage(message){
YAHOO.util.Dom.setStyle(message,'font-size','80%');
YAHOO.util.Dom.setStyle(message,'text-align','right');
YAHOO.util.Dom.setStyle(message,'padding','5px');
YAHOO.util.Dom.setStyle(message,'font-family','verdana,sans-serif');
YAHOO.util.Dom.setStyle(message,'color','white');
}
function styleTopBottom(){
YAHOO.util.Dom.batch([top,bottom],function(o){
YAHOO.util.Dom.setStyle(o,'background','#000');
YAHOO.util.Dom.setStyle(o,'width','100%');
YAHOO.util.Dom.setStyle(o,'position','fixed');
YAHOO.util.Dom.setStyle(o,'left','0');
YAHOO.util.Dom.setStyle(o,'height','10%');
YAHOO.util.Dom.setStyle(o,'opacity','.85');
YAHOO.util.Dom.setStyle(o,'overflow','hidden');
});
YAHOO.util.Dom.setStyle(top,'top','0');
YAHOO.util.Dom.setStyle(bottom,'bottom',0);
YAHOO.util.Dom.setStyle(bottom,'height','70%');
};
return{
init:generate
}
}();
readingblinds.init();
The interesting methods are move() and render(); the rest is more or less run-of-the-mill DOM scripting.
The move() method is an event handler that gets called by any mousemove event on the document. YUI’s Dom Collection then makes it easy for me to get the current mouse cursor position with getXY() and I just need to make sure that the mouse is low enough in the browser window to not cause a negative height on the top div.
The render() method then sets the appropriate heights. I determine the upper border of the browser with getDocumentScrollTop() and substract that one from the cursor position. To determine where to end the bottom div I use getViewPortHeight().
This was cool enough, but I wanted to be able to turn the blinds on and off and change the size of the visible part with the keyboard, too. For this, I needed to use the keylistener utility some tool methods to resize the gap or show and hide both of the cover divs. The resizing methods needed to get some boundaries to avoid div overlap or the whole viewport to be uncovered.
var readingblinds = function(){
var visible = true;
var y,top,bottom;
var info = true;
var size = 70;
function generate(){
top = document.createElement('div');
bottom = document.createElement('div');
document.body.appendChild(top);
document.body.appendChild(bottom);
styleTopBottom();
var message = document.createElement('div');
var note = document.createTextNode(
'Reading Blinds - ' +
'move mouse to highlight section to read. ' +
'Press "b" to show and hide, "s" to decrease size,' +
' "l" to increase size'
);
message.appendChild(note);
top.appendChild(message);
styleMessage(message);
var keyspy = new YAHOO.util.KeyListener(
document,
{ keys:66 },
{ fn:peekaboo }
);
keyspy.enable();
var keyspy2 = new YAHOO.util.KeyListener(
document,
{ keys:83 },
{ fn:smaller }
);
keyspy2.enable();
var keyspy3 = new YAHOO.util.KeyListener(
document,
{ keys:76 },
{ fn:larger }
);
keyspy3.enable();
YAHOO.util.Event.on(document, "mousemove", move);
};
function move(e){
y = YAHOO.util.Event.getXY(e);
if(y[1] > size){
render(y);
}
};
function render(y){
var real = y[1]-YAHOO.util.Dom.getDocumentScrollTop();
YAHOO.util.Dom.setStyle(top,'height',real-size+'px');
YAHOO.util.Dom.setStyle(bottom,'top',real+size+'px');
var h = YAHOO.util.Dom.getViewportHeight()-real+size;
YAHOO.util.Dom.setStyle(bottom,'height',h + 'px');
};
function styleMessage(message){
YAHOO.util.Dom.setStyle(message,'font-size','80%');
YAHOO.util.Dom.setStyle(message,'text-align','right');
YAHOO.util.Dom.setStyle(message,'padding','5px');
YAHOO.util.Dom.setStyle(message,'font-family','verdana,sans-serif');
YAHOO.util.Dom.setStyle(message,'color','white');
}
function styleTopBottom(){
YAHOO.util.Dom.batch([top,bottom],function(o){
YAHOO.util.Dom.setStyle(o,'background','#000');
YAHOO.util.Dom.setStyle(o,'width','100%');
YAHOO.util.Dom.setStyle(o,'position','fixed');
YAHOO.util.Dom.setStyle(o,'left','0');
YAHOO.util.Dom.setStyle(o,'height','10%');
YAHOO.util.Dom.setStyle(o,'opacity','.85');
YAHOO.util.Dom.setStyle(o,'overflow','hidden');
});
YAHOO.util.Dom.setStyle(top,'top','0');
YAHOO.util.Dom.setStyle(bottom,'bottom',0);
YAHOO.util.Dom.setStyle(bottom,'height','70%');
};
function peekaboo(){
if(visible === true){
YAHOO.util.Dom.setStyle(top,'display','none');
YAHOO.util.Dom.setStyle(bottom,'display','none');
visible = false;
} else {
YAHOO.util.Dom.setStyle(top,'display','block');
YAHOO.util.Dom.setStyle(bottom,'display','block');
visible = true;
}
};
function smaller(){
if(size > 10){
size -= 5;
render(y);
}
};
function larger(){
if(size < YAHOO.util.Dom.getViewportHeight()/2){
size += 5;
render(y);
}
};
return{
init:generate
}
}();
readingblinds.init();
That was pretty cool already, but as I wanted to make reading blinds a single script include or bookmarklet I had the problem of relying on the YUI. Well, there is a trick to conjure YUI from thin air by using the YAHOO_config object with the listener method creating a script node to get the YUI Loader.
So instead of calling readingblinds.init() directly, I used the following magic YUI trick:
if(typeof YAHOO=="undefined"||!YAHOO){
YAHOO_config = function(){
var s = document.createElement('script');
s.setAttribute('type','text/javascript');
s.setAttribute('src','http://yui.yahooapis.com/2.5.2/'+
'build/yuiloader/yuiloader-beta-min.js');
document.getElementsByTagName('head')[0].appendChild(s);
return{
listener:function(o){
if(o.name === 'get'){
window.setTimeout(YAHOO_config.ready,1);
}
},
ready:function(){
var loader = new YAHOO.util.YUILoader();
var dependencies = ['yahoo','dom','event'];
loader.require(dependencies);
loader.loadOptional = true;
loader.insert({
onSuccess:function(){
readingblinds.init();
}
});
}
};
}();
} else {
readingblinds.init();
}
That’s the lot. You can download readingblinds.js
and include it in your site, or you can drag the following link to your links toolbar: Reading Blinds.
Stoyan Stefanov is a member of Yahoo’s Exceptional Performance team; he’s worked on a variety of performance-related projects at Yahoo, including the popular YSlow plugin for Firebug. He’s also a contributing author here on YUIBlog.
Stoyan’s latest project is Object Oriented JavaScript, a new book from Packt whose simple goal is to help you learn how to “think in JavaScript.” Stoyan and his editors were kind enough to let us share with you Chapter 8 from OOJS — “Coding and Design Patterns.”
Among the coding patterns explored in this chapter:
Design patterns include:
The sample chapter is an excellent standalone resource, but the full volume is outstanding as well. Our thanks to Stoyan and his editors for allowing us to freely share the coding and design patterns content here.
]]>
If you can’t make it to the YUI meetup tonight but you do want to drop in and see what’s going on, we’ll be broadcasting the event on the experimental Yahoo! Live service:
Live is a relatively recent product out of Yahoo’s Brickhouse development incubator. We haven’t used it for this purpose before, but since we’ll be up at Brickhouse for tomorrow night’s meetup we thought we’d highlight some of that group’s fantastic work.
Hope to see you online or in person tonight!
Note: The Live channel will not be broadcasting all day — just from about 7:15 p.m. through the end of the code demos. Drop in after 7:15 p.m. PDT tonight and, barring any technical challenges, you should find us there.
]]>
Kris Cieslak is back, after a long break, with a new YUI-based game: Pacman. We last heard from Kris about 18 months ago, when he was showing off Yetris, Puzzle and Solitaire. Now Kris returns with another classic game built entirely in JavaScript, bolstered by YUI 2.5.2’s core (Yahoo, Dom and Event). Check it out and give Kris feedback on his blog.
]]>
Ryan Grove is a web developer and part-time getaway driver (the former for Yahoo! Search and the latter for pretend). During the day he works primarily on Search Assist, iPhone Search, frontend architecture improvements, and performance; at night he writes open source software and occasionally sleeps.
When we set out to build an iPhone-optimized version of Yahoo! Search, we wanted to bring SearchMonkey, 
Search Assist, and other JavaScript-heavy Yahoo! Search features to the iPhone, but we also wanted the site to be blazing fast even over EDGE, all while reusing as much existing code as possible in order to minimize engineering effort and make maintenance easier. This is how we did it.
Our first task was to remove code that wasn’t strictly necessary for the iPhone experience. We were able to eliminate a significant portion of the Search Assist code, and we shaved off even more bytes by rewriting the remainder in an iPhone-specific way rather than the generic, framework-like style of the original code.
Some examples of the kinds of things an iPhone-specific site doesn’t need:
mousemove and mouseover events just before the mousedown, mouseup, and click events, and it fires the mouseout event when an element loses focus.contextmenu event cannot be triggered.Rewriting this code instead of reusing the existing code was a tradeoff since it meant we would need to spend more time maintaining it in the future, but the performance gains were worth it: we brought the minified JavaScript weight of the iPhone Search Assist implementation down from 32KB to 2KB (before gzip). Execution speed was also greatly improved by eliminating animations and simplifying the code that requests search suggestions on each keystroke.
After cutting out the unnecessary code, the next step was to make our remaining code as small as possible. The YUI Compressor made this easy, and we were able to save additional bytes by refactoring our code to follow the advice given in Nicholas Zakas’s article Helping the YUI Compressor, which describes several things you can do to help the YUI Compressor generate even more compact code.
Consider the following example (for the sake of brevity, I’ve replaced code that doesn’t pertain to this example with placeholder comments):
YAHOO.namespace('Search');
YAHOO.Search.iPhone = function () {
// ... private methods ...
return {
// ... public methods ...
toggle: function (el) {
if (YAHOO.util.Dom.hasClass(el, 'hidden')) {
YAHOO.util.Dom.removeClass(el, 'hidden');
} else {
YAHOO.util.Dom.addClass(el, 'hidden');
}
}
};
}();
The YUI Compressor will compress the original 359 bytes to 209 bytes:
YAHOO.namespace("Search");YAHOO.Search.iPhone=function(){return{
toggle:function(A){if(YAHOO.util.Dom.hasClass(A,"hidden")){
YAHOO.util.Dom.removeClass(A,"hidden")}else{YAHOO.util.Dom.addClass(A,
"hidden")}}}}();
We can compress this code even further by replacing the repeated reference to YAHOO.util.Dom with a local variable and by using the more compact ternary operator rather than an if statement:
YAHOO.namespace('Search');
YAHOO.Search.iPhone = function () {
var YUD = YAHOO.util.Dom;
// ... private methods ...
return {
// ... public methods ...
toggle: function (el) {
var className = 'hidden';
YUD[YUD.hasClass(el, className) ? 'removeClass' : 'addClass'](el,
className);
}
};
}();
This will compress to a mere 173 bytes:
YAHOO.namespace("Search");YAHOO.Search.iPhone=function(){
var A=YAHOO.util.Dom;return{toggle:function(C){var B="hidden";
A[A.hasClass(C,B)?"removeClass":"addClass"](C,B)}}}();
Optimizations like this are particularly important due to Mobile Safari’s cache limitations, which we’ll discuss a little later.
Search Assist was the only JavaScript component that we rewrote for iPhone Search; everything else was reused wholesale with no modifications. Two things made this possible:
One of the most important factors to consider when reusing existing code is that the iPhone’s processor is much slower than desktop processors; as a result, JavaScript execution can be tens or even hundreds of times slower. It’s a good idea to avoid complex animation, heavy DOM manipulation, and other CPU-intensive operations.
If necessary, refactor your existing code to allow animations to be turned off, use event delegation whenever possible to minimize your DOM event overhead, and always be sure to provide a tag name and root element to YUI Dom Utility methods like getElementsByClassName. You’ll see performance improvements in desktop browsers as well as Mobile Safari.
In the months after the iPhone was launched, the Yahoo! Exceptional Performance Team (and others outside of Yahoo!) discovered that Mobile Safari doesn’t cache components larger than 25KB pre-gzip. This presents a bit of a problem for iPhone web apps using YUI since the core YUI components (YAHOO Global Object, Dom Collection, and Event Utility) weigh in at a combined size of just over 30KB. We wanted to minimize the number of HTTP requests we made, especially via EDGE, but we also wanted to ensure that our components were cached so the browser wouldn’t need to download them on every pageview.
The solution was a tradeoff: We split our components into cache-friendly chunks of less than 25KB. This results in a few additional HTTP requests the first time the user visits the site, but it ensures that the components are cached and don’t need to be re-downloaded for future pageviews.
The easiest way to do this is to use the YUI Dependency Configurator, which will automatically create ComboHandler URLs for the components you select. For example, if your iPhone web app requires YAHOO, Dom, Event, and the JSON Utility, you can break these dependencies up into two requests, each smaller than 25KB:
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.5.2/build/yahoo/yahoo-min.js&2.5.2/build/dom/dom-min.js"></script> <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.5.2/build/event/event-min.js&2.5.2/build/json/json-min.js"></script>
One catch: the YUI Configurator will try to include yahoo-min.js in each generated URL since all YUI libraries depend on it. There’s no need to load this file twice, so be sure to manually remove it from all but the first URL you generate.
Thanks to Mobile Safari’s awesomeness, YUI’s abstraction of browser compatibility issues, YUI Compressor’s excellent minification routines, and ComboHandler’s ability to aggregate multiple components into cache-friendly chunks, it only took us two weeks to build Yahoo! Search for iPhone. The end result is snappy even on slow EDGE network connections.
]]>
As some of you may recall, Yahoo held a big Open Hack Day back in September, 2006, at which many entertaining things happened, including Beck playing a concert for assembled hackers on the Yahoo lawn. It’s been too long, but we’re doing it again on September 12 and 13. And, of course, you’re invited.
The focus of Open Hack is to get together with other hackers and build cool stuff, show off the fruits of your labor, and win fun and fabulous prizes. But the Friday developer-day sessions also provide a chance for us to share with you work we’ve been doing at Yahoo that may be of use in your own projects and hacks. Although we haven’t announced the full Friday schedule yet, I do want to let you know that there will be at least two YUI-focused sessions:
Other developer-day content that might be of particular interest to YUIBlog readers:
All times are provisional at this point, but reserve your spot on HackDay.org, check out the teaser below, and we’ll look forward to seeing you here at Yahoo in a few weeks.
]]>