YUI 3 Quick Tip: Adding Your Own Awesome

September 29, 2010 at 12:22 pm by Eric Miraglia | In Development | 3 Comments

Luke (@ls_n) posted this snippet in response to a question the other day, and I thought it was worth sharing here as a quick tip.

As with most selector-based idioms, a lot of YUI 3′s expressive power comes from what you can do once you have reference to one or more HTMLElements — in YUI 3, that means having a Node reference, which you usually get via Y.one(selector string) or Y.all(selector string). So, Y.one("#foo").doSomethingInteresting is a common pattern.

It’s easy to extend YUI 3′s expressiveness by adding your own magic to Node (and/or NodeList). Here’s one way to make your extension modular and reusable.

First, create a new custom module (we’ll call it node++):

YUI.add('node++', function (Y) {
	
	//define a function that will run in the context of a
	//Node instance:
	function doSomethingAwesome() {
		Y.log("Do something awesome here.");
	}

	//use addMethod to add doAwesomeThing to the Node prototype:
	Y.Node.addMethod("doAwesomeThing", doSomethingAwesome);
	
	//extend this functionality to NodeLists:
	Y.NodeList.importMethod(Y.Node.prototype, "doAwesomeThing");
	
}, '0.0.1', { requires: ['node'] });

Luke’s gist is here.

With that definition on the page, node++ can be used in any instance. In your implementation code, you would do:

YUI().use('node++', function (Y) {
	
	//use from a single Node:
        Y.one('#foo').doAwesomeThing();

	//use from a NodeList:
	Y.all('p').doAwesomeThing();
	
});

Note that only the YUI instance(s) to which you bind your node++ module will have access to doAwesomeThing. One feature of this design that you’ll like as you build complex apps is that your implementation logic won’t need to change if the dependency list for node++ evolves — that will get handled for you automatically at use() time, and the dependency declaration stays with the code to which it pertains.

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

YUI Theater — Dav Glass: “Using Node.js and YUI 3″ (36 min.)

September 29, 2010 at 11:34 am by Eric Miraglia | In YUI Theater | 11 Comments

Dav Glass speaks about YUI 3 and Node.js at Yahoo on September 16, 2010.

Ryan Dahl’s work on Node.js — and the community forming around that project — has joined HTML5 as one of the big stories of 2010. YUI engineer Dav Glass has been working to make YUI 3 a powerful ally for Node.js implementers, and in this video he shows you what he’s done so far — including demos of progressively enhanced widgets running the same code on client and server. Don’t miss this one.

If the video embed below doesn’t show up correctly in your RSS reader, click through to watch or download the high-resolution version of the video on YUI Theater.

Other Recent YUI Theater Videos:

  • Alois Reitbauer: dynaTrace Ajax Edition — dynaTrace provides one of the most powerful tools for analyzing the performance of web applications in Internet Explorer. In this talk, dynaTrace engineer Alois Reitbauer walks through four specific analytic scenarios using the dynaTrace interface.
  • Ryan Grove: Achieving Performance Zen with YUI 3 — Following codified guidelines can help you build fast websites, but building applications that are clean, fast and extensible also involves taking a balanced approach to performance at every level of your F2E work. YUI 3 is designed to help you in this process, providing a right-sized abstraction layer with built-in performance magic and a variety of tools that make fast frontend code easy and fun to produce. In this session, we’ll explore the zen of performant JavaScript in the YUI 3 world and introduce you to some of the powerful tools YUI 3 puts at your disposal in every app you write.
  • Douglas Crockford: Crockford on JavaScript — Scene 6: Loopage — Software development is hampered by a specific set of design mistakes that were made in the first programming languages and repeated in everything that has been done since. And, somewhat miraculously, JavaScript is going to make it right, radically transforming the way we write applications. Again. In the Loop of History, it has all happened before, but it has never happened like this. This is why you should care about the emergence of server-side JavaScript and the excitement around projects like Node.js – not because they’re at the sharp end of a trend, but because they’re paving the road toward the next big revolution in software.

Subscribing to YUI Theater:

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

Implementation Focus: Car Rental Express

September 28, 2010 at 6:01 am by Stefan Klopp | In In the Wild, YUI Implementations | 2 Comments

About the author: Stefan Klopp is the Director of Development for ExpressITech, the parent company of Car Rental Express. Stefan has been developing highly usable web solutions for the car rental industry in various roles over the last 6 years. He currently lives and works in Vancouver, British Columbia, Canada.

Car Rental Express is the leading independent car rental comparison website on the Internet. It lets users rent cars online in more than 1000 cities and airports around the world.

Our user base is largely non-technical, which means they want to compare prices and rent cars as easily as possible. With the relaunch of our website in June of 2010 we have implemented many components of YUI 2 to help provide our customers with an intuitive experience.

Which YUI components are we using?

The components that we’ve been using include Connection Manager, AutoComplete, DataSource, Calendar, Animation, JSON, and Container.

Why we chose YUI

When reviewing the different JavaScript libraries that we could potentially use on Car Rental Express, we found that the YUI was the most complete for our needs. The biggest selling features for us was the very modular approach the YUI took to implement different design patterns, as well as the robust documentation and examples they provided. From a development standpoint this led to rapid development of our application without having to struggle with a library.

How we use YUI

We utilize the YUI in a number of ways. Our 4 most used components are AutoComplete, Calendar, Container, and Connection Manager. Here are some of the ways we use each of these components.

AutoComplete

The AutoComplete component is used extensively on our site to help users find a city or airport in which to rent a car. We really liked how easy it was to implement this component, and how quickly it responds. We cache search results server-side to help improve search results; however, having the client-side caching also helped tremendously in speeding up the response of the component. Another feature that we really took to was how easy the results were to style. When displaying the locations to the user this was crucial as we needed to identify which locations where found in cities and which were found at airports.

Calendar

The Calendar component is also used throughout the site when a renter is filling in dates to conduct a search. We are using a customized version of John Peloquin’s Interval Selection Calendar and displaying it in a YUI Dialog. Essentially what we wanted to do was give the renter a two-month view when choosing their dates, as well as visually show them what date range they currently have selected. Again, this was extremely straightforward to implement using YUI 2 Calendar, and it basically came down to creating a YUI Dialog, setting the body to contain a div for the Calendar, then attaching a YUI Interval Calendar to that div.

Containers

We utilize YUI Containers throughout our website in a number of different ways. In the example above we were using a Dialog to help us display the Interval Calendar when a user was selecting a date. On our rate search results page we make heavy use of Containers to give the renter more information on different aspects of the car rental agency and the vehicle they might potentially rent. Most of the containers on this page are Panels that we re-use for each different listing. For example, the vehicle display features Panel:

Things got a little more fun with the Renter Rated agency ratings. When displaying the ratings, we really wanted to focus the user’s attention to the scores an agency received and to display this information in a clean, easy-to-view way. By utilizing the Dialog Control we were able to constrain the viewport and center the dialog easily to help us achieve this goal. By setting a blank header and footer it made styling simple by just adding the appropriate styles to our CSS. The end result was a clean ratings container that provides the renter with the information they want.

Connection Manager

Connection Manager is used throughout the site whenever we need to pull data via a XHR request. In some of the examples above we utilize this component for requesting cities and airports for the AutoComplete implementaitons and pulling the rating information for the Renter Rated Dialog.

One interesting way we utilize Connection Manager is with our rental center block that sits on most pages. To help with performance we do a lot of full-page caching on many of our content pages. However, we still wanted to display the dynamic rental center block on these pages. This presented us with a problem we were able to solve with Connection Manager. Rather than having to break up our fully cached page and cache only aspects of the page we found it was easier to just include the rental center block via a simple asynchronous request. We found that this allowed us to retain the performance from having a fully cached page, yet still display dynamic content in our rental center box.

Final Thoughts

Overall we have been extremely happy with our choice to use YUI. It provides us with a modular library that is well documented, easy to use and implement.

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

In the YUI 3 Gallery: Matt Taylor’s RaphaelJS Module

September 27, 2010 at 1:05 pm by Matthew Taylor | In Development, YUI 3 Gallery | 9 Comments

Matt Taylor (@rhyolight, blog) works for Yahoo! on an internal browser-side JavaScript framework. He enjoys working with graphics, and he’s worked with drawings and animations before using Java2d libraries. Before moving to Silicon Valley to work for Yahoo!, Matt worked in the St. Louis area as a software contractor. He’s also worked extensively with Groovy and Grails technologies for SpringSource. He was the original lead programmer for the YUI2-based GrailsUI plugin for the Grails web framework.

RaphaelJS is a powerful JavaScript library that manages SVG drawings and animations. It allows you to easily create SVG canvases and draw basic shapes and paths very easily, even grouping them into sets and applying transformations to one or many vectors. You can draw shapes, manipulate images, and animate everything. RaphaelJS provides a nice API to create and modify SVG elements with ease.

While the library is impressive, but I’ve found that I can add some important features to elements of the RaphaelJS library with YUI3. I’ve started off these efforts with the new RaphaelJS Gallery Module.

Lazy Loading RaphaelJS and Plugins

The first feature is the lazy-loading of not only the RaphaelJS library, but any RaphaelJS plugins you might need. The RaphaelJS Gallery Module will only load these files when you declare you’ll be using them within a YUI sandbox. For example:

 
YUI({gallery: 'gallery-2010.09.22-20-15'}).use('gallery-raphael', function(Y) {
 
	Y.Raphael().use(function(Raphael) {
		
		// use Raphael here just like you would outside YUI
		var paper = Raphael('myPaper', 500, 500);
 
	});
 
});

If you are using RaphaelJS plugins, specify their paths in an array and send that as the first parameter in the Y.Raphael().use() function:

 
YUI({gallery: 'gallery-2010.09.22-20-15'}).use('gallery-raphael', function(Y) {
 
	var myPlugins = ['plugins/raphael.awesomePlugin.js', 'plugins/raphael.wickedPlugin.js'];
 
	Y.Raphael().use(myPlugins, function(Raphael) {
 
		// use Raphael here just like you would outside YUI
		var paper = Raphael('myPaper', 500, 500);
		// the 'paper' will have any new functions added by your plugins now
	});
 
});

The RaphaelJS library is loaded first, then any specified plugins are loaded before your callback function is executed with the Raphael object as the only parameter.

Custom Events

Once you’ve created a drawing space with the Raphael object, then you can immediately get down to the drawing. When you call methods like rect, circle, and path on the drawing space, you’ll receive back objects representing SVG vectors. Normally, you’ll have access to their corresponding DOM elements through the node property. For example:

 
var paper = Raphael('myPaper', 500, 500);
var square = paper.rect(0, 0, 100, 100);

This creates a rectangular vector object at coordinates [0,0] with a width and height of 100 pixels. You have access to the underlying DOM element (which is an SVG rect element) like so:

 
var rectNode = square.node;
rectNode.onclick = function() {
	alert('Congratulations, you clicked a square!');
};

If you are an avid YUI user, you’d probably like something more than this. How about a built in Y.Node as well? Just like the node property refers to the HTMLElement behind the SVG object, the $node property refers to the Y.Node wrapper for that element. So you can do things like this:

 
square.$node.on('mouseover', function() {
	alert('Congratulations, you can move a mouse!');
});

Let’s try something more complex now. An interaction with one vector should be able to cause other drawn vectors to update their styles, right? How about we create some bars that all render their colors dependent on where a the mouse is located on a circle on the page:

 
var paper = Raphael('rcanvas', 600, 800);
 
var circ = paper.circle(350, 200, 100).attr({fill: 'pink', stroke: 'black'});
 
// pushing a bunch of rectangles into an array
var i=0; rectangles = [];
for (; i<10; i++) {
	rectangles.push(paper.rect(0, 40*i, 200, 20).attr({fill: 'red', stroke: 'yellow'}));
}
 
// looping through the rectangles, adding specific circle mousemove handlers for each
Y.Array.each(rectangles, function(rect, index) {
	var i = index + 1;
	circ.$node.on('mousemove', function(evt) {
		// the fill color is dynamic, dependent on the location of this rectangle
		// in the array as well as the location of the mouse
		var lf = circ.attrs.cx - circ.attrs.r,
			rt = 2 * circ.attrs.r + lf,
			x = evt.clientX - lf,
			top = circ.attrs.cy - circ.attrs.r,
			btm = 2 * circ.attrs.r + top,
			y = evt.clientY - top;
			red = (((128 * x) / (2 * circ.attrs.r))-1) * i/6,
			green = 256 - ((((128 * x) / (2 * circ.attrs.r))-1) * i/6),
			blue = (((128 * y) / (2 * circ.attrs.r))-1) * i/6;
		rect.attr('fill', 'rgb(' + red + ', ' + green + ', ' + blue + ')');
	});
});

This example is running here, but as you can see in the snapshots below, the color of each bar is dependent on the mouse location over the circle as well as the order of the bar.



Depending on where your mouse cursor is located over the circle, the bar colors change individually.

So you can see that $node is a useful shortcut, but nothing spectacular. It would really be fantastic if each SVG object you create with RaphaelJS could fire custom events. That would allow your individual drawing elements to fire custom events, and anything on the page could listen and respond. This can be useful in many ways. For starters, it provides rich interactions between your drawings. User interactions with one vector can now notify any other vectors of the interaction on demand. This means you can programatically fire events from your drawings when certain conditions are met. Not only does this allow your drawings to notify other vectors, but anything on the page can listen in.

 
var paper = Raphael('rcanvas', 600, 800);
 
var circ = paper.circle(350, 200, 100).attr({fill: 'pink', stroke: 'black'});
 
// making arrays of rectangles and circles
var i=0, rectangles = [], circles = [];
for (; i<10; i++) {
	rectangles.push(paper.rect(0, 40*i, 40*i, 20).attr({fill: 'red', stroke: 'yellow'}));
	circles.push(paper.circle(0,0,20).hide());
}
Y.Array.each(rectangles, function(rect, index) {
	var i = index + 1;
	circ.$node.on('mousemove', function(evt) {
		var lf = circ.attrs.cx - circ.attrs.r,
			rt = 2 * circ.attrs.r + lf,
			x = evt.clientX - lf,
			top = circ.attrs.cy - circ.attrs.r,
			btm = 2 * circ.attrs.r + top,
			y = evt.clientY - top;
			newWidth = (((256 * x) / (2 * circ.attrs.r))-1) * i/6,
			red = (((128 * x) / (2 * circ.attrs.r))-1) * i/6,
			green = 256 - ((((128 * x) / (2 * circ.attrs.r))-1) * i/6),
			blue = (((128 * y) / (2 * circ.attrs.r))-1) * i/6;
		// this time, not only changing the color, but also the rectangle width
		rect.attr({
			width: newWidth,
			fill: 'rgb(' + red + ', ' + green + ', ' + blue + ')'
		});
		// firing custom event to notify that this rectangle width has changed
		rect.fire('width-changed', {width:newWidth, source: rect, order: index});
	});
	
	// each rectangle gets a listener that fires on width-changed
	rect.on('width-changed', function(evt) {
		var attrs = evt.source.attrs;
		// get the corresponding circle and move it to the right end of the rectangle
		circles[evt.order].attr({
			cx: attrs.x + attrs.width,
			cy: attrs.y,
			fill: 'cornflowerblue'
		}).show();
		
	});
	
});

Take a look at this running example here. You can also see from the snapshot below that circles are being drawn on the right ends of the rectangles. This is occuring in response to each individual rectangle’s custom event firing, being caught by a handler that moves the circle to a position relative to the current attributes of the rectangle.

This opens up some interesting possiblities for RaphaelJS within YUI3. For example, what if we could create a group of vector shapes with the group itself being the entity that fires events to the outside world? Internally, each vector drawing could communicate with its container via custom events, and the container would make decisions about what data it fires to the outside world. This opens up the idea of fully encapsulated, interactive SVG controls.

Summary

With the ascendance of HTML5 and its satellite technologies, there are so many more options other than Flash for rich interactions. Ideally, any vectored elements on the page should be fully accessible and standardized. This opens up wonderful possiblities for us to create accessible, standard web controls without resorting to Flash. SVG is an appealing option because every vector drawn on the page is backed up by a DOM node that we can modify with YUI just like any other DOM node. That’s what allows the RaphaelJS Gallery Module to augment all SVG objects being created by RaphaelJS, and that is a key to rich interaction with these elments from elsewhere on the page.

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

clearfix Reloaded + overflow:hidden Demystified

September 27, 2010 at 6:27 am by Thierry Koblentz | In CSS 101 | 12 Comments

About the author: Thierry Koblentz is a front-end engineer at Yahoo!
He owns TJK Design and ez-css.org. You can follow Thierry on Twitter at @thierrykoblentz
.

clearfix and overflow:hidden may be the two most popular techniques to clear floats without structural markup.

This short article is about enhancing the first method and shedding some light on the real meaning of the second.

clearfix

In everything you know about clearfix is wrong I explain the issues this method creates across browsers and I suggest to only use clearfix on elements that are not next to floats (e.g. a modal window), although as authors we still have to deal with collapsing margins. This demo page demonstrates the issue.

Margin-collapse behavior in the first two boxes shows that it is the generated (non-empty) content that keeps the bottom margin inside the box (which makes perfect sense according to spec).

So, to create the same box layout across browsers we can enhance the original method by generating content using both pseudo-elements :before and :after:

.clearfix:before,
.clearfix:after {
  content: ".";    
  display: block;    
  height: 0;    
  overflow: hidden;	
}
.clearfix:after {clear: both;}
.clearfix {zoom: 1;} /* IE < 8 */

Don’t simply replace your clearfix rules with these new ones in existing projects, though, as you may have already patched issues related to collapsing margins via other methods.

overflow

In most discussions about clearing floats the overflow:hidden method comes up, and it is always shot down by a "If you’re placing absolutely positioned elements inside the div, you’ll be cutting off these elements". But this is not necessary true. overflow:hidden will always clip relatively positioned elements, but it will not always hide absolutely positioned ones. This is because it all depends on the containing block:

10.1 Definition of “containing block”:

4. If the element has ‘position: absolute’, the containing block is established by the nearest ancestor with a ‘position’ of ‘absolute’, ‘relative’ or ‘fixed’, …

This means absolutely positioned elements will show outside of a box styled with overflow:hidden unless their containing block is the box itself or an element inside the said box.

You can check this demo page to see how things work.

Better alternatives

If you can apply a width to the element containing floats, then your best option is to use:

display: inline-block;
width: <any explicit value>;

Further reading

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

YUI: Open Hours Wed Sep 29th

September 24, 2010 at 1:50 pm by Luke Smith | In Development | 1 Comment

The next installment of YUI: Open Hours will be next Wednesday, the 29th.

YUI 3 Charts are coming in the next release, and a preview of some early work is already in the Gallery. Tripp Bridges will be on the call, introducing the new structure and showing how the learnings from YUI 2′s Charts package informed the new architecture, seeking that fine balance between flexibility and simplicity. Oh, and did I mention no Flash?

Also on deck will be Allen Rabinovich giving an update on the amazing work he’s been doing on the yuilibrary.com redesign. We’re talking everything, here: home page, user guides, demos, tutorials, API docs. The works. In many ways it’s a whole new story, and a much better one.

We’ll be online from 10am to 12pm PDT. The connection details are the same as usual.

  1. Dial in to 1-888-371-8922 (Skype works great for non-US participants*)
  2. Enter the attendee code 47188953#
  3. Join the screen sharing session (this will prompt you to install the Adobe Connect plugin if this is your first time using it)

And finally, the yuilibrary.com forum thread for this Open Hours is here. Look there for notes, interesting takeaways, and the recording of the call after it’s done. Or start the conversation off early by posting questions, suggestions for topics, or code that you’d like review.

Don’t forget to subscribe to the YUI Calendar and follow @yuilibrary on Twitter for the latest updates on Open Hours and other YUI interestingness.

Hope to see you there!

* – If Skype is not an option, email me for a local number.

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

In the Wild for September 24, 2010

September 24, 2010 at 1:00 pm by Eric Miraglia | In In the Wild | Comments Off

As we get ready for YUIConf 2010 and a lot more in the coming months, here are some of the other things we’ve taken note of in the larger YUI world:

Share and extend: Bookmark with del.icio.us | digg it! | reddit!

Next Page »
Hosted by Yahoo!

Copyright © 2006-2012 Yahoo! Inc. All rights reserved. Privacy Policy - Terms of Service

Powered by WordPress on Yahoo! Web Hosting.