custom yui widgets

38
Building interactive widgets with YUI Cyril Doussin Yahoo! EU Front-End Summit, Dec 2007

Upload: cyrildoussin

Post on 06-Dec-2014

11.698 views

Category:

Technology


0 download

DESCRIPTION

My presentation for the YAHOO! Europe Front-End Engineering Summit in December 2007.

TRANSCRIPT

Page 1: Custom YUI Widgets

Building interactive widgets with YUI

Cyril DoussinYahoo! EU Front-End Summit, Dec 2007

Page 2: Custom YUI Widgets

WarningsLots of code

/** * Returns the namespace specified and creates it if it doesn't exist * <pre> * YAHOO.namespace("property.package"); * YAHOO.namespace("YAHOO.property.package"); * </pre> * Either of the above would create YAHOO.property, then * YAHOO.property.package * * Be careful when naming packages. Reserved words may work in some browsers * and not others. For instance, the following will fail in Safari: * <pre> * YAHOO.namespace("really.long.nested.namespace"); * </pre> * This fails because "long" is a future reserved word in ECMAScript * * @method namespace * @static * @param {String*} arguments 1-n namespaces to create * @return {Object} A reference to the last namespace object created */YAHOO.namespace = function() { var a=arguments, o=null, i, j, d; for (i=0; i<a.length; i=i+1) { d=a[i].split("."); o=YAHOO;

// YAHOO is implied, so it is ignored if it is included for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) { o[d[j]]=o[d[j]] || {};

YAHOO.env.ua = function() { var o={

/** * Internet Explorer version number or 0. Example: 6 * @property ie * @type float */ ie:0,

/** * Opera version number or 0. Example: 9.2 * @property opera * @type float */ opera:0,

/** * Gecko engine revision number. Will evaluate to 1 if Gecko * is detected but the revision could not be found. Other browsers * will be 0. Example: 1.8 * <pre> * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7 * Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8 * Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8 * Firefox 3 alpha: 1.9a4 <-- Reports 1.9

YAHOO.env.ua = function() { var o={

/** * Internet Explorer version number or 0. Example: 6 * @property ie * @type float */ ie:0,

/** * Opera version number or 0. Example: 9.2 * @property opera * @type float */ opera:0,

/** * Gecko engine revision number. Will evaluate to 1 if Gecko * is detected but the revision could not be found. Other browsers * will be 0. Example: 1.8 * <pre> * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7 * Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8

Page 3: Custom YUI Widgets

Warnings(probably) Norm incompatible

Page 4: Custom YUI Widgets

Warningssoz

Page 5: Custom YUI Widgets

(some) YUI Goals

• Provide solid foundations:

• Patch up DOM API

• Do the hard work for you (CSS layouts, browser testing etc.)

• Avoid repeating yourself (reusable components)

• Make it simple: consistent design, good documentation

Page 6: Custom YUI Widgets

Javascript widgets

• Common need: enhance page functionality in an unobtrusive, accessible way

• ActiveX Flash Javascript is (most often) the appropriate way to do this

• nice to make this reusable on many pages/sites

Page 7: Custom YUI Widgets

YUI widgets

• Autocomplete

• Button

• Calendar

• Color Picker

• Container

• DataTable

• Logger

• Menu

• Rich Text Editor

• Slider

• TabView

• TreeView

Page 8: Custom YUI Widgets

YUI widgets

• Autocomplete

• Button

• Calendar

• Color Picker

• Container

• DataTable

• Logger

• Menu

• Rich Text Editor

• Slider

• TabView

• TreeView

Page 9: Custom YUI Widgets

YUI Container

“The Container family of components is designed to enable developers to create different kinds of content-containing modules on the web.”

“Module and Overlay are the most basic containers, and they can be used directly or extended to build custom containers.”

Page 10: Custom YUI Widgets

YUI ContainerModule

Overlay

SimpleDialog

Dialog

Tooltip Panel

Page 11: Custom YUI Widgets

YUI ContainerModule

Overlay

SimpleDialog

Dialog

Tooltip Panel

Your Control

Page 12: Custom YUI Widgets

YAHOO.widget.Module

• Common markup structure

• Customisation through Configuration

• Custom Events

• Utility functions

Page 13: Custom YUI Widgets

Our example:Contact List with pagination

Page 14: Custom YUI Widgets

Setting things up:Basic Markup

<h2>Contacts</h2><ol> <li> <dl> <dt>Name</dt> <dd>Ed Eliot</dd> <dt>Web site</dt> <dd><a href="http://www.ejeliot.com/">ejeliot.com</a></dd> </dl> </li> <li> <dl> <dt>Name</dt> <dd>Stuart Colville</dd> <dt>Web site</dt> <dd><a href="http://muffinresearch.co.uk/">Muffin Research Labs</a></dd> </dl> </li> <li> <dl> <dt>Name</dt> <dd>Ben Ward</dd> <dt>Web site</dt> <dd><a href="http://ben-ward.co.uk/">ben-ward.co.uk</a></dd> </dl> </li></ol>

Page 15: Custom YUI Widgets

Setting things up:Structured Markup

<div id="contact-list"> <div class="hd"> <h2>Contacts</h2> </div> <div class="bd"> <ol> <li> <dl> <dt>Name</dt> <dd>Ed Eliot</dd> <dt>Web site</dt> <dd><a href="http://www.ejeliot.com/">ejeliot.com</a></dd> </dl> </li> <li> <dl> <dt>Name</dt> <dd>Stuart Colville</dd> <dt>Web site</dt> <dd><a href="http://muffinresearch.co.uk/">Muffin Research Labs</a></dd> </dl> </li> <li> <!-- ... --> </li> </ol> </div> <div class="ft"></div></div>

Page 16: Custom YUI Widgets

Setting things up:

<div id="contact-list"> <div class="hd"> <h2>Contacts</h2> </div> <div class="bd"> <ol> <li> <dl> <dt>Name</dt> <dd>Ed Eliot</dd> <dt>Web site</dt> <dd><a href="http://www.ejeliot.com/">ejeliot.com</a></dd> </dl> </li> <li> <dl> <dt>Name</dt> <dd>Stuart Colville</dd> <dt>Web site</dt> <dd><a href="http://muffinresearch.co.uk/">Muffin Research Labs</a></dd> </dl> </li> <li> <!-- ... --> </li> </ol> </div> <div class="ft"></div></div>

Structured Markup

Page 17: Custom YUI Widgets

Setting things up:

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

dependencies• YAHOO

• YAHOO.util.Dom

• YAHOO.util.Event

• YAHOO.widget

• YAHOO.widget.Module<script type="text/javascript" src="http://yui.yahooapis.com/2.4.0/build/container/container-min.js"></script>

Page 18: Custom YUI Widgets

Setting things up:

YAHOO.Cyril.ContactList = function(el, userConfig) { YAHOO.Cyril.ContactList.superclass.constructor.call(this, el, userConfig);};YAHOO.extend(YAHOO.Cyril.ContactList, YAHOO.widget.Module);

extending Module

YAHOO.namespace(YAHOO.Cyril);

Page 19: Custom YUI Widgets

Done :)

YAHOO.util.Event.onDOMReady(function() { var contact_list = new YAHOO.Cyril.ContactList('contact-list'); YAHOO.util.Dom.batch( [ contact_list.element, contact_list.header, contact_list.body, contact_list.footer], function(el) { el.style.border = '1px solid red'; } );});

YAHOO.util.Event.onDOMReady(function() { var contact_list = new YAHOO.Cyril.ContactList('contact-list');});

Page 20: Custom YUI Widgets

Done :)

Page 21: Custom YUI Widgets

Configuration

YAHOO.Cyril.ContactList.prototype.initDefaultConfig = function () {

YAHOO.Cyril.ContactList.superclass.initDefaultConfig.call(this);

/** * Maximum number of contacts to show * @config * @type Number * @default 2 */ this.cfg.addProperty('num_contacts', { handler: this.configNumContacts, validator: this.validateNumContacts, suppressEvent: true, supercedes: false, value: 2 });}

Page 22: Custom YUI Widgets

Configuration

YAHOO.Cyril.ContactList.prototype.validateNumContacts = function(value) {

value = parseInt(value);

return !(isNan(value) || (value < 1) || (value > 3));

};

Page 23: Custom YUI Widgets

Configuration

contact_list.config.setProperty('num_contacts', 1);

alert(contact_list.getProperty('num_contacts));

Page 24: Custom YUI Widgets

Custom Events

Page 25: Custom YUI Widgets

Custom Events

Page 26: Custom YUI Widgets

Custom Events

• with other Controls

• with itself

A structured way to make your Control play well:

Page 27: Custom YUI Widgets

Custom Events/*** Initializes the custom events for YAHOO.Cyril.ContactList.* This method gets called by YAHOO.widget.Module.prototype.init* @method initEvents*/YAHOO.Cyril.ContactList.prototype.initEvents = function() {

// call the base class method to make sure inherited custom events get set up YAHOO.Cyril.ContactList.superclass.initEvents.call(this);

/** * CustomEvent fired before showing a different contact * @event beforeUpdateContactsEvent * @param {HTMLElement} contactElement LI HTMLElement for the contact to show */ this.beforeUpdateContactsEvent = new YAHOO.util.CustomEvent("beforeShowContact", this);

/** * CustomEvent fired after showing a different contact * @event updateContactsEvent * @param {HTMLElement} contactElement LI HTMLElement for the contact now displayed */ this.updateContactsEvent = new YAHOO.util.CustomEvent("showContact", this);};

Page 28: Custom YUI Widgets

Custom Events

var contactElement = get a reference to the new contact element here;if (this.beforeUpdateContactsEvent.fire(contactElement)) { // ... change the contact displayed to contactElement here}this.updateContactsEvent.fire(contactElement);

giving control to third-party code

contact_list.updateContactsEvent.subscribe(function(type, args) { alert(args[0].current_index);});

Page 29: Custom YUI Widgets

Init function

• called upon instantiation

• some “mandatory” things to do

• gets your widget up and running

Page 30: Custom YUI Widgets

Init function

Call YAHOO.widget.Module.prototype.init

YAHOO.Cyril.ContactList.superclass.init.call(this, el/*, userConfig*/);

Page 31: Custom YUI Widgets

Init function

Fire "beforeInit" and "init" events when appropriate

this.beforeInitEvent.fire(YAHOO.Cyril.ContactList);

// .. rest of the init function

this.initEvent.fire(YAHOO.Cyril.ContactList);

Note there is no need to call this.initEvents(...) to initialise Custom Events

Page 32: Custom YUI Widgets

Init function

Cache DOM references

// cache element reference

this.some_element = document.getElementById('some_element_id');

No need for the main widget’s element + header, body, and footer child elements.

Page 33: Custom YUI Widgets

Init function

Do DOM manipulations

// create/modify DOM elements (ie. previous/next links)

this.initDOMManipulations();

Page 34: Custom YUI Widgets

Init function

set up Event listeners

// initialise event delegation

this.initEventListeners();

Page 35: Custom YUI Widgets

Init function

Default behaviour

// show/hide contact elements

this.updateDisplay();

Page 36: Custom YUI Widgets

Init functionYAHOO.Cyril.ContactList.prototype.init = function(el, userConfig) { // Note that we don't pass the user config in here yet because we only want it processed once, at the lowest subclass level (by calling this.cfg.applyConfig later on) // this also calls this.initEvents YAHOO.Cyril.ContactList.superclass.init.call(this, el/*, userConfig*/); // fire event saying we are about to start the initialisation this.beforeInitEvent.fire(YAHOO.Cyril.ContactList); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.contact_elements = this.body.getElementsByTagName('li'); if (this.contact_elements.length == 0) { return; } this.current_index = 0;

// create/modify DOM elements (ie. previous/next links) this.initDOMManipulations(); // show/hide contact elements this.updateDisplay(); // initialise event delegation this.initEventListeners(); // fire event saying initialisation of the Control is done this.initEvent.fire(YAHOO.Cyril.ContactList); };

Page 37: Custom YUI Widgets

Multiple instances• store instance in an Array

• Custom Events don’t get in the way

YAHOO.util.Event.onDOMReady(function() {

// grab all contact lists by their classes and instanciate them.

var contact_lists = YAHOO.util.Dom.getElementsByClassName('contact-list');

for (var i = 0, contact_list; contact_list = contact_lists[i]; i ++) { var control = new YAHOO.Cyril.ContactList(contact_list); // store a reference to the instance YAHOO.Cyril.contactLists = [ control ] control.updateContactsEvent.subscribe(function(type, args) { alert('Current index: ' + args[0].current_index); }); }

});

Page 38: Custom YUI Widgets

Teh End

• http://www.wat.tv/playlist/689334

• http://www.jaunted.com/files/3873/French_baguette.jpg

• http://flickr.com/photos/plasticbag/971055811/

• http://flickr.com/photos/intranation/1113203816/

• http://flickr.com/photos/intranation/1870271315/

Cyril Doussin (http://cyril.doussin.name)

YUI: http://developer.yahoo.com/yui/

YUI blog: http://yuiblog.com