YUI 2.8: Learning the Library

By Daniel Barreiro , Dan Wellman
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started with YUI

About this book

The YUI Library is a set of utilities and controls written in JavaScript for building Rich Internet Applications, across all major browsers and independently of any server technology. There's a lot of functionality baked into YUI, but getting to and understanding that functionality is not for the faint of heart. This book gives you a clear picture of YUI through a step-by-step approach, packed with lots of examples.

YUI 2.8: Learning the Library covers all released (non-beta) components of the YUI 2.8 Library in detail with plenty of working examples, looking at the classes that make up each component and the properties and methods that can be used. It includes a series of practical examples to reinforce how each component should/can be used, showing its use to create complex, fully featured, cross-browser, Web 2.0 user interfaces. It has been updated from its first edition with the addition of several chapters covering several new controls and enriched with lots of experience of using them.

You will learn to create a number of powerful JavaScript controls that can be used straightaway in your own applications. Besides giving you a deep understanding of the YUI library, this book will expand your knowledge of object-oriented JavaScript programming, as well as strengthen your understanding of the DOM and CSS. The final chapter describes many of the tools available to assist you the developer in debugging, maintaining, and ensuring the best quality in your code.

In this new edition, all the examples have been updated to use the most recent coding practices and style and new ones added to cover newer components. Since the basic documentation for the library is available online, the focus is on providing insight and experience.

The authors take the reader from beginner to advanced-level YUI usage and understanding.

Publication date:
July 2010
Publisher
Packt
Pages
404
ISBN
9781849510707

 

Chapter 1. Getting Started with YUI

Welcome to the first chapter of YUI 2.8: Learning the Library. Throughout this book, we'll be exploring what makes up the library and what it can do for you. By implementing a selection of the available utilities and controls, we can see exactly how each one works and what functionality and tools it leaves at your disposal.

In this chapter we're going to introduce ourselves to the library by taking an overall view of it. The topics that we are going to cover include:

  • How to get the library, where to get it from, how to install it, and how to work with it in your own web pages

  • Where it came from, what inspired its creation, who made it, and the core ideas behind it

  • Exploring the library and investigating what components form its constituent parts

  • Where we can find important information and news about the library and places where we can go to for help if we need it

  • The licensing issues that surround its legal use

  • Who is likely to make the most of it

We'll also go over a brief coding example where you will get down to some proper scripting and find out for yourself just how easy it is to get up and running with the components themselves. This is where you will see the power provided by the library at first-hand.

 

What is the YUI?


The Yahoo! User Interface (YUI) Library is a free collection of utilities and controls, written primarily in JavaScript, which has been produced by the expert developers at Yahoo! to make your life easier as a web developer or frontend user interface designer.

It consists of a series of JavaScript and CSS components that can be used to quickly and easily build the rich and highly interactive applications that today's web consumer expects and demands.

The premise of the library is simple; often when writing JavaScript, you'll come up with a function that works perfectly in one browser, yet badly (or worse, not at all) in alternative browsers. This means that you'll often need a set of different functions to do exactly the same thing in different browsers.

This can be done for some of the major browsers without too much difficulty using standard object detection methods within if statements. However, this can lead to massively increased script files and unwieldy code that takes longer to debug and troubleshoot, and longer to write in the first place.

The YUI wraps both sets of code up into one object that can be used programmatically with one class, so instead of dealing with different sets of code for different browsers, you deal with the library and it makes the different calls depending on the browser in use.

Another important aspect of the library that I should mention at this point is its respect for the Global Namespace. All objects created by the library and its entire code run within, and can only be accessed through, the YAHOO Global Namespace object. This means that the entire library, including every utility and every control, and its numerous classes, create just one namespace object within the Global Namespace.

The Global Namespace is the global collection of JavaScript object names, and it is very easy to litter it with potentially conflicting objects, which can become a problem when code is shared between applications. The YUI library minimizes its impact on the Global Namespace while at the same time remains globally accessible by occupying a single name, YAHOO. However, for application code sandboxing is preferred and we shall show both techniques and mostly use the latter.

Essentially, the YUI is a toolkit packed full of powerful objects that enables rapid frontend GUI design for richly interactive web-based applications. The utilities provide an advanced layer of functionality and logic to your applications, while the controls are attractive pre-packed objects that we can drop onto a page and begin using with little customization.

Who is it for and who will it benefit the most?

The YUI is aimed at and can be used by just about anyone and everyone, from single site hobbyists to creators of the biggest and best web applications around. Developers of any caliber can use as much or as little of it as they like to improve their site and to help with debugging.

It's simple enough to use for those of you that have just a rudimentary working knowledge of JavaScript and the associated web design technologies, but powerful and robust enough to satisfy the needs of the most aspiring and demanding developers amongst you.

The library will be of interest primarily to frontend developers, as the main aim of the YUI is to provide a framework within which robust and attractive interfaces can be quickly and easily designed and built. It can help you to side-step what can otherwise be insurmountable compatibility issues.

There is no set standard that says you must know this much or that much before you can begin to use the YUI. However, the more you know and understand about JavaScript, the more the library will make sense to you and the more you will be able to gain from using it.

Trying to learn how to make use of the YUI without first knowing about the JavaScript language itself, at least to a basic working standard, is an endeavor likely to end in frustration and disappointment. It would be a great shame if a lack of understanding prevented you from enjoying the benefits that using the library can bring to both your creativity and creations.

So to get the most out of the YUI, you do need to have at least a basic understanding of JavaScript and the principles of object oriented programming. However, a basic working understanding is all that is required and those developers who have less knowledge of scripting will undoubtedly find that they come out of the experience of developing with the YUI knowing a whole lot more than they did to begin with.

The YUI can teach you advanced JavaScript scripting methods, coding, and security best practices, and more efficient ways of doing what you want to do. It will even help more advanced programmers streamline their code and dramatically reduce their development time, so everyone can get something from it.

For some, the YUI is also a challenge; it's an excellent opportunity for developers to get involved in a growing community that is creating something inspiring. The Firefox browser is a great example of an open source, community-driven, collaborative effort of separate but like-minded individuals. Some people may not want to develop web pages or web applications using the library: they may just want to be involved in evolving it to an even greater accomplishment.

I should also point out at this stage that like the library itself, this book expects you to have a prior knowledge and understanding of JavaScript, HTML, and CSS. While the use of the utilities, controls, and CSS tools will be explained in detail throughout the book, any HTML, CSS, or PHP code that is featured in any of the examples may not be explained in detail. Other skills, such as the ability to install and configure a web server, are also required.

Why the Yahoo! User Interface Library?

Using any JavaScript library can save you great amounts of time and frustration when coding by hand, and can allow you to implement features that you may not have the knowledge or skill to make use of. But why should you use the YUI rather than the many other libraries available?

To start with, as I'm sure you already know, Yahoo! is extremely well established, and at the forefront of cutting-edge web technology and frontend design principles. The utilities and controls provided by the library have already been tried and tested in their world-class service provision environment. Hence you know that the components are going to work, and work in the way that you expect them to work and that Yahoo! says that they will. The YUI Library is not a second-rate product, it is what Yahoo! uses.

The YUI library is not the only developer-centric offering to come from these world-class leaders and to achieve high levels of accomplishment and a following amongst developers. Apart from this, other very successful projects include the extensive Design Pattern library, Yahoo! Widgets, and the Yahoo! Query Language. They also have a wide range of APIs for you to experiment and work with, so they have already shown a commitment to providing open source tools designed to succeed.

Additionally, the library has already been publicly available for over three years and in this time has undergone rapid and extensive improvement in the form of bug fixes and additional functionality. Like the Mozilla and Firefox browsers, it has a huge, world-wide following of developers, all seeking to further enhance and improve it.

Other libraries seek to alter the JavaScript language itself, by building capabilities into the language that the developers felt should already have been present and extending the language in new and interesting ways. While these libraries can provide additional functionality at a deeper and more integrated level, their use can often be hampered by technical implementation difficulties. These will be too difficult to overcome for all but the most advanced and seasoned developers.

The YUI is not like this; it is extremely well documented, stuffed full of examples, and is extremely easy to use. It doesn't get bogged down in trying to alter the JavaScript language at a fundamental level, and instead sits on top of it as a complementary extension.

There's also no reason why you can't use the YUI library in conjunction with other JavaScript libraries if a particular feature, such as the rounding of box corners as provided by MochiKit for example, is required in your application but not provided by the YUI.

Graded browser support

Whichever browser you prefer, there's one thing that I think we can all agree on; all browsers are not created equal. Differing support and a lack of common standards implementation are things that have confounded web developers for as long as there have been web developers.

Although the situation is improving with agreed standards from the W3C, and we have better and more consistent support for these standards, yet we are far from being in a position where we can write a bit of code and know that it is going to function on any of the many browsers in use.

There may never come a time when this can be said by developers, but with the YUI, you can already count on the fact that the most popular browsers in use, on all types of operating systems, are going to be able to take full advantage of the features and functionality you wish to implement.

It doesn't, and can't be expected to support every single web browser that exists, but it does group together common browsers with common capabilities into a graded support framework that provides as much as it can to visitors no matter which browser they happen to be using.

Every single browser in existence falls into one of the defined grades; the most common class of browser are the A-grade variety of browsers, which the creators of the library actively support. These are modern, generally standards compliant and are capable of rendering in full the enhanced visual fidelity, and advanced interface functionality provided by the library as well as the inner core of content.

Though the number of browsers in this category is small, more than 95% of users regularly accessing Yahoo's sites use one of these. The YUI development team continually checks Yahoo's own statistics so that new browsers may be incorporated into or dropped from this category accordingly.

C-grade browsers are able to access the base or core content and functionality of the library components, but cannot handle the enhanced content. They are basically old, less capable versions of current browsers, or discontinued ones. These are browsers that are simply not supported by the library.

X-grade browsers are the ones that do not fall in the previous two categories. They are most likely to provide the full, enhanced experience. The most frequent cause for a browser to be in the X-grade list is that it does not have enough market share to justify devoting much time to test the YUI on it. A current example is Safari, which works fine in Windows, but it is not tested because it is an uncommon combination. Any browser that has not been extensively tested by the YUI development team is automatically an X-grade browser regardless of its capabilities.

Currently (in 2010 Q1), the complete spectrum of A-grade browsers supported by the library includes the following combinations of browser and platform configurations:

Browsers

Platforms

IE6, IE7, and IE8

Windows XP

IE8

Windows Vista

Firefox 3.0

Windows XP

Firefox 3.6

Windows XP, Vista and Mac OS 10.6

Safari 4.0

Mac OS 10.5 and 10.6

Google Chrome 4.0

Windows XP

These common configurations are able to make use of not just the core content of any applications we create with the YUI, but also all of the enhanced functionality brought on by the library. Any browser not on this list will still receive either an A or C-grade experience, but may be classed as an X-grade browser if it has not been extensively tested.

The graded browser support strategy is based on the notion of progressive enhancement as opposed to graceful degradation. Graceful degradation is a term that I'm sure you've heard at some point and involves designing content such that when it breaks in older browsers, it retains some semblance of order.

This method involves designing a page with presentation in your supported browsers as your main priority while still allowing unsupported browsers to view at least some kind of representation of your content.

Progressive enhancement approaches the problem of supporting browsers with different capabilities from the other direction by providing a core of accessible content and then building successive layers of presentation and enhanced functionality on top of this inner core of generalized support.

The following screenshot shows how the Rich Text Editor control appears in a C-grade browser. Older readers may recognize the browser used in this experiment as Netscape Navigator version 4—a browser popular approximately a decade ago.

As you can see from this example, the inner core of the page content is a standard HTML <textarea> element, which is displayed completely normally. The page doesn't break, but the high-fidelity content is not displayed. Using graceful degradation techniques, the browser would probably attempt to display the editor, but it would probably look very poor and would certainly not function.

The following screenshot shows how the editor appears in an A-grade browser:

In a capable, supported browser the library can transform the <textarea> element into the full Rich Text Editor control. Now the following screenshot shows exactly the same page in exactly the same browser but with JavaScript switched off:

Notice the similarity between a C-grade browser and an A-grade browser with JavaScript switched off.

The knowledge that has enabled Yahoo! to use the concept of graded browser support has been gained from the wide variety of user agents that hit their site every single day. They've been accessed by over 10,000 different software and platform configurations since they began focusing on by whom and how their portal is accessed. Approximately 96% of this total has received an A-grade experience when using the Yahoo! site.

 

What comes with the YUI?


Some JavaScript libraries are condensed into a single script file, such as the jQuery library. While this can make linking to them easier, it can be inefficient depending on how much of the library you actually use.

The YUI Library is split into its constituent components, making it easy to pick and mix which utilities and controls are used, and making it much more efficient to implement. In addition to the large collection of JavaScript files the library provides a great deal more.

The library topography

The library is currently divided into four distinct sections; the library core files, a series of utilities, a set of controls, and some excellent CSS tools. These are complemented by a series of tools that assist in the development process. There are also three versions of most of the library's utilities and controls, including a full version of the underlying JavaScript file that powers each component, complete with whitespace and comments for better readability and understanding that can help your learning and development.

Along with the full versions, there are also -min.js and -debug.js versions of all the utilities and controls. The -min (for minified) files have had all whitespace and comments removed, and variable names have been shortened where possible to cut down drastically on file size. The tool used to produce the -min version, the YUI Compressor is available for downloading at the YUI site so you can use it on your own pages.

The -min versions of each component are perfect for production-release applications. These are the ones that you would include in your own pages. Once all development and testing is done, you should minify your own code. Your development code should be well commented and nicely formatted and spaced; you shouldn't scrimp on the code you write for the sake of reducing the file size, the YUI Compressor can take care of doing that for you.

The -debug version of each component is designed to be used in conjunction with the Logger Control rather than presented to your visitors. Along with whitespace and comments, these files also contain additional code that logs messages to the Logger console during key interactions within the components. In fact, the -debug version is the original source; the other two are automatically generated from this one by first stripping the logging messages for the full version and then compress for the minified one.

The differences between the full and -min versions of each file can be quite large, with the -min versions often being less than half the size of the full version. The only comment in each of the -min files is the copyright notice, which has to stay intact in every file. Other than that, these files are pretty much solid chunks of hard code and readability is therefore very poor.

To further improve the loading time of the library, several combinations of files often used together are provided as aggregates. Thus the core files can be loaded in just one go. These are provided only in minified form even though they lack the -min suffix.

Once the application is ready to be deployed, Yahoo provides two more performance enhancements. You may load the library files from your own servers, but you can also load them either from Yahoo's Content Delivery Network (CDN) or from Google's CDN. These ensure that the user of your application, anywhere in the world, can retrieve the YUI components from the closest server farm available, the very same servers that the Yahoo! site pages use.

Finally, Yahoo's CDN accepts combination requests. Browsers can only have a certain number of active communications channels open at once. When there are more requests for included files than it can handle, the rest will be queued. A combination request is one where the names of several components are concatenated into the same URL and requested all at once, thus avoiding getting later requests delayed in the queue.

If we try to load the Calendar component as well as the Base CSS Tools, this is how it translates into actual numbers:

Method

Number of connections

Download Size (KB)

Delay (ms)

Raw

9

93.9

2365

Minified

9

34.2

1662

Aggregates

5

33.1

1277

Combo

2

32.1

115

Combination requests are different from aggregate files. The latter are produced in the build process of the library and are available from both CDNs as well as in the developer download. The combination requests are completely dynamic and have to be produced on the fly with an application running on the CDN; the combined components do not exist as files in the CDN as the aggregates do. You cannot do a combination request from Google CDN nor when developing in your own machine. However, a first beta release of the application that serves these requests has been released as the YUI PHP Loader and an external contributor has already done an experimental port to Java.

To assist the developer in building the <script> and <style> tags required to retrieve the library components, the YUI site provides the Dependency Configurator. It lets you select the components you need, the version (-debug, full, or -min) you want, and which CDN you want to download it from. It will produce a listing that you can simply copy and paste into your page. All mandatory dependencies will be there in the proper order.

There are also three different file designations that each component can be classed as; fully released components are termed GA (General Availability). GA components are typically the oldest, have been tested extensively, and had most of the bugs weeded out. They are reliable and have been considerably refined.

Beta designated utilities and controls are still in the process of being ironed out, but they have been released to the development community for wider testing, bug highlighting, and feature suggestion.

Any component termed experimental is still in the conceptual phase of its design and may or may not be promoted to Beta or GA status.

The core files

The core of the library consists of the following three files:

  • YAHOO Global Object

  • Dom utilities

  • Event Utility

The Global Object sets up the Global YUI namespace and provides other core services to the rest of the utilities and controls. It's the foundational base of the library and is a dependency for all other library components (except for the CSS tools). It also contains the YAHOO.Lang object which is made of a series of static methods that add functionality that the language, JavaScript, should have, such as a .trim() function for strings.

The Dom utilities provides a series of convenient methods that make working with the Document Object Model much easier and quicker. It adds useful selection tools, such as those for obtaining elements based on their class instead of an ID, and smoothes out the inconsistencies between different browsers to make interacting with the DOM programmatically a much more agreeable experience.

The Event Utility provides a unified event model that co-exists peacefully with all of the A-grade browsers in use today and offers a consistent method of accessing the event object. Most of the other utilities and controls also rely heavily upon the Event Utility to function correctly.

As the core files are required in most YUI implementations, they have been aggregated into a single file: yahoo-dom-event.js. Using this one file instead of three individual files helps to minimize the number of HTTP requests that are made by your application.

The Utilities

The utilities provide you with different sets of user-interface functionality that you can implement within your web pages. They provide programming logic and deal specifically with the behavior and interactions between your visitors and the different objects and elements on your pages.

They are a concept that you begin with and then build upon, and they provide the foundation from which you create your vision. They provide unseen behavior; for example, the Animation Utility isn't something your visitors will see directly, but its effects on the element being animated will of course be visible. They are the backstage hands of your application.

Like the core files of the library, several utilities have all been rolled up into one easy-to-link-to aggregate file: utilities.js. Again, this can be used to make your application run more efficiently when using all of the utilities together. The Dependency Configurator will automatically offer to load this file instead of its individual components if it proves smaller.

The set of utilities included in the current release of the library (which is constantly changing and growing) are as follows:

  • Animation Utility

  • Browser History Manager

  • Connection Manager (core and full)

  • Cookie Utility

  • DataSource Utility

  • Drag & Drop Utility

  • Element Utility

  • Event plugins

  • Get Utility

  • ImageLoader Utility

  • JSON Utility

  • Resize Utility

  • Selector Utility

  • Storage Utility [beta]

  • StyleSheet Utility [beta]

  • SWF Utility and related components [beta]

  • YUILoader Utility

The Connection Manager is provided in the minimal, core, and the full featured version. So, if you need the very basic set of features, you are not loading the extras. Likewise, the basic Event Utility, part of the core utilities, is supplemented by an extra set of optionals. This pattern is repeated, as we will see in the next section.

The Controls

The controls, on the other hand, are a collection of pre-packaged objects that can be placed directly on the page as they are, with very little customization. Your visitors can then interact with them.

These are objects on the page that have properties that you can adjust and control, and are the cornerstone of any web-based user interface.

These controls will be highly recognizable to most visitors to your site and will require little or no learning in order to use. The complete suite of controls currently included with the library is:

  • AutoComplete Control

  • Button Control

  • Calendar Control

  • Carousel Control [beta]

  • Charts Control [beta]

  • Color Picker Control

  • Container Family (core and full)

  • DataTable Control

  • ImageCropper [beta]

  • Layout Manager

  • Menu Control

  • Paginator

  • ProgressBar Control [beta]

  • Rich Text Editor Control (simple and full)

  • Slider Control

  • TabView Control

  • TreeView Control

  • Uploader [experimental]

The CSS Tools

The CSS Tools form the smallest, but by no means the least useful, component of the library. The utilities and controls are designed to be used almost independently (although some of the files do depend on other files in the library to function properly), but the CSS tools are designed to be used together (although they can also be used separately if desired) and provide a framework for standardizing the visual representation of elements on the page.

The following four tools make up the current CSS section of the library:

  • Reset CSS

  • Fonts CSS

  • Grids CSS

  • Base CSS

The CSS tools have just two versions of each CSS file instead of three: a full version and a minimum version; there are no debug versions in this section of the library. As with the yahoo-dom-event utility, some of the CSS files have also been combined into one file for your convenience. You can use reset-fonts-grids.css or reset-fonts.css depending on your requirements.

The developer tools

These files are meant to assist you in the process of developing or deploying the application; they are not expected to ever reach the final user. They are:

  • Profiler

  • Profiler Viewer

  • Logger

  • YUI Test

  • YUI Compressor

  • YUI PHP Loader [beta]

  • YUI Doc

  • YUI Builder

The first four are JavaScript files that can be loaded along with your application to test or evaluate it. The others are external utilities written in different languages that need to be installed into your development machine or deployment server. These and other utilities developed by others will be covered towards the end of this book.

The library's structure

Once the library has been unpacked, you'll see that there are a series of folders within it; the build folder contains production-ready code that you can use immediately on your website. This is where the code that makes each component work and all of its associated resources, such as images and stylesheets can be found.

The docs directory contains the complete API documentation for every library component. This is where you can find the classes that make up each component, look at the underlying code, and review the properties and methods available to you.

The examples folder contains a series of demonstrative web pages that highlight the key functionality or behavior of each library component and mirror the example space found online. They are often a good place to start testing a new idea: find an example close to what you want and start changing it.

The tests folder contains a series of pages that use the YUI Test tool and the Logger Control to check that each component is functioning correctly for the platform on which it is being run. Each method for the component being tested is called, and the results are logged for you to examine. Any change or patch to the library should be tested to ensure it doesn't break existing functionality. These are the very same tests run on all A-grade browsers at Yahoo! before any new release.

The assets folder contains extras used either by the examples, the API docs, or index files in the library pack; they are not used by the YUI components. Finally, an as-docs folder contains the documentation for the interface to the SWF flash components, which are beta at this stage.

Another set of folders that you'll need frequently when using the library controls are the assets folders under each of the component folders in the build directory. Each of the controls has its own assets folder, which contains things like supporting images and stylesheets, as well as the sam skin files (if applicable) for display purposes.

There are some other files and folders within the library, such as an index for the library so that you can easily look for documentation or examples and release notes.

Due to the changing nature of the beta, and the experimental utilities and controls, we will not be looking at them in any great detail in this book. For information regarding any of these components, see the YUI site and API guides.

What else does Yahoo! provide?

There are some additional resources that are available courtesy of Yahoo! to help you use the library to its maximum potential. There is a series of very helpful "Cheat Sheets" for each component at its developer guide page in a PDF file, which can be printed each on a single page.

These resources provide a useful and centralized reference manual, which lists the key methods, properties, and syntax patterns of each of the fully released components and gives some basic examples of their implementation.

There is a discussion forum, which developers can use to discuss their projects and get help from experts. The old Yahoo! Group for YUI developers, with 13,600 members and an average of 1000 messages a month until half a year ago, is still active but it has been steadily declining since then in favor of the new forum at http://yuilibrary.com/forum/. Both are fully searchable and they are a good place to start if you've got a problem with getting a utility or control to do what you want it to or to submit a question if there is no information listed.

The forum is home to a growing community of developers that have been brought together by the YUI; community involvement is an excellent way to connect with developers and can take a project in new and impressive directions.

For those of you who want to join the YUI development community and give something back to the Yahoo! Developers who have bestowed this awesome tool upon us, besides helping your fellow developers in the forum, there is also the facility to submit bug reports or feature requests. This is an excellent channel of feedback and as the YUI team points out, many useful features have been added to the library following a feature request. It also allows the team to remove errors and refine the features of existing components.

To file a ticket for a bug fix or an enhancement suggestion you can go to http://yuilibrary.com/projects/yui2/newticket. A year ago this tracking system resided in SourceForge.net, but it didn't have all the features the YUI team needed and, in fact, internally they used another system to track their progress so the two systems were often out of sync. Now, the bug tracker we see is the one the YUI team sees. Though all the members of the YUI team participate in the forum, if you find a bug don't just comment it in the forum, as forum posts cannot be tracked; the bug tracker is the place to ensure that a bug gets fixed.

Once a bug is fixed, you no longer need to wait until the next release to get your hands on the fix. The YUI Library and many of its tools are now saved into GitHub at http://github.com/yui so, as soon as you see a bug fixed, you can retrieve the latest build from the very same place the YUI team uses. This is a live development repository, so not all the files are in a stable state; any file retrieved from this repository has to be used with caution and generally not in a production environment.

To keep up-to-date on developments in the YUI and read associated news statements and technical articles about the library and the Yahoo! Developer Network in general, or to watch screencasts from the development team and other experts, you can visit the YUI blog at http://yuiblog.com.

This is a companion blog not just for the YUI Library but also for the Yahoo! Design Pattern Library. This is separate from the YUI and is not something that we'll be looking at in this book, but it is worth mentioning because the two resources can be used together in many situations.

The entire selection of different video screencasts and podcasts are brought together in one place for easy searching in the YUI Theater. Both the blog and the theater are subscribable via RSS, so that you can have up-to-date news and announcements surrounding the library.

Finally, you can go further: sign a Contributor License Agreement (CLA) and help with the YUI code itself. The CLA basically ensures that you agree to provide your contributions under the same license as the YUI and that you are not violating other people's rights when offering this code. This prevents any individual contributor from forcing exceptions to the general terms of the license used with the YUI.

Are there any licensing restrictions?

All of the utilities, controls, and CSS resources that make up the YUI have been publicly released, completely for free, under the open source BSD license. This is a very unrestrictive license in general and is popular amongst the open source community.

For those of you who don't know anything about what the license stands for and what it allows you to do, I'll give you quick overview now so that you need not worry about it again. Consider these next few paragraphs your education in open source software licensing!

BSD stands for Berkeley Software Distribution and was originally designed and used by a team of developers who created an open source operating system of the same name that was similar in many ways to the UNIX platform (and even shared part of its code base with it). Many of today's most popular operating systems, including Windows and Mac OS X are derived from or contain code from the original BSD operating system.

The current BSD version, sometimes known as the New BSD license, differs from the original. It has had the restrictive UC Berkeley advertising clause removed, making it almost equivalent to the MIT license, but with the addition of a brief final clause prohibiting the use of the copyright owner's name for endorsement without obtaining prior consent.

This means that you can pretty much do whatever you want to do with the library source code; you can use it as it is, you can modify it as you wish, add to it, or even remove bits. You can use the files in the format in which they are provided, or you can use the code within them in the distribution of a compiled, closed-source application. Thus, the code belongs to the community and should Yahoo! ever drop it, the community can carry on.

You can use it in your own personal projects, as part of a commercial venture or even within an educational framework. You can do all of this provided that you retain the copyright notice in your source code, or the copyright notice present on each of the library files remains intact.

If you're using the library files as they come in the library, all you need to do is make sure that the existing copyright notice is left at the top of every file that you use. In a compiled application, it should be clearly visible in the help section or user manual.

 

Installing the YUI


The YUI is not an application in its own right, and it doesn't need to be installed as such. Getting started with the YUI is extremely simple; you first choose whether to download all of the source files from Yahoo! and use them locally as part of your websites' hierarchy, or whether to use the URLs provided on the YUI developer pages to reference the library files stored on Yahoo's web servers.

These are the exact same files that are used in many different interface implementations across the Yahoo! websites and as such can be depended on for being almost continuously available.

Another benefit of using Yahoo's or Google's CDN is that their networks are global in nature, with servers running in many geographically distinct parts of the world. Being able to serve library files from a location closer to your visitors' location results in a better response from your application; this is good news for your visitors and therefore good news for your business.

Additionally, as I mentioned earlier, there are different versions of each of the working files in the library including a "minified" file that has been stripped of whitespace and comment blocks. The Yahoo! servers provide these minified versions of the files, but in addition, they also serve the files in a GZIP format, making the files up to 90% smaller and therefore, much more efficient for transportation across the Internet. Finally, Yahoo! also helps the cache hit rates by issuing expires headers with expiration dates set far in the future. But best of all, these benefits are all provided for free.

If you've decided that you want to download the YUI in its entirety, you'll find a link on the YUI home page at http://developer.yahoo.com/yui/2/. The files were formerly stored at SourceForge.net and you might find references pointing there, including in the first edition of this book, but the project has been migrated away from SourceForge.

So as far as installing the library goes, the most that you'll need to do is to download the library to your computer and unpack it to a local directory where you can easily find the files, assets, and resources that you require for your current project, and if you choose to let Yahoo! host the files for you, you won't even need to do that.

Creating an offline library repository

All the examples in this book fetch the library components from the Yahoo servers. If you are unable to access those you may create your own repository. So you will need to create a new folder on your hard drive called yuisite. This folder is where all of our examples will reside.

Just as some of the examples included in the downloaded files do, we will use PHP for server-side scripting, thus this folder needs to be created somewhere under your web server root and where PHP scripts can be executed. It is worth mentioning that YUI is not tied to PHP in any way. Every sample PHP script in this book as well as any provided with the examples in the YUI library download can be replaced by equivalent files in any other server platform. We use PHP simply because it is popular, simple and, most important, free, but any other server platform would do just as well.

Inside this folder, create another new folder called yui. When you unpack the library, you will see a folder called build inside it. You will need to copy and paste the entire build directory into the yui folder that you have just created. You may, if you wish, copy the whole library to the yui folder, but our examples only require the build directory.

To use the examples with this offline repository, the code for the examples needs to be changed. All the <script> and <style> tags that point to the Yahoo! servers need to be changed to point to the location of the offline repository, whichever it might be. While the examples in the code bundle point to the Yahoo servers, the printed version of them might point to this off-line repository just to keep the URLs short.

It is important that this structure is correct; otherwise none of the examples that we create as we progress through this book will work. A common indicator that library files are not accessible is a JavaScript error message stating that YAHOO is undefined.

 

Using the library files in your own web pages


One thing that you need to check when using different controls and utilities from the library is which, if any, of the other utilities will be needed by the component that you wish to use; fortunately the online documentation and cheat sheets will list out any dependencies of any component that you choose and the Dependency Configurator will assist you in finding out the best combination.

There is only one file that must be used in every implementation of any of the various components: the YAHOO Global Object. This utility creates the namespaces within which all of the YUI library code resides, and contains some additional methods that are used by other files throughout the library.

It must appear before any of the other library files because if references to other component files appear before the Global Object, none of the namespaces used will be recognized by your script. This will cause a JavaScript error message stating that YAHOO is undefined.

The CSS files should be linked to in the <head> section of your page, as any other CSS file would be. For performance reasons, the code that invokes and customizes the library components should be as close to the bottom of the page as possible. Also, you can easily separate your JavaScript from your HTML altogether and keep your scripts in separate files.

To use the current version of the Animation Utility from the Yahoo! servers for example, the following script tags would be required:

<script type="text/javascript" src="http://yui.yahooapis.com/ 2.8.0/build/yahoo-dom-event/yahoo-dom-event.js">
</script>
<script type="text/javascript" src="http://yui.yahooapis.com/ 2.8.0/build/animation/animation-min.js">
</script>

All code components depend on the YAHOO Global Object, which should always go first. As the Animation Utility also depends on the Event and Dom utilities, we can use the yahoo-dom-event aggregate instead of individual files.

Once these script tags have been added to your page, the code required to animate your object or element would go into its own script tag in the <body> section of the page.

Now, we'll take our first look at one of the library components in detail: the Calendar Control. We can take a quick look at its supporting classes to see what methods and properties are available to us, and can then move on to implement the control in the first of our coding examples.

 

Code placement


Good coding practice should always be adhered to, whether designing with the YUI or not. Keeping your JavaScript and CSS code in separate files helps to minimize the initial size of the page so it shows up earlier and also increases the chances of finding the external, common files in the cache. But it does have its downsides too; every file that your page links to adds another HTTP request to the interaction between your visitor and your server, which can result in slower performance. However, as they change far less than the HTML page that uses them, repeated visitors are more likely to have them in their caches.

In real-world implementations, we would always keep as much of our JavaScript and CSS in separate files as possible, keeping a clear distinction between content, behavior, and presentation layers. For the purpose of this book, however, we will be keeping the HTML and JavaScript code in one file. I stress that this is not the correct way to do things and is done purely so that the examples do not become bloated with numerous files.

 

Perfect date selection with the Calendar Control


For our first coding example, we'll take a quick look at the Calendar Control. The YUI Calendar allows you to easily create a variety of attractive and highly functional calendar interfaces that can allow your visitors to quickly and easily select single dates or range of dates.

It's an easy component to master, making it ideal for our very first coding example. Not much coding is required for a basic calendar implementation, and the control can easily be customized using the Calendar classes' extensive range of properties or by overriding the default styling.

There is also a range of different formats of Calendar that we can create; there's the basic, single select, one-page calendar control, which displays one month at a time, or there's a larger, multi-page calendar, which allows multiple months to be displayed at once. Multi-select calendars can come in either single or multiple month display formats.

The rendered calendar is instinctively intuitive to use and is presented in a very attractive manner. Almost anyone being presented with it will instantly know how to use it. By default, it features a clear and sensible interface for selecting a date, arranging the dates of the current or starting month in a grid headed by the day of the week.

It also features automatic rollovers for valid or selectable dates, automatic current date selection, and an infinite date range both forwards and backwards in time that the visitor can move through to select the date of their choice. When navigating between months, the individual days automatically reorder themselves so that the correct date appears in the correct day of the week.

Several classes make up the Calendar Control; two separate classes represent the two different types of calendar that can be rendered and another class contains math utilities that allow you to add, subtract, or compare different dates. We will take a look at the classes that make up this control to see what is available and exactly how it works before we begin coding.

The basic Calendar class

The most basic type of calendar is the single-panel Calendar, which is created with the YAHOO.widget.Calendar class. To display a calendar, an HTML element is required to act as a container for the calendar. The following screenshot shows a basic Calendar Control:

The constructor can be called specifying, at the very least, a reference to the HTML element that will contain the calendar. This can either be an actual DOM reference or it can be its id attribute.

You can also specify an additional argument that can accept a literal object containing various configuration properties. The configuration object is defined within curly braces within the class constructor. This is a pattern frequently used in YUI components.

When the constructor for an object might take many optional arguments, instead of reserving a slot in the argument list for each possible one, a configuration object is accepted instead, which is nothing more than a regular JavaScript object literal or an expression that returns an object. This object should have properties corresponding to the configuration attributes that you want to set different from the default.

For the Calendar Control you would set attributes such as its title, a comma-delimited range of pre-selected dates or a close button shown on the calendar.

There are many methods defined in the basic Calendar caliber class. Some of the more useful methods are:

  • A method for determining whether a date is outside of the current month: isDateOOM.

  • Navigation methods such as nextMonth, nextYear, previousMonth, and previousYear that can be used to programmatically change the month or year displayed in the current panel.

  • Operational methods such as addMonths, addYears, subtractMonths, and subtractYears, which are used to change the month and year shown in the current panel by the specified number of months or years.

  • The render method is used to draw the calendar on the page and is called for every implementation of a calendar, after it has been configured. Without this method, no calendar appears on the page.

  • Two reset methods: reset, which resets the calendar to the month and year originally selected, and resetRenderers, which resets the render stack of the calendar.

  • Selection methods that select or deselect dates such as deselect, deselectAll, deselectCell, select, and selectCell.

As you can see, there are many methods that you can call to take advantage of the advanced features of the Calendar Control.

The CalendarGroup class

In addition to the basic calendar, you can also create a grouped calendar that displays two or more month panels at once using the YAHOO.widget.CalendarGroup class. The control automatically adjusts the calendar's UI so that the navigation arrows are only displayed on the first and last calendar panels, and so that each panel has its own heading indicating which month it refers to.

The CalendarGroup class contains additional built-in functionality for updating the calendar panels on display, automatically. If you have a two-panel calendar displaying, for example, January and February, clicking the right navigation arrow will move February to the left of the panel so that March will display as the right-hand panel. All of this is automatic and nothing needs to be configured by you.

Though showing two or more calendars in the page looks very different to the user, for the programmer it hardly makes any difference at all.

 

Implementing a Calendar


To complete this example, the only tool other than the YUI that you'll need is a basic text editor. Native support for the YUI is provided by some web authoring software packages, most notably Aptana, an open source application that has been dubbed "Dreamweaver Killer". However, I always find that writing code manually while learning something is much more beneficial.

It is very quick and easy to add the Calendar, as the basic default implementation requires very little configuration. It can be especially useful in forms where the visitor must enter a date. Checking that a date has been entered correctly and in the correct format takes valuable processing time, but using the YUI Calendar means that dates are always exactly as you expect them to be.

So far we've spent most of this chapter looking at a lot of the theoretical issues surrounding the library; I don't know about you, but I think it's definitely time to get on with some actual coding!

The initial HTML page

Our first example page contains a simple text field and an image that once clicked will display the Calendar control on the page, thereby allowing a date to be selected and added to the input. Begin with the following basic HTML page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>YUI Calendar Control Example</title>
<script type="text/javascript"
src="yui/build/yahoo-dom-event/yahoo-dom-event.js">
</script>
<script type="text/javascript"
src="yui/build/calendar/calendar-min.js">
</script>
<link rel="stylesheet" type="text/css"
href="yui/build/calendar/assets/skins/sam/calendar.css">
<style type="text/css">
input { margin:0px 10px 0px 10px;}
</style>
</head>
<body class="yui-skin-sam">
<div>
<label>Please enter your date of birth:</label>
<input type="text" name="dobfield" id="dobfield">
<img id="calico" src="icons/cal.png"
alt="Open the Calendar control">
</div>
<div id="mycal"></div>
</body>
</html>

We begin with a valid DOCTYPE declaration, a must in any web page. A question that often pops up in the YUI forums is why HTML4 Strict? Experience has shown that it is the one more reliably implemented across all browsers. Support for XHTML is uneven across browsers and HTML5 is not yet a standard. Let us call HTML4 Strict the A-grade supported doc type; others might just work but are not tested and some are positively known not to work. Remember, Yahoo! collects an unbeatable quantity of statistics and this doc type is the one that they have found that provides the best and most consistent user experience to their millions of visitors per day.

For validity, we can also add the lang attribute to the opening <html> tag and for good measure, enforce the utf-8 character set. Nothing so far is YUI-specific, but coding in this way every time is a good habit.

We link to the stylesheet used to control the appearance of the Calendar Control, which is handled in this example by the sam skin within the <link> tag. Accordingly, we also need to add the appropriate class name to the <body> tag.

Following this, we link to the required library files with <script> tags; the Calendar Control is relatively simple and requires just the YAHOO, Dom, and Event utilities (using the aggregated yahoo-dom-event.js file for efficiency), as well as the component source file calendar-min.js.

A brief <style> tag finishes the <head> section of the page with some CSS relevant to this particular example, and the <body> of the page at this stage contains just two <div> elements: the first holds a <label>, the text field, and a calendar icon (which can be used to launch the control), while the second holds the calendar control. When viewed in a browser, the page at this point should appear like this:

Note

The calendar icon used in this example was taken, with gratitude from Mark Carson at http://markcarson.com.

We need to create a <script> tag to contain our code. As an HTML page loads many of its components asynchronously, we cannot be sure what HTML elements get loaded when and when they get appended to the DOM. In this case, we cannot be sure the calendar icon will be there by the time the script starts executing so right before the closing </body> tag, add the following code:

<script type="text/javascript">
YAHOO.util.Event.onDOMReady(function () {
var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, Lang = YAHOO.Lang;
});
</script>

We first call the .onDOMReady() method of the Event Utility, which will call the function that is supplied as its argument when the DOM is ready to be used. We could even be more specific by using the method .onAvailable() to ask for our calendar icon but we would gain little by doing that.

Instead of supplying .onDOMReady() with a reference to a function to call, we are defining the function right on the spot. This is part of the flexibility that JavaScript has built-in: you can define a function anywhere you need it and you don't even need to give it a name. An anonymous function has a further advantage. We have already mentioned that the whole of the YUI Library takes a single name in the Global Namespace: YAHOO, which is a good thing because this namespace gets easily cluttered with variables and functions and what not. You might think that you control what goes into the Global Namespace. That is not the case.

All the members of both window and document have aliases in the Global Namespace. The properties window.location, document.location, window.document.location and plain location all point to the very same property. The property window.name can simply be called name; many programmers using the variable name don't even realize they are using a DOM property. Proprietary extensions in different browsers add extra members in this namespace. Worried enough already?

At some point someone decides to make some extra money by adding some paid banners, or provide directions by embedding some active map into the page and it will include some code. Some of this code is sloppy and further pollutes the Global Namespace.

The Global Namespace is not a comfortable place to be in.

An anonymous function takes no name at all in any namespace. We leave no litter behind; we get no pollution from outside.

Let's go back to the earlier code. Within that anonymous function we are declaring a set of three variables: Dom, Event, and Lang. We call these "shortcuts". They point to the most frequently used classes in the core utilities. Having the whole YUI stored under the single global name YAHOO has a cost: all its members have long names, all starting with YAHOO. We don't want to type those long names all the time so we create aliases for those we use more frequently. We might not use them all; in this example we won't use Lang. A tool we will see in the last chapter, JSLint, will tell us which variables went unused so we may well have this set of shortcuts as a template and let JSLint tell us if we overdid it. We may add additional shortcuts as needed. These shortcuts are not copies of the classes but additional references to the very same class; they don't waste time or memory, in fact, in the end they save on both.

The anonymous function provides another benefit, it creates a sandbox. Every variable or function declared in it will be local to that function and accessible to all functions within. The shortcuts we have created are visible to all the code contained in the sandbox, we can use them freely within, but are completely invisible outside the sandbox because they are local to the anonymous function. That is why we had to spell out the whole YAHOO.util.Event.onDOMReady outside the sandbox, because the Event shortcut is not visible there (and has not been executed yet, but we would not be able to even if it had been). If we declare a variable called name within the sandbox, we would not be using window.name accidentally, we would still be able to access that one by its full name if we need to, but if we refer to name it would be our very own variable.

The use of sandboxes has become the standard in YUI programming. In fact, YUI3 uses sandboxing extensively. The other alternative, creating your own namespace, which was the recommended way not long ago, is no longer used for most application code. Formerly you would piggyback your code in a branch under the YAHOO global variable. Most examples packed with the YUI library use the YAHOO.example namespace. The examples in the first edition of this book used YAHOO.yuibook. You did not take any space in the Global Namespace; you simply used some space you knew the YUI library did not use.

Creating your own namespace is still done for libraries. As anything created within the sandbox cannot be seen outside of it, you can't create libraries in sandboxes because they cannot be seen elsewhere. For application code, which is not called from anywhere outside of the sandbox itself, keeping everything hidden within is perfectly fine.

Now we can add the extremely brief code that's required to actually produce the calendar. Within the braces of our anonymous function, add the following code:

//create the calendar object, specifying the container
var myCal = new YAHOO.widget.Calendar("mycal");
//draw the calendar on screen
myCal.render();
//hide it again straight away
myCal.hide();

This is all that we need to create the Calendar; we simply define myCal as a new Calendar object, specifying the ID of the HTML element that will hold it as an argument of the constructor.

Once we have a Calendar object, we can call the .render() method on it to create the calendar and display it on the page. No arguments are required for this method. As we want the calendar to be displayed when its icon is clicked, we hide the calendar from view straight away.

To display the calendar when the icon for it is clicked, we'll need one more function. Add the following code beneath the .hide() method:

//define the showCal function which shows the calendar
var showCal = function() {
//show the calendar
myCal.show();
}

As we've said, JavaScript allows us to create functions anywhere. This function is contained within the anonymous function that is our sandbox; a function within a function. We can do this any number of levels deep. An inner function can access all the local variables of the functions it is contained in; thus we can refer to myCal from inside showCal.

Functions can be stored in variables; in fact, naming a function is nothing more than saying in what variable the function will be stored. Here we are storing the function that shows the calendar in a variable called showCal, effectively declaring a function named showCal. We prefer this notation to highlight where it is being stored.

The keyword var in front of the variable name is vital. JavaScript allows us to use variables without declaring them previously. Variables used without being declared are created automatically in the Global Namespace. We don't want this to happen. We want showCal to be in the sandbox, that is why we declare the variable showCal with the var keyword and initialize it to a function. But don't worry, if we forget the var keyword, the JSLint utility will warn us.

To have the showCal function executed when the icon for it is clicked, we'll need to listen for the click event. We can use method YAHOO.util.Event.addListener() but we already have a shortcut called Event and the YUI also gives us a shorter alias for .addListener() so we can add the following code beneath the .hide() method:

Event.on("calico", "click", showCal);

Save the file that we've just created as calendar.html or similar in your yuisite directory. If you view it in your browser now and click on the Calendar icon, you should see this:

The calendar is automatically configured to display the current date, although this is something that can be changed using the configuration object mentioned earlier.

Now that we can call up the Calendar Control by clicking on our Calendar icon, we need to customize it slightly. Unless the person completing the form is very young, they will need to navigate through a large number of calendar pages in order to find their date of birth. This is where the Calendar Navigator interface comes into play.

We can easily enable this feature using a configuration object passed into the Calendar constructor. Alter your code so that it appears as follows:

//create the calendar object, using container & config object
var myCal = new YAHOO.widget.Calendar("mycal", {navigator:true});

Clicking on the Month or Year label will now open an interface that allows your visitors to navigate directly to any given month and year:

The configuration object can be used to set a range of calendar configuration properties including the original month and year displayed by the Calendar, the minimum and maximum dates available to the calendar, a title for the calendar, a close button, and various other properties.

Let's update our Calendar instance so that it features a title and a close button. Add the following properties to the literal object in our constructor:

//create the calendar object, specifying the container and a literal
//configuration object
var myCal = new YAHOO.widget.Calendar("mycal", {navigator:true, title:"Choose your Date Of Birth", close:true});

This is what our Calendar should now look like:

Configuration properties like those we have just set can also be set outside of the constructor by using the .setProperty() method. Let's use these to alter our Calendar so that the first column header is set to Monday instead of Sunday. Add the following code directly before the call to the .render() method:

//configure the calendar to begin on Monday
myCal.cfg.setProperty("start_weekday", "1");

When the calendar is displayed now, Monday will be the first day instead of Sunday:

Finally, we need to add some additional code that will allow the date that is selected to be inserted into the text field. We can do this using some of the custom events defined by the calendar classes.

Highly eventful

Both the Calendar and CalendarGroup classes have a series of custom events defined for them that allow for easily listening and reacting to interesting moments during any calendar or calendar group interaction.

The two classes both have the same set of events defined for them, which include:

  • beforeDeselectEvent: Fired before a cell is deselected

  • beforeHideEvent: Fired just before the calendar is hidden

  • beforeHideNavEvent: Fired just before the calendar navigator is hidden

  • beforeRenderEvent: Fired before the calendar is drawn on screen

  • beforeSelectEvent: Fired before a cell is selected

  • beforeShowEvent: Fired just before the calendar is shown

  • beforeShowNavEvent: Fired just before the calendar navigator is shown

  • changePageEvent: Fired once the current calendar page has been changed

  • clearEvent: Fired once the calendar has been cleared

  • deselectEvent: Fired once the cell has been deselected

  • hideEvent: Fired once the calendar has been hidden

  • hideNavEvent: Fired once the calendar navigator has been hidden

  • renderEvent: Fired once the calendar has been drawn on screen

  • resetEvent: Fired once the calendar has been reset

  • selectEvent: Fired once a cell, or range of cells, has been selected

  • showEvent: Fired once the calendar has been shown

  • showNavEvent: Fired once the calendar navigator has been shown

This rich event system allows you to easily watch for cells being selected or deselected, month panel changes, render events, or even the reset method being called, and add code to deal with these key moments effectively. As you can see, most of the events form pairs of before and after events, which allows you to easily cancel or abort an operation before it has any visual impact by returning false in the before event.

Let's now take a look at how these custom Calendar events can be used. First define the function that will handle the select event; add the following code directly after the showCall() function:

//attach listener for click event on calendar icon
Event.on("calico", "click", showCal);
//define the ripDate function which gets the selected date
var ripDate = function(type, args) {
}
//subscribe to the select event on Calendar cells
myCal.selectEvent.subscribe(ripDate);

Every time the select event is detected, our ripDate function will be executed. The type and args objects are automatically provided to us by the control; the args object is what we are interested in here, because it gives us easy access to an array of information about our Calendar.

Now, within the curly braces of the ripDate() function set the following variables:

//get the date components
var dates = args[0],
date = dates[0],
theYear = date[0],
theMonth = date[1],
theDay = date[2];

The first item in the args array is an array of selected dates, so we first save this to the variable dates. As this is a single-select calendar, only the first item of the dates array will contain data, so this is also saved to a variable: the date variable.

Each date is itself an array, with the first item corresponding to the year, the second item equaling the month, and the third item mapped to the individual date. All of these values are saved into variables.

var theDate = theMonth + "/" + theDay + "/" + theYear;

This part of the function uses standard concatenation techniques to build a string containing the individual date components in the format in which we want to present them (so that, for example, it would be extremely easy to express dates in UK format, where the date appears before the month):

//get a reference to the text field
var field = Dom.get("dobfield");
//insert the formatted date into the text field
field.value = theDate;
//hide the calendar once more
myCal.hide();

Finally, we use the very handy Dom utility's .get() method to grab a reference to the text field, set the value of the text field to our date string, and then hide the calendar once more.

Save the file once more and view it again in your browser of choice. After clicking the calendar icon and choosing a date, it should be displayed in the text field:

At this point, we can take a brief look at how we can override the default styling of the calendar. When we added the calendar navigator there was no visible clue for the user to show that the month and year could be clicked. When the cursor hovers over them, they change, but the user might never notice that. We might want to correct that so that the month and year have the same white background as the navigation arrows. This can be done with the following simple CSS rule, which should be inserted into the <style> tag in the <head> of our document:

.yui-skin-sam .yui-calendar a.calnav {
border: thin solid silver;
background: white;
}

Because we're using the default sam skin, we should begin the selector with the yui-skin-sam class name then the class name of the calendar container and finally that of the month and year. Other elements of the calendar, such as the navigation arrows, can easily be styled in this way. Using a DOM explorer to expose the names of other parts of the calendar is also an easy way to change other elements of the calendar. Our calendar should now appear like this:

Note

We should never change the original YUI files.

Changing the YUI files may seem harmless at first, but when a new version is released we find ourselves desperately trying to locate the changes we made in the old version to apply them to the new one, or we have to forgo updating. Besides, we preclude ourselves from using the CDNs to load the library files. There is always a way to override—as we just did—redefine or subclass the original CSS styles or JavaScript objects in our own, separate application code.

The DateMath class

In addition to the two classes catering for two different types of calendar, a class, YAHOO.widget.DateMath, defines a series of utilities for performing simple mathematical calculations or comparisons on dates. It has only a small number of static properties and a small set of methods. There are no events defined in this class and no configuration attributes. It is very much like JavaScript's own Math class that you can use without creating an instance.

All of its methods return either a Boolean value indicating whether the comparison was true or false, or a modified date object. Some of them will be used very frequently, while others will be used only rarely (but are still very useful).

Our date of birth calendar isn't really appropriate for seeing how the DateMath calls can be used. In order to examine some of the available methods, we should create a new calendar. In a blank page of your text editor, begin with the following HTML:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>YUI MathDate Class Example</title>
<link rel="stylesheet"
type="text/css"
href="yui/build/calendar/assets/skins/sam/calendar.css">
<script type="text/javascript"
src="yui/build/yahoo-dom-event/yahoo-dom-event.js">
</script>
<script type="text/javascript"
src="yui/build/calendar/calendar-min.js">
</script>
</head>
<body class="yui-skin-sam">
<div id="mycal"></div>
<div id="results"></div>
</body>
</html>

This very simple page will form the basis of our example. It looks very much like the previous example; in fact, all our examples will look pretty much the same, so, from now on, we'll only point out the components we'll need to include—and we already know the many alternative ways of fetching them—the HTML that goes in the body and the script that always goes right before the closing </body> tag.

Formerly, the DateMath class was only available along the Calendar Control, whether you meant to show a calendar or not. Now, it can be loaded separately, but we will use the Calendar in this example so we load the bundle.

Next, add the following <script> tag to the <body> tag of the page, directly below the results <div> tag:

<script type="text/javascript">
// create the sandbox when the DOM is ready
YAHOO.util.Event.onDOMReady(function() {
// shortcuts
var Dom = YAHOO.util.Dom, Calendar = YAHOO.widget.Calendar, DateMath = YAHOO.widget.DateMath;
});
</script>

As usual, we wait until the DOM is ready and then we create our sandbox. Within it, we create our shortcuts. Instead of the generic ones, we create shortcuts for the classes we will use in this example. Inside of our sandbox, we add:

//create the calendar object, specifying the container
var myCal = new Calendar("mycal");
//draw the calendar on screen
myCal.render();
//we will find out things about today's date,
// which we get from the Calendar control.
var today = myCal.today;

We create the calendar in the same way as in the previous example and render it on the page. This time, we don't need to worry about hiding it again as it will be a permanent fixture of the page. As we do some math on today's date, we read it from the calendar and keep it handy. We keep adding:

//we will pile up the results here:
var results = "";
// ** Our code will go here **
//insert the results into the page
Dom.get("results").innerHTML = results;

Performance analysis still shows that inserting HTML markup into the innerHTML property of a DOM element is, by far, faster than creating and appending DOM elements one by one. So, we create a variable to hold our results and then insert it into the container we created for them.

We won't have much user interaction with the Calendar Control, but we will use several of its tables of strings to assemble our results. Insert the following code where indicated above:

//get and display today's date
var dayNum = today.getDay(),
dayString = myCal.Locale.WEEKDAYS_LONG[dayNum],
date = today.getDate(),
monthNum = today.getMonth(),
monthString = myCal.Locale.MONTHS_LONG[monthNum],
year = today.getFullYear();
//put them all together
results += "<p>Today is " + dayString + ", " + date + " " + monthString + " " + year + "<\/p>";

Once we have this, we can get references to the date and month numerical representations and from these we can get the full day name and month name using Locale.WEEKDAYS_LONG[dayNum] and Locale.MONTHS_LONG[monthNum].

The Locale object is automatically created by the control and contains localized day and month names. It is primarily used to add new locales and specify alternative day and month names. English is available by default so we can simply read the properties and pull out what we want.

We can see some all-uppercase property names in this code, a naming convention usually reserved for constants. JavaScript has no constants, every variable can be changed; however, we use this convention to indicate our intent: these variables are not meant to be changed in application code. In this case, we would change them if we added other locales, but that would be customizing the library. Our application code would never change them.

Another naming convention worth mentioning is that of variables or functions starting with an underscore. Those are meant to be private members. JavaScript has no provision for private members so using the underscore is the way for the developer to tell everybody to stay away. There are many reasons for the developer to do it and a big one for you to stay away from them: they are not part of the contract; if the developer finds a better way to do things, private variables might suddenly disappear. Many developers find those variables through a debugger and use them. That is not a good idea; there will always be a public, safe way of achieving the same.

Once we have the information we need, it is simple enough to concatenate everything into our result string. Your page should look similar to the following screenshot:

Now we can have some fun with a few of the DateMath methods. First, add the following directly beneath our last block of code:

//work out date in 10 days time
DataMath classDataMath classmethodsvar futureDate = DateMath.add(today, DateMath.DAY, 10);
results += "<p>In ten days time it will be " + futureDate + "<\/p>";

We can use the .add() method of the YAHOO.widget.DateMath class to add a specified amount of time to a date object. The .add() method takes three arguments. The first is the date object on which the addition should be carried out, the second is one of the built-in constants representing the unit to be added (which could be days, weeks, months, or years), and the final argument is the actual amount to be added.

For the purposes of this example, I have left the futureDate field in full UTC format, but we could easily extract just the parts of the date that we want, just as we did to get the today's date.

Let's now look at the almost identical .subtract() method. Add the following code:

//work out date two months ago
var pastDate = DateMath.subtract(today, DateMath.MONTH, 2);
results += "<p>Two months ago the date was " + pastDate + "<\/p>";

You can see how easy the DateMath class makes addition and subtraction of date objects. The class has other useful methods such as the .getDayOffset() and .getWeekNumber() methods. We can expose the functionality of these two methods with the following code:

//work out day and week numbers of current date
var numberOfDays = DateMath.getDayOffset(today, year);
results += "<p>" + numberOfDays + " days have elapsed so far this year<\/p>";
var weekNumber = DateMath.getWeekNumber(today);
results += "<p>We are in week number "+ weekNumber + "<\/p>";

Save the file as datemath.html and view it in your browser of choice:

 

Summary


During the course of this chapter we have taken an in-depth view into what the YUI is, where it came from, and the things that spurred it into existence. We have seen everything that the license gives us permission to do and investigated the different ways of serving the files that power it. We've also looked at who can make the most of the library, how to install it, and how to use it in your own web pages.

Lastly, we finished off all the theory with a practical example that had you creating and customizing your first user interface control: a calendar, and working with one of its supporting classes: the DateMath class. I hope that this first example has made you eager to experiment with the library further and has shown you how easy it is to implement YUI components.

About the Authors

  • Daniel Barreiro

    Daniel Barreiro, screen-name Satyam, has been a very active member in the YUI forums, providing support, writing articles in the YUI Blog, and maintaining examples and further articles in his own site. A YUI Contributor, he is one of the few external developers to have a component included in the YUI 2 library.

    Browse publications by this author
  • Dan Wellman

    Dan Wellman is an author and frontend engineer living on the South Coast of the UK and working in London. By day he works for Skype and has a blast writing application-grade JavaScript. By night he writes books and tutorials focused mainly on frontend web development. He is also a staff writer for the Tuts+ arm of the Envato network, and occasionally writes for .Net magazine. He's the proud father of four amazing children, and the grateful husband of a wonderful wife.

    Browse publications by this author
Book Title
Unlock this full book with a FREE 10-day trial
Start Free Trial