This document discusses hidden gems and features within the YUI JavaScript library. It begins by introducing the author as a Yahoo web developer and YUI enthusiast. The author then presents an analogy that viewing YUI APIs from a gamer's perspective reveals hidden features, just as exploring a game world might reveal secrets.
The document is structured to guide the reader through progressively less hidden areas of YUI, from "Deeply Hidden" techniques to features "Hiding in Plain Sight." It provides examples of useful but obscure methods like Y.extend(), Y.augment(), and Y.stamp(). Other highlighted features include Y.Frame for creating isolated environments, Y.DOM.inViewportRegion for lazy loading, and event handlers
28. Deeply Hidden – first batch
Y.augment()
varFoo=function(){
/** special foo code **/
}
Y.augment(Foo,Y.EventTarget);
varfoo=newFoo();
// foo has EventTarget functionality
29. Deeply Hidden – first batch
Y.merge()
var one = {apple: "mac"}
var two = {pc: "ibm", handheld:"palm"}
var three= {pc: "dell"}
var res =Y.merge(one,two,three);
Y.log(res);
//> {apple:”mac”,handheld:”palm”,pc:”dell”}
30. Deeply Hidden – first batch
Y.mix()
varDuh=function(){
/** static stuff so I cannot extend **/
}
varYeah=function(){
/** new functionality I need **/
}
Y.mix(Duh,Yeah);
// Duh has Yeah’s functionality
// like Y.extend only for any object
31. Deeply Hidden – first batch
Phew! Now to less esoteric stuff…
33. Deeply Hidden – second batch
Y.stamp()
// set id’s for all links
Y.all("a").each(function(){
varsId=Y.stamp(this);
if(!this.get("id")){
this.set("id", sId);
}
});
// safe to run this 2X times – wont
// change ID’s
37. Deeply Hidden – second batch
Node.getData() / Node.setData()
// kinda like stamp() only you set the value
// <div id=“foo” class=“bar”></div>
Y.one("#foo").setData("info", {name:'foo'});
//now get the dom node some other way
Y.log(Y.one(".bar").getData("info").name);
//>foo
// data is not stored in the DOM of the element
55. Near the Surface
Y.DOM.inViewportRegion
var watcher =Y.one("#footer");
if (Y.DOM.inViewportRegion(
Y.Node.getDOMNode(watcher), false, null)) {
Y.log("in viewport!");
}
// only checks 1x time. You need to poll
// or check during scroll event
// can check for partial or whole element
// in viewport
56. Near the Surface
• Y.Frame
• Y.DOM.inViewportRegion
• Y.substitute / Y.Lang.sub
58. Y.Substitute / Y.Lang.Sub
• Useful for templating like Mustache.js
• Does {placeholder} substitution on a
string.
59. Y.Substitute / Y.Lang.Sub
• Useful for templating like Mustache.js
• Does {placeholder} substitution on a
string.
• Uses JSON object with keys
60. Y.Substitute / Y.Lang.Sub
• Useful for templating like Mustache.js
• Does {placeholder} substitution on a
string.
• Uses JSON object with keys
• Usually just use Y.Lang.sub() for simple
substitution
61. Near the Surface
Y.Substitute
var temp ="Hello, {who}!";
varobj= {who: "World"};
var greeting =Y.substitute(temp,obj);
Y.log(greeting);
// > Hello, World!
// great for making HTML templates
62. Near the Surface
• Y.Frame
• Y.DOM.inViewportRegion
• Y.substitute / Y.Lang.sub
• Y.QueryString
79. Hiding in Plain Sight
Y.Later
var time =60;
var display =Y.one('#timer');
functiondec(){
time -=1;
Y.one('#timer').setContent(time+
' seconds left');
}
var fuse = Y.later(1000,Y.one('body'),dec, null,true);
80. So far so good?
• Deeply Hidden
• Just Beneath the Surface
• Hiding in Plain Sight
81. Next up:
• Deeply Hidden
• Just Beneath the Surface
• Hiding in Plain Sight
• Future Levels
92. Your Quest…
• Get the basics down (Y.Base, Y.Widget)
• Explore the Gallery
(http://yuilibrary.com/gallery/ )
93. Your Quest…
• Get the basics down (Y.Base, Y.Widget)
• Explore the Gallery
(http://yuilibrary.com/gallery/ )
• Have an attitude of discovery
94. Your Quest…
• Get the basics down (Y.Base, Y.Widget)
• Explore the Gallery
(http://yuilibrary.com/gallery/ )
• Have an attitude of discovery
• Have fun! (Try new things)
95. Your Quest…
• Get the basics down (Y.Base, Y.Widget)
• Explore the Gallery
(http://yuilibrary.com/gallery/ )
• Have an attitude of discovery
• Have fun! (Try new things)
• Share your Gems (@triptych)
97. Credits
• YUI Team – killer codebase
• Anthony Pipkin – great ideas
• Ryan Grove – code formatting tips
• Internet – pretty pictures
• Game developers – for making worlds
Hi everyone, I’d like to welcome you to the talk “YUI Hidden Gems”.
Who am I? My name is Andrew Wooldridge
I’m a Web Developer here at Yahoo! I’ve worked here for over 4 years, with a few years break in between. So I’m a bit of a boomerang Yahoo! I have worked on such teams as the Games Team, Yahoo Buzz, and where I am now – Yahoo Search.
Over the course of those years I’ve become a total YUI Enthusiast. I worked at Yahoo in the early days of YUI, and I remember making the case with my team at the time for moving our existing codebase to YUI. I also helped create one of the first AJAX driven sites at Yahoo called Instant Search. It would update your search results in realtime as you type, predating Google’s implementation by many years.
I’m also a gamer. I’ve been playing games since the days of Pac-Man and Asteroids, and I’ve owned just about every kind of game console that you can imagine, although my kids seem to have taken over that job.
You may be asking “why mention gaming?” After all this is a YUI conference, not a game developer convention.
I’m talking about it because I want to give you some insight about how I approach things – especially when it comes to being a Front End Engineer, and dealing with YUI.
Since you’re at a YUI conference, you’ve most likely have spent a lot of time looking over the YUI apis. To you this might look like something like this:
Not too exciting, right?
But coming from a gamer perspective, I see YUI in a much different way.
To me, YUI is like an adventure game, where the developers have built up this complex, amazing world, and I get to explore it to find things that are useful to me in my projects.
So, if you look at YUI though the eyes of a gamer, this presentation may look something like this.
YUI HIDDEN GEMS! Press Start! [Pause.. ] Tastefully done in HTML and CSS3 and a few custom fonts. ( Source: http://bit.ly/tkwa1o)
The best analogy I can come up with is this- think about learning YUI as you might approach a game like Minecraft. I don’t know if you’ve ever played this game before, but it is unique in that there’s no set goals up front. You start off knowing virtually nothing about the world you are exploring, but you’ve been given some tips about how to start, and you use those to shape the world around you. You discover as you “dig deeper” that there are hidden gems that will greatly benefit your experience. You also learn how to take basic elements and combine them in interesting ways. This same kind of strategy will serve you well as you learn more about YUI.
So, with that in mind, here’s how we’ll proceed. I have spent a lot of time digging around YUI, and I’ve come up with a collection of features that aren’t really emphasized on the main YUI site. They are most likely things you wouldn’t encounter on your own at first, but they can really save you some time, and might even get you hooked on finding “hidden” features yourself. Carrying the Minecraft analogy forward we’ll start out with:
Deeply Hidden gems – items that are either pretty obscure, or fundamental to YUI, But it’s kinda taken for granted that you already know they exist.
Then we’ll ascent to Just Beneath the Surface. These are gems that a bit more focused on specific tasks, but are nevertheless very useful and good to know.
And then we’ll lift ourselves up further from the depths to elements “hiding in plain sight” that are fairly simple and obvious once you see them, but again are not talked about much on the YUI site, outside of being listed in the API docs.
From there we’ll explore some future levels – which represent features of YUI that are still in active early development. But they are already very useful and interesting to explore. The fact that you can try these out already on the YUI site really illustrates one of the strengths of YUI. They are not only open source, but also open development. Early features are released in beta form and give the community a chance to help shape their development.
Finally, like any adventure game, we’ll end our discussion by sending you off on your own quest. With a few tips as to how to proceed.
So, let’s get started.
We begin our journey deep inside the core of YUI, with some methods that are fundamental to the way YUI works, and are heavily used by the library itself to build components, modules, plugins, and virtually every aspect of the library.
Our first batch of elements include Y.extend()
Y.augment
Y.merge
And Y.mix. These methods are often talked about together as a group, because they all deal with core functionality within YUI. But there’s nothing preventing you from taking advantage of these methods for your own code as well. This is one of the great things about YUI. Not only does it have a lot of bells and whistles, and offer abstractions to many basic javascript functions, it also is a model for best practices as a web developer. Virtually every aspect of YUI is tightly self-integrated and lower level methods are used to build more complex functionality.
Y.Extend is used to create class hierarchies. Essentially this gives you a powerful tool to allow you to create classes and subclasses which inherit the properties and methods of their superclass. You’ll find many examples of this in the YUI codebase, and it allows you to organize your own javascript functionality as well in a similar fashion. One thing to note that Extend creates vertical hierarchies, and any subclass is considered to be an instance of the superclass as well, unlike Augment, which we will discuss next.
Y.Augment is a way of packaging up functionality that could be useful to many different classes and follows a composition-style class architecture. From a game perspective you might imagine Augment is a way of equipping your “character” or your “class” in this case, with additional functionality, but it does not change the core nature of that class nor creates subclasses. Another benefit of this approach is augment doesn’t build the added on methods until they are actually used for the first time, saving memory. I refer you to Luke’s awesome presentation from yesterday if you want more details.
I looked for an easy way to compare these two, but really the YUI site has a great way of representing the differences between these two methods. Again, for more details, check out Luke’s presentation video.
Y.Merge is a bit different from Augment or Extend. It’s not necessarily meant to deal with classes but rather offers a great way to merge together two different javascript objects. Instead of you having to do a FOR IN call to some object, and then manually setting new properties in another object, this method allows you to cleanly combine two or more data sets. You can decide how deeply to copy objects and there are other settings you can learn about on the YUI website. Note in this example how the PC property is overwritten by the existence of a second value. Later properties of the same name will override earlier ones.
One more to go in our first batch! Y.mix handles the case when you want to add functionality to static classes such as elements in the DOM. You cannot instantiate them or extend them via prototypes, so this allows you to get around that and treat the object as if it were extensible as a class. Mix is like Augment only more versatile. In fact Augment uses Mix under the hood.
Whew! We’ve made it this far and we’re still alive. Now we can get to less esoteric things – but I wanted to talk about those methods first, because they are classic examples of “hidden” gems. They are primarily used within YUI to build up its own class hierarchies, and merge data sets, but there’s nothing preventing you from taking advantage of these in your own code as well. It fact it’s highly encouraged. Note that none of these things are purposefully “hidden”, they are just kinda taken for granted that you are aware of them..
Let’s look at our second batch of Deeply Hidden YUI gems. They are not necessarily presented together as the previous group are, so we’ll cover them one at a time. Y.stamp is an interesting method that generates a GUID. That is essentially a unique string of characters that can be used to uniquely identify an element on a web page. YUI uses this stamping internally as well, but this is a great way to quickly identify dynamically generated code for instance. When you call Y.Stamp YUI looks to see if a GUID has already been created for this element. If so, it just returns that GUID, but if not, it’ll generate one on the spot for you and return that. So in essence you are ‘stamping’ the object, and you don’t have to worry about whether you’ve already stamped it in the past.
Here’s an example using Y.stamp. Say we have a web service that has returned a set of search results and we have rendered them on the page already. We may want to set up some click tracking on the page, and want to make sure that every link has a unique id. This method allows you to gather up all the links, check if they have an id, and if not, assign one via stamp.
Our next Hidden Gem is Y.UA - otherwise known as User Agent. I suspect this method is so carefully hidden because – like I said – YUI wants to teach you best practices as a web developer and Y.UA can be a bit of a crutch. Essentially it runs some tests inside the browser and extracts things like the browser’s User Agent string, whether you are using Webkit, or IE, or what OS you are using.
Here’s a quick example. I like that YUI – while hiding this functionality in a simple api call, still recognizes that there might be some reason you need to know that your browser is on say a mobile device. And you need a unified way to get to that information. In reality you should always use feature detection instead of browser detection, especially now that browsers are updating their versions on almost a daily basis.
Our next Gem is one of my favorites. Node.getData and Node.setData allow you to use a node as if it were a unique key into a object store on your website. Traditionally, if you wanted to associate some data with a dom node, you’d either set a custom attribute on that node, or you might have to artificially assign an ID and create some kind of javascript hash table or something to keep track of those changes. Node.getData and setData do all that work for you, and they don’t pollute the DOM with arbitrary html attributes that might mess up older browsers or expose information via dom inspector.
Here’s a quick example that illustrates what you can do. You can even store multiple sets of data, say json objects, and namespace them with keys so that you don’t inadvertently clobber someone else’s data sets on the same dom node. Why would you even do this? You might imagine a case where you have a number of images on a page, and you want to keep metadata about them – like their file size, geolocation, and dimensions. You might do this with getdata and setdata and build a script that allows you to view that metadata when you hover over the image.
Or next Gem comes from a discovery I made when I was working on a iframe-based widget for a project at my workplace. I needed to be able to have two different instances of YUI talk to one another across their sandboxes, and I was directed to Y.Global. Y.Global is a place where page-level events will bubble up to, and represents a common object that you can refer to no matter what YUI instance you are currently within.
Here’s an example usingY.Global to allow one instance of YUI to listen for a custom event that was triggered inside of another instance. You basically use the same event methods you might use on a Node, but you invoke them from the Global object.
So we’ve talked about a second batch of “deeply hidden” gems. Y.stamp for creating GUID’s, Y.UA for getting information about the browser, Node.getData which allows you to store data about a Node without impacting your markup, and Y.Global which allows you to pass messages between YUI instances.
Now we have enough experience to level up to our next batch of Gems.
Our next set of Gems are more Near the Surface. They are more specialized in their use and have a bit more of a narrow focus in their application. You might not end up using these every day, but when you do need them, they are great time savers.
The first of these is Y.Frame.
Y.Frame is actually part of the Editor module created by Dav Glass, if you look at the api documentation. It was created as a helper class for the YUI Editor module, which uses an iframe to isolate editing functionality from the rest of the page it is embedded in.
It is a wrapper class for a HTML Iframe and can load content from the current page or from a remote script.
It also creates a seconf YUI instance on the page that is bound to that new window and document created inside the iframe.
This setup allows you to pass information between the iframe and the host page. You can modify the dom of the inner frame, load CSS and YUI components into it, as well as listen for events that you could pass up into the host page. It’s very versatile and is an excellent example of YUI’s approach to building components. Dav could have just created some code that generates an iframe inside his editor component and keep all that functionality local to the Editor component. Instead, he used YUI’s component framework to build something that any other class in YUI could use – with exposed methods and properties. This is really one of the key reasons why I think YUI is superior to other javascript libraries. They have designed YUI to allow you to naturally build additional functionality that meshes perfectly with their own code hierarchy.
Here’s an example that creates a Frame instance and loads some content into it. Note how you can easily load YUI components into the iframe document as well as style the inner page. The container property refers to the DOM element that this iframe will be appended to.
Using the events system which we get because frame extends from Y.Base, we can listen for the “ready” custom event. This will be triggered when all of the content within the iframe is loaded and the iframe is ready to use. We then can call getInstance() which will give us the inner frame DOM, and we can manipulate it just like the host DOM via YUI. What I really like about Y.Frame is that it was built to service the Editor module, but YUI’s extensible framework allows anyone else to use it as well by itself.
After Y.Frame we have Y.DOM.inViewportRegion.
Here is another example of a component that most likely was built to solve a specific problem, but has uses far beyond its origins. There is a utility called ImageLoader which allows you to delay the loading of images on a web page until they are scrolled into view. inViewportRegion is the method ImageLoader uses to make this determination.
Even though it’s used in Imageloader, it actually lives in the DOM module.
I think because of where is exists in the codbase, it doesn’t take a YUI Node like you might expect. Instead you need to pass it a true HTML DOM node. This was something that tripped me up when I first tried it out, so be forewarned.
While ImageLoader takes advantage of this method, it’s also perfect for anyone else who wants to lazy load content. For instance you might delay loading a flash player that might effect the performance of your page until the user scrolls down to see it, or you might use it to see if a top navigational menu has scrolled offscreen and present a different floating menu that follows the user as they scroll.
Here’s an example using Y.DOM.inViewportRegion. Note that you’ll have to call it every time your interface updates – say by polling or through listening to the scroll event.
Our next gem is called Y.substitute or also Y.Lang.sub.
Y.Substitute is a method that deals with the case where you might want to have a template that you reuse based on the data you might get from some datasource. If you’ve ever used a library like Mustache.js, then you’ll be familiar with this method.
It works by looking for placeholders inside a string wrapped by brackets,
and replacing those with the matching value in a json object.
Y.Substitute has all kinds of bells and whistles which allow you to do sophisticated string manipulation, but in the simplest case where you just want a json object to populate a string, you’ll use Y.Lang.Sub.
In this example we take a simple string containing the “who” placeholder and replacing it with the value of “who” in the json object. This method is perfect for creating HTML templates that you could use when building a new YUI component or widget. One use case might be to create a wordpress clone in YUI or building a View in a MVC framework.
Our next method is Y.QueryString.
Y.QueryString is a Utility module that deals with URL query strings. It’s an example of a Utility that encapsulates a common task many web developers have to deal with, and saves you the time and effort of writing your own parser.
Essentially it will take a javascript object and convert it into a query string and vice versa.
Parse is the method to convert a string into a js object.
And Stringify will convert an object into a querystring. There is an equivalent Class called Y.JSON which will do the same only for the JSON format.
Querystring is perfect for creating urls that need parameters passed say as a Get request.
Here’s an example usingY.QueryString. Notice how it will coerce boolean values from true/false into 1/0 when it converts it into the query string.
And here’s an example using the parse method. Again this is a great way to harvest information from a url – for instance you might pass parameters to a dynamic web application via the query string, and you could use this to parse them out and pass them into your application
So, let’s recap. We have Y.Frame to create a YUI abstraction around iframes, we have inViewportRegion to potentially lazy load page elements, we have Y.substitute for templating, and we have Y.Querystring to parse and create URL querystrings.
Our experience points have increased again, so it’s time to Level up!
Our next batch of Gems are even more specialized and fairly easy to find, now that we have gotten really good at finding them.
As a web developer you’ve probably run into a need for this next gem pretty often. You want to do something when the user mouses over a link and undo it when they mouse out. You could use a combination of mouseover and mouseout for this, but in reality those events often get called too aggressively within complicated elements in a document. YUI also has event handlers for mouseenter and mouseleave – which are abstractions for what you wish mouseover and mouseout would really do, however YUI does this one better by giving you a shorthand event called “hover” which takes two methods – one for the hover over aspect and one for the hover out.
Here’s our example. Note how we need to tell the YUI instance to load “event-hover” in order to get this additional functionality. This shows us another strength of YUI. Using the Loader, we are able to factor out functionality that not everyone needs in the basic case, but still allow them to take advantage of it when they need it. If you never need hover and mouseover/mouseout works for you, you never have to load the unnecessary code to do this.
Next we have outside events. This is an example of functionality contributed by someone outside of the YUI team – Brett Stimmerman who originally created this as a gallery module “gallery outside events”. It started out in the Gallery and eventually was deemed useful enough to be brought into the core YUI.
Outside events allow an element to respond to an event somewhere else in the DOM – as long as its not inside this element. A great example of this might be when you are viewing a zoomed in image in a slide show, and you want to have a “click anywhere else” to dismiss the image.
Here’s a list of the pre-defined events you can set as “outside” and you can even define your own synthetic events using YUI’s custom event system.
Next, we have Y.Later. Y.Later wraps up a combination of setTimeout and setInterval in a cross browser method.
Since this is one of our Plain Sight Gems, you might this this is pretty obvious stuff, but I really like how YUI simplifies the way you deal with timers and takes care of function scoping issues. In this example we count down from 60 and display the results each second.
So, we’ve made it out of the depths. We’ve emerged on the surface and we’ve found some gems hiding in plain sight.
Now it’s time to look at Future Levels. These are gems that are in Beta and represent some of the amazing new features being built with YUI. The picture you see here is of an experimental new animal in Minecraft. It’s there, but not quite finished. It’s a great analogy to the new YUI features.
Just like minecraft, YUI is always growing and changing. The Graphics component gives you a javascriptapi for creating images that leverage a browser’s capabilities such as SVG, Canvas and VML.
Here’s some examples – which you’ve probably already seen in previous talks. The fact that we can get images with such high fidelity and sophistication really speaks to the hard work this team is putting into this. Also note that the Graphics Utility underlies the Charts Widget as well.
Next we have the beginnings of an MVC framework built into YUI.
This is another example of how YUI looks at best practices on the web and incorporates them into it’s own library. Leveraging its own component and event infrastructure this framework takes its inspiration from such projects as backbone js.
Next up, we have the Transition Utility.
Transition is an interesting adaptation by the YUI team to take what it has learned about animation, and apply it to native CSS3 transitions. It’s also nice in that it allows you to use these transitions in way that supports graceful degredation. If the browser has CSS3 transitions, YUI takes advantage of them, but if not, it fails over to Animation so you can get an equivalent experience.