Home > Development > features
The promise of JavaScript/CSS libraries like the free, BSD-licensed Yahoo! User Interface (YUI) Library is that they make it easier to create rich interfaces in the browser. In this article, we'll explore the creation of a simple web app using YUI and look closely at the YUI paradigm.
Getting Started
YUI consists of several CSS components and nearly three dozen JavaScript components, all of which are designed to empower the rapid creation of web applications that run in all the major web browsers. Yahoo! uses a Graded Browser Support approach in which we "white-list" a subset of browsers that we'll fully support — we call these the "A-Grade browsers," and, taken together, they represent more than 90% of traffic on Yahoo!'s network worldwide. YUI is tested and supported in all A-Grade browsers (including current versions of Safari, Opera, Firefox and Internet Explorer).
The best way to think about YUI and what it does for you is to consider the difference between the user interface language of the browser as compared with the desktop. In the browser, the "default" language is relatively limited. You have form elements (buttons, select menus, text inputs) and hyperlinks. On the desktop, you expect much more: Tabs, sliders, cascading menus, dialogs, tooltips, data grids, rich text editing, drag and drop, animation, autocompletion, and so on. Here's one way to visualize this difference, with the browser's native UI elements on the left and the richer set of desktop-style UI elements on the right:
In the browser, everything on the right side of this diagram requires some hard work. YUI, like other JavaScript/CSS libraries, aims to make that work less hard.
Getting to Know YUI
The best way to get to know YUI is to take a quick tour of the YUI website at http://developer.yahoo.com/yui/. You'll find that YUI contains four CSS components, a light JavaScript core engine (containing powerhouse elements like DOM normalization and an event system), JavaScript utilities (components like Drag & Drop that enable you to build rich interactions), widgets (fully-encapsulated user interactions like a Calendar date-picker), and developer tools.
CSS Components
JavaScript Core
Utilities
For each YUI component, you'll find on the website the following resources to help you get started:
User's Guide: Every YUI building block is fully documented with a User's Guide that steps through the most basic use cases. These documents also provide information about common configuration options, component-level events, customization strategies, and UI styling/skinning.
Cheat Sheets are printable one-page documents that summarize a component's API, configuration options, and common use cases. You can download the full cheat sheet packet from the YUI website — it makes for a useful desk reference as you work through YUI-based projects.
API Documentation: YUI's full, searchable API is available for review, including method, property, event, and source references.
Examples: Every YUI component ships with a full complement of examples covering common use cases.
Building Your First Application
The best way to get the feel for YUI is to build a sample application — so let's get started. In our sample application, we'll use the YUI AutoComplete Control powered by the Yahoo! Search web service to supercharge a standard site-search form. As a user types a search on our site (or sites), AutoComplete will query Yahoo! Search for possible results; when it finds pages that match the query, it will open a suggestion container with a menu of results for the user to choose from. This is equivalent to having the first page of search results come back on-the-fly. The user doesn't have to navigate to the results page; s/he doesn't even need to finish typing in the search terms, in some cases.
Once the container is open, the user can click on a result or arrow to a result using the keyboard; in the latter case, the enter key sends the user to the selected page.
Here's a screenshot of the app in its finished state:
Here are our requirements and the YUI components we need to meet those requirements:
Armed with this knowledge about our dependencies, we can go to the YUI Configurator on the YUI website and let it determine the full list of YUI files we'll need for our implementation.
Take the output of the Configurator and put the stylesheet and script information in the element of your document. Now we're ready to start writing our application.
Setting Up the Markup
The markup for our application is simple: We need a form, a text input, and a submit button for the basic form, and we need an element to serve as the suggestion container to be populated by AutoComplete. We'll add some Yahoo! Search-specific hidden fields to our form to ensure that, if submitted, results will only be returned for the sites we've selected:
Adding AutoComplete to Your Search Form
From the functioning markup base, we can begin implementing the YUI components that we added to the head of the page. In any AutoComplete implemenation, we begin by creating a DataSource — effectively, establishing the pool of "suggestions" that AutoComplete can choose from in populating its suggestion container. You can read about the various kinds of AutoComplete DataSources on the AutoComplete User's Guide — they include basic JavaScript arrays, custom JavaScript functions, and XMLHttpRequest-based services, and script-node sources. (If you're playing around with this code, you may also want to print out a copy of the AutoComplete Cheat Sheet.) In this application, we'll use the script node solution which allows us to access cross-domain data from Yahoo! Search without using a server-side proxy. (Security note: You should never access cross-domain JavaScript from untrusted sources. In this case, we're trusting the Yahoo! Search webservice not to return a malicious script.)
Here's our code to set up the DataSource:
The schema array is important; these fields map to fields passed in by the JSON web service we are using, and we'll reference these when we format the results for our suggestion container in a moment. Note that Yahoo! Search gives us a literal URL for the result page and a "click URL". The click URL is the URL we should send users through to reach a search result, as it aids Yahoo! Search in evaluating the quality of results and in sorting results more intelligently for future searches.
With our DataSource in place, we can set up our AutoComplete instance. We need to pass four arguments to AutoComplete's constructor:
Here's the annotated code for setting up the AutoComplete instance with some rational configurations applied for this kind of application:
None of these settings are sacred; feel free to play around with different configurations.
Next up, we need to format the results that AutoComplete puts in our suggestion container; we do that in our instance's formatResult function which is called for each result item. Nothing fancy in the markup...we'll simply use tags to specify page titles.
In the code above,
The function we just wrote populates the suggestion container. When a user selects an item from this container, the itemSelectEvent is fired. That's our cue to take the user to the page they selected from the search results. Let's subscribe to the itemSelectEvent and use that event to trigger navigation to the selected page:
We've snuck in a little hack here for Opera, which does not honor
One more bit of business remains before we test out our application. AutoComplete, true to its name, wants to automatically complete the text being typed in the input field when an item is selected in the suggestion container. We don't want that here. Rather, we want the input field to remain untouched while item selection takes us to the designated page. To accomplish this, we're going to customize our AutoComplete instance by overriding one of its core methods:
At this point, we've looked at:
Although each YUI component has its own set of configurations and events, you'll find that this set of implementation concerns is consistent throughout the library. Use the User's Guides, API docs, and Cheat Sheets to identify the patterns used by each component.
We're using elements of YUI's default "skin", so we will apply the controlling class name for invoking that skin (
As with most applications, there are some final touches to be made in our code to get our implementation in line with the comp we looked at earlier in this article. Here are the requisite changes to add in the footer and to correctly position the suggestion container:
With that code in place, our implementation is complete. You can check out the working example in the file
Summary
YUI is a comprehensive frontend toolkit — we've just looked at a tiny subset of its functionality here. But don't be daunted by YUI's comprehensiveness. It is, at heart, a straightforward framework on top of which you can build robust, scalable web applications that work across all the A-Grade browsers.
As you begin developing with YUI, you should consider joining the YUI community forum and subscribing to YUIBlog. In the community forum, you'll be joined by nearly 10,000 felow YUI users, many of whom have developed (and generously share) a deep expertise in specific aspects of the library. On the blog, you'll find articles and videos from the core YUI engineering team and links out to YUI resources in the community at large.
Getting Started
YUI consists of several CSS components and nearly three dozen JavaScript components, all of which are designed to empower the rapid creation of web applications that run in all the major web browsers. Yahoo! uses a Graded Browser Support approach in which we "white-list" a subset of browsers that we'll fully support — we call these the "A-Grade browsers," and, taken together, they represent more than 90% of traffic on Yahoo!'s network worldwide. YUI is tested and supported in all A-Grade browsers (including current versions of Safari, Opera, Firefox and Internet Explorer).
The best way to think about YUI and what it does for you is to consider the difference between the user interface language of the browser as compared with the desktop. In the browser, the "default" language is relatively limited. You have form elements (buttons, select menus, text inputs) and hyperlinks. On the desktop, you expect much more: Tabs, sliders, cascading menus, dialogs, tooltips, data grids, rich text editing, drag and drop, animation, autocompletion, and so on. Here's one way to visualize this difference, with the browser's native UI elements on the left and the richer set of desktop-style UI elements on the right:
In the browser, everything on the right side of this diagram requires some hard work. YUI, like other JavaScript/CSS libraries, aims to make that work less hard.
Getting to Know YUI
The best way to get to know YUI is to take a quick tour of the YUI website at http://developer.yahoo.com/yui/. You'll find that YUI contains four CSS components, a light JavaScript core engine (containing powerhouse elements like DOM normalization and an event system), JavaScript utilities (components like Drag & Drop that enable you to build rich interactions), widgets (fully-encapsulated user interactions like a Calendar date-picker), and developer tools.
CSS Components
JavaScript Core
Utilities
- Animation Utility
- Browser History Manager
- Connection Manager
- Cookie Utility
- DataSource Utility
- Drag and Drop Utility
- Element Utility
- Get Utility
- ImageLoader Utility
- JSON Utility
- Resize Utility
- Selector Utility
- The YUI Loader Utility
- AutoComplete
- Button
- Calendar
- Charts
- Color Picker
- Container
- DataTable
- ImageCropper
- Layout Manager
- Menu
- Rich Text Editor
- Slider
- TabView
- TreeView
- Uploader
For each YUI component, you'll find on the website the following resources to help you get started:
User's Guide: Every YUI building block is fully documented with a User's Guide that steps through the most basic use cases. These documents also provide information about common configuration options, component-level events, customization strategies, and UI styling/skinning.
Cheat Sheets are printable one-page documents that summarize a component's API, configuration options, and common use cases. You can download the full cheat sheet packet from the YUI website — it makes for a useful desk reference as you work through YUI-based projects.
API Documentation: YUI's full, searchable API is available for review, including method, property, event, and source references.
Examples: Every YUI component ships with a full complement of examples covering common use cases.
Building Your First Application
The best way to get the feel for YUI is to build a sample application — so let's get started. In our sample application, we'll use the YUI AutoComplete Control powered by the Yahoo! Search web service to supercharge a standard site-search form. As a user types a search on our site (or sites), AutoComplete will query Yahoo! Search for possible results; when it finds pages that match the query, it will open a suggestion container with a menu of results for the user to choose from. This is equivalent to having the first page of search results come back on-the-fly. The user doesn't have to navigate to the results page; s/he doesn't even need to finish typing in the search terms, in some cases.
Once the container is open, the user can click on a result or arrow to a result using the keyboard; in the latter case, the enter key sends the user to the selected page.
Here's a screenshot of the app in its finished state:
Here are our requirements and the YUI components we need to meet those requirements:
- The search control should work without JavaScript, taking the user to the standard Yahoo! Search results page.
- The search suggestion container should have full arrow-key and mouse support; the YUI AutoComplete Control provides this functionality.
- The suggestion container should be animated; AutoComplete has intrinsic support for this if we include YUI's Animation Utility.
- We want to avoid using as server-side proxy (as would be required in traditional XHR/Ajax-style applications). Instead, we'll use a JSON-based webservice from Yahoo! Search and leverage YUI's Get Utility for this proxyless solution. AutoComplete implements the Get Utility for its proxyless, script-node based DataSource, so we'll make use of that.
Armed with this knowledge about our dependencies, we can go to the YUI Configurator on the YUI website and let it determine the full list of YUI files we'll need for our implementation.
Take the output of the Configurator and put the stylesheet and script information in the element of your document. Now we're ready to start writing our application.
Setting Up the Markup
The markup for our application is simple: We need a form, a text input, and a submit button for the basic form, and we need an element to serve as the suggestion container to be populated by AutoComplete. We'll add some Yahoo! Search-specific hidden fields to our form to ensure that, if submitted, results will only be returned for the sites we've selected:
You can test out the markup portion of the application in the file
1-markup.html. The expected behavior is that submitting the form takes you to Yahoo! Search, where the two designated sites are searched for results. In this article, we're using the two sites dedicated to YUI (developer.yahoo.com/yui and yuiblog.com). You can easily change this setting to specify one or more sites relevant to your own work; just keep in mind that the sites must be open to Yahoo! Search indexing.Adding AutoComplete to Your Search Form
From the functioning markup base, we can begin implementing the YUI components that we added to the head of the page. In any AutoComplete implemenation, we begin by creating a DataSource — effectively, establishing the pool of "suggestions" that AutoComplete can choose from in populating its suggestion container. You can read about the various kinds of AutoComplete DataSources on the AutoComplete User's Guide — they include basic JavaScript arrays, custom JavaScript functions, and XMLHttpRequest-based services, and script-node sources. (If you're playing around with this code, you may also want to print out a copy of the AutoComplete Cheat Sheet.) In this application, we'll use the script node solution which allows us to access cross-domain data from Yahoo! Search without using a server-side proxy. (Security note: You should never access cross-domain JavaScript from untrusted sources. In this case, we're trusting the Yahoo! Search webservice not to return a malicious script.)
Here's our code to set up the DataSource:
/* First, we'll create our DataSource, using the Script
Node DataSource constructor. We pass in the base URL
and the schema that we'll use to map the returned
data. */
this.oDataSource = new YAHOO.widget.DS_ScriptNode("http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&output=json&site=developer.yahoo.com&site=yuiblog.com®ion=us", ["ResultSet.Result","Title","Url","ClickUrl"]);
With our DataSource in place, we can set up our AutoComplete instance. We need to pass four arguments to AutoComplete's constructor:
- The ID of the text input element (
searchinput); - the ID of the suggestion container element (
searchcontainer); - the DataSource instance (created above;
oDataSource); - and any configurations we want to make on our AutoComplete instance for things like animation (which we'll pass in as an object literal; a list of configuration options can be found in the AutoComplete API documentation).
Here's the annotated code for setting up the AutoComplete instance with some rational configurations applied for this kind of application:
/* With all of the pieces in hand, we can now instantiate
and configure our AutoComplete instance: */
this.oAutoComp = new YAHOO.widget.AutoComplete(
"searchinput", // the input field's ID
"searchcontainer", // the suggestion container's ID
this.oDataSource, // the DataSource
{ // here, we begin our configuration options:
autoHighlight: false, //We don't want the first
//result highlighted by default.
animVert: true, //Yes, animate the suggestion
//container...
animHoriz: false, //but only vertically, not
//horizontally.
animSpeed: 0.3, //The animation should last
//0.3 seconds.
minQueryLength: 4, //Don't search for results until
//the user has entered at least
//4 characters in the input field.
useShadow: true, //Build in a drop-shadow.
prehighlightClassName: "yui-ac-prehighlight"
//Use a different highlight style
//for mouse-over than for arrow-to.
});
Next up, we need to format the results that AutoComplete puts in our suggestion container; we do that in our instance's formatResult function which is called for each result item. Nothing fancy in the markup...we'll simply use tags to specify page titles.
/* Formatting your result is the key to having a customized
look-and-feel for your AutoComplete implementation. Here,
we do a very simple markup for the result title and the
URL for the result. */
this.oAutoComp.formatResult = function(oResultItem, sQuery) {
return "<em>" + oResultItem[0] + "</em><br />" + oResultItem[1];
};
oResultItem passed to formatResult is comprised of the fields we specified in our DataSource schema: Title, Url, and ClickUrl.The function we just wrote populates the suggestion container. When a user selects an item from this container, the itemSelectEvent is fired. That's our cue to take the user to the page they selected from the search results. Let's subscribe to the itemSelectEvent and use that event to trigger navigation to the selected page:
/* What do we want to do when an item in the suggestion container
is selected (either by arrowing and hitting enter or by clicking)?
We'll subscribe to the itemSelectEvent and when it fires use its
arguments to set a new location for the current page. */
this.oAutoComp.itemSelectEvent.subscribe(function(type, args) {
/* this line works around Opera's preventDefault
bug: */
YAHOO.util.Dom.get("searchsubmit").disabled = true;
/* now, we go off to the destination page chosen by
the user from the AutoComplete suggestion list: */
location.href = (args[2][2]);
});
preventDefault in all cases; by disabling the submit button on our form when an item is selected, we can work around that bug while still allowing the form to submit normally when no item is selected via AutoComplete.One more bit of business remains before we test out our application. AutoComplete, true to its name, wants to automatically complete the text being typed in the input field when an item is selected in the suggestion container. We don't want that here. Rather, we want the input field to remain untouched while item selection takes us to the designated page. To accomplish this, we're going to customize our AutoComplete instance by overriding one of its core methods:
/* Here we'll hack AutoComplete a little bit. AutoComplete is
designed to put the selected item's primary value in the
input field. In this case, that would be the result's Title
field. We don't really want that -- we're using AutoComplete
not to do type-ahead but to map to instant results. So, we'll
suppress the standard behavior by overriding a private method
on this specific AutoComplete instance: */
this.oAutoComp._updateValue = function() {
return true;
}
- How to configure a YUI implementation and put YUI on the page;
- How to set up the markup for a progressively-enhanced YUI widget;
- How to instantiate and configure a YUI widget;
- How to subscribe to and make use of the "custom events" provided by a YUI widget;
- And how to override default behavior to get a bespoke implementation that maps to our requirements.
Although each YUI component has its own set of configurations and events, you'll find that this set of implementation concerns is consistent throughout the library. Use the User's Guides, API docs, and Cheat Sheets to identify the patterns used by each component.
With this code in place, our implementation is functional (though not as pretty as we want just yet, and not quite complete). We can look at this partial code milestone in 2-partial.html. Don't worry about how it looks yet — just note that it's functional and ready for some finishing touches.
Finishing Touches
To get the final look-and-feel from our requirements document, we need to add some CSS styling. We're going to center the search control in the middle of its host element; Jenny Han Donnelly, AutoComplete's author, has a nice tutorial on the CSS and JS customizations required for this purpose.
Here's the CSS portion:
<style type="text/css">
#sitesearch {text-align:center; position:relative;}
#searchinput {position:static;width:30em; font-size:11px; font-weight:bold; width:30em;}
#searchcontainer {text-align:left; width:34em; }
#searchcontainer .yui-ac-bd {font-size:10px; color:#666; background-color:#E1E7F3; text-align:left;}
#searchcontainer li {overflow:hidden; text-overflow:ellipsis; cursor:pointer; }
#searchcontainer em {font-style:normal; font-weight:bold; color:#000033;}
.yui-ac-ft {padding:3px; font-size:10px; text-align:right;}*/
</style>
yui-skin-sam) at the top level of our document (it need only be a parent element of the skinned control, but if you are only using one skin on a given page it is convenient to place the style on the document's <body> element. You can read more about skinning YUI on the YUI website.As with most applications, there are some final touches to be made in our code to get our implementation in line with the comp we looked at earlier in this article. Here are the requisite changes to add in the footer and to correctly position the suggestion container:
/* We want to have, at the bottom of the search container, a
link making it obvious to the user how s/he can find *all*
results for the current query. We'll use AutoComplete's
built-in footer mechanism for that, adding a link to which
we'll wire a form-submit event: */
this.oAutoComp.setFooter("<a id='sitesearchshowall' href='#'>View all search results.</a>");
/* Here's the wiring for the form submission on our footer link.
Note that we use the YUI Event Utility to add this listener --
this is part of YUI Core. */
YAHOO.util.Event.on("sitesearchshowall", "click", function(e) {
/* The Dom Collection's get method is similar to
document.getElementById in this instance: */
YAHOO.util.Dom.get("sitesearchform").submit();
});
/* We'll use one of AutoComplete's built-in events to position the
suggestion container directly below the input field. AutoComplete
handles this for you in non-centered implementations; for notes
on the centered implementation shown here, see Jenny Han Donnelly's
tutorial: http://developer.yahoo.com/yui/examples/autocomplete/ac_ysearch_json.html */
this.oAutoComp.doBeforeExpandContainer = function(oTextbox, oContainer, sQuery, aResults) {
var pos = YAHOO.util.Dom.getXY(oTextbox);
pos[1] += YAHOO.util.Dom.get(oTextbox).offsetHeight + 2;
YAHOO.util.Dom.setXY(oContainer,pos);
/* Workaround for an IE6 rendering bug: */
document.getElementById("searchcontainer").style.overflow = "visible";
return true;
};
3-complete.html.Summary
YUI is a comprehensive frontend toolkit — we've just looked at a tiny subset of its functionality here. But don't be daunted by YUI's comprehensiveness. It is, at heart, a straightforward framework on top of which you can build robust, scalable web applications that work across all the A-Grade browsers.
As you begin developing with YUI, you should consider joining the YUI community forum and subscribing to YUIBlog. In the community forum, you'll be joined by nearly 10,000 felow YUI users, many of whom have developed (and generously share) a deep expertise in specific aspects of the library. On the blog, you'll find articles and videos from the core YUI engineering team and links out to YUI resources in the community at large.









Thanks, nice article.
You just have a duplicated paragraph at: Although each YUI component has its own set of configurations and events, you'll find that this set of implementation concerns is consistent throughout the library. Use the User's Guides, API docs, and Cheat Sheets to identify the patterns used by each component.
Very well researched and well written article. Although I personally have used YUI Autocomplete in the past, I'll be sharing it with folks around the office. Thanks!
Nice article, but the layout, font choice, and font size were horrific.
@Bobby -- Sorry for the formatting issues. I don't have much control over those. I hope you found some good infromation, nonetheless, about YUI and what the project offers to developers. Warm regards, Eric
One minor detail that perhaps needs addressing: When there's no search results returned, there's no autocomplete dropdown shown so there's no messaging back to the user that their search failed. That leaves things in a somewhat vague state, from a UI perspective. The user's only/natural option then is to click the submit button, which takes them to the actual SRP, which then shows "no results found". How can we display a message to the user to let them know to try different search terms?
@Jim G -- Thanks for the suggestion; I hear what you're saying. Like you, I don't see the search-suggest or "instant search" functionality replacing the search results page (SRP), and entering a search term and pressing enter/return or clicking on the submit button should take you to a full SRP. (Using the Yahoo Search API on the server side, you could build a SRP housed in your own site chrome, too.) But while the user is typing, I wouldn't want to display a "no results found" message for a couple of reasons. The most important is that the suggestion container's contents will lag behind the typing of a fast typer -- and so a "no results" message might be misleading. As I was considering what you wrote, though, it did occur to me that an activity icon, one that showed when autocomplete was actively looking for results, would be a good addition and would help signal to users that the control was actively trying to help them. Regards, Eric
Eric, thanks for the response and the additional info. Along the lines of a "no results found" message -- what I was thinking of is how at www.yahoo.com and search.yahoo.com a "No suggestions for your search." message is displayed if no results are available. However, the functionality there is intended to provide search suggestions, not search results, so I see your point regarding this example as well. I like the idea of an activity icon or similar. Thanks again!