SlideShare a Scribd company logo
1 of 139
Download to read offline
Jazz up your JavaScript
Unobtrusive scripting with JavaScript libraries

              Simon Willison
         Webstock, 11th February 2008
This tutorial


• Unobtrusive scripting
• JavaScript libraries
• Writing unobtrusive scripts with jQuery
But first... let’s travel
back in time to 2004
(The only photo I could find of me in 2004)
JavaScript was the ugly duckling of the web standards world
Animated snowflakes
DHTML scripts copied and pasted from dynamicdrive.com
3 revolutions since 2004

•
    Ajax
• Unobtrusive scripting
• High quality open-source libraries
February 2005
The quieter revolutions
were just as important
Unobtrusive Scripting
Progressive enhancement
Rather than hoping for graceful degradation, PE
builds documents for the least capable or
differently capable devices first, then moves on to
enhance those documents with separate logic for
presentation, in ways that don't place an undue
burden on baseline devices but which allow a
richer experience for those users with modern
graphical browser software.


           Steven Champeon and Nick Finck, 2003
Applied to JavaScript

• Build a site that works without JavaScript
• Use JavaScript to enhance that site to
  provide a better user experience: easier to
  interact with, faster, more fun
http://www.neighbourhoodfixit.com/
• Start with Plain Old Semantic HTML
• Layer on some CSS (in an external
  stylesheet) to apply the site’s visual design

• Layer on some JavaScript (in an
  external script file) to apply the
  site’s enhanced behaviour
Surely everyone has
JavaScript these days?
• There are legitimate reasons to switch it off
 • Some companies strip JavaScript at the
    firewall

  • Some people run the NoScript Firefox
    extension to protect themselves from
    common XSS and CSRF vulnerabilities

• Many mobile devices ignore JS entirely
• Screen readers DO execute JavaScript, but
  accessibility issues mean that you may not
  want them to
The NoScript extension
Unobtrusive examples
labels.js




• One of the earliest examples of this
  technique, created by Aaron Boodman (now
  of Greasemonkey and Google Gears fame)
How it works
         <label for=quot;searchquot;>Search</label>
         <input type=quot;textquot; id=quot;searchquot; name=quot;qquot;>

• Once the page has loaded, the JavaScript:
 • Finds any label elements linked to a text field
 • Moves their text in to the associated text field
 • Removes them from the DOM
 • Sets up the event handlers to remove the
    descriptive text when the field is focused
• Clean, simple, reusable
easytoggle.js
  • An unobtrusive technique for revealing
     panels when links are clicked

<ul>
  <li><a href=quot;#panel1quot; class=quot;togglequot;>Panel 1</a></li>
  <li><a href=quot;#panel2quot; class=quot;togglequot;>Panel 2</a></li>
  <li><a href=quot;#panel3quot; class=quot;togglequot;>Panel 3</a></li>
</ul>


<div id=quot;panel1quot;>...</div>
<div id=quot;panel2quot;>...</div>
<div id=quot;panel3quot;>...</div>
How it works
•   When the page has loaded...

    •   Find all links with class=quot;togglequot; that reference an
        internal anchor

    •   Collect the elements that are referenced by those
        anchors

    •   Hide all but the first

    •   Set up event handlers to reveal different panels when a
        link is clicked

•   Without JavaScript, links still jump to the right point
Django filter lists

• Large multi-select boxes aren't much fun
 • Painful to scroll through
 • Easy to lose track of what you have
    selected
• Django's admin interface uses unobtrusive
  JavaScript to improve the usability here
Mapping Microformats

• The hCard microformat provides a standard
  set of CSS classes for marking up an address
• Wouldn’t it be great if we could
  unobtrusively plot them on a Google Map...
•   When the page loads...

    •   Scan through for hCards (by looking for
        class=quot;vCardquot;)

    •   Extract the street address and postcode for
        each one

    •   Pass it to the Google Maps geocoder to get
        the lat/long point

    •   Insert a div for the Google Map, instantiate it
        and add the points as markers
How about Ajax?
• Ajax is frequently used to avoid page refreshes
• So...
 • Write an app that uses full page refreshes
 • Use unobtrusive JS to quot;hijackquot; links and form
    buttons and use Ajax instead
• Jeremy Keith coined the term quot;Hijaxquot; to
  describe this
A simple example
Bad

Have you read our
<a href=quot;javascript:window.open(
   'terms.html', 'popup',
   'height=500,width=400,toolbar=no'
);quot;>terms and conditions</a>?
Also bad

Have you read our
<a href=quot;#quot; onclick=quot;window.open(
   'terms.html', 'popup',
   'height=500,width=400,toolbar=no'
); return false;quot;
>terms and conditions</a>?
Better

Have you read our
<a href=quot;terms.htmlquot;
 onclick=quot;window.open(
   'terms.html', 'popup',
   'height=500,width=400,toolbar=no'
  ); return false;quot;
  >terms and conditions</a>?
Better still

Have you read our
<a href=quot;terms.htmlquot;
 onclick=quot;window.open(
   this.href, 'popup',
   'height=500,width=400,toolbar=no'
  ); return false;quot;
  >terms and conditions</a>?
Best

Have you read our
<a href=quot;terms.htmlquot;
  class=quot;sidenotequot;
>terms and conditions</a>?
Characteristics of
   unobtrusive scripts
• No in-line event handlers
• All code is contained in external .js files
• The site remains usable without JavaScript
• Existing links and forms are repurposed
• JavaScript dependent elements are
  dynamically added to the page
Handling events

function makeLinkPopup(link) {
    if (link.addEventListener) { // W3C spec browsers
	

   link.addEventListener('click', popupClicked, false);
    } else if (link.attachEvent) { // Internet Explorer
      link.attachEvent('onclick', popupClicked);
    } else {
      return; // Fail silently in ancient browsers
    }
}
Handling events (2)
function popupClicked(ev) {
    // Find the link that was clicked
    ev = ev || window.event;
    var link = ev.target || ev.srcElement;
    if (link.nodeType == 3) { // Safari bug fix
	

 	

 link = link.parentNode;
    }
    window.open(link.href, 'popup',
       'height=500,width=400,toolbar=no');
    // Now prevent the default link action
    if (ev.preventDefault) {
       ev.preventDefault(); // W3C spec browsers
    } else {
       ev.returnValue = false; // Internet Explorer
    }
}
Handling events (3)
function setupLinks() {
  var links = document.getElementsByTagName('a');
  for (var i = 0, link; link = links[i]; i++) {
    if (link.className == 'sidenote') {
      makeLinkPopup(link);
    }
  }
}

if (window.addEventListener) {
  window.addEventListener('load', setupLinks, false);
} else if (window.attachEvent) {
  window.attachEvent('onload', setupLinks);
}
That’s way too much
  nasty boilerplate
Unobtrusive challenges
• Adding events from pure script (avoiding
  inline script handlers) works differently
  between IE and other browsers
• Cancelling default actions (link navigation,
  form submission) also works differently
• Scripts that add behaviour need to execute
  as soon as the DOM is available
The onload problem
• All of these examples use code that runs
  when the window quot;loadquot; event is fired
  • Wait until page is loaded, then manipulate
     the DOM
• Problem: If the page takes a while to load
  (large inline images) there will be a Flash Of
  Unstyled Content (FOUC)
• Also, if the user clicks things before the
  setup code has fired they won't get the
  expected behaviour.
onDOMReady
•   A number of attempts have been made to create
    an onDOMReady event that fires when the
    DOM has been constructed but before the page
    has loaded

    •   dean.edwards.name/weblog/2006/06/again/

    •   Modern libraries all support this in some form

•   One caveat: CSS may not have loaded, so
    calculated dimensions may be incorrect
So we need libraries

• Writing this stuff by hand is madness
• Boilerplate code to deal with browser
  inconsistencies is the number one enemy of
  unobtrusive scripting
• Thankfully, today these are all solved
  problems
JavaScript Libraries
Controversial statement

• A year ago, there was a sizable debate over
    whether libraries were worth using at all -
    many people preferred to just “roll their
    own”
• Today, that argument is over. Libraries have
    won.
•   (some may disagree)
“The bad news:
JavaScript is broken.
    The good news:
 It can be fixed with
  more JavaScript!”
              Geek folk saying
JavaScript characteristics
• Highly dynamic language
 • Most things can be introspected
 • Most things can be modified at runtime
• Functional programming, anonymous
  functions and closures
• Ability to modify behaviour of built-in types
• Prototypal inheritance - arguably more
  powerful than class-based inheritance,
  though much less widely understood
Modifying built-in types

var s = quot;This is a stringquot;;
alert(s.dasherize()); // Throws an error

String.prototype.dasherize = function() {
  return this.toLowerCase().replace(/s+/g, '-');
}

alert(s.dasherize()); // this-is-a-string
Functional programming
function hello() {
  alert(quot;helloquot;);
}

var hello = function() {
  alert(quot;helloquot;);
}

(function() {
  alert(quot;helloquot;);
})();
Functional programming
function hello() {
  alert(quot;helloquot;);
}

var hello = function() {
  alert(quot;helloquot;);
}

(function() {
  alert(quot;helloquot;);
})();
Functional programming
function hello() {
  alert(quot;helloquot;);
}

var hello = function() {
  alert(quot;helloquot;);
}

(function() {
  alert(quot;helloquot;);
})();
Closures

function outer() {
  var s = quot;This is a stringquot;;
  function inner() {
    alert(s);
  }
  inner();
}
Closures

function outer() {
  var s = quot;This is a stringquot;;
  function inner() {
    alert(s);
  }
  return inner;
}

var func = outer();
func(); // Alerts quot;This is a stringquot;;
Closures
function outer(s) {
  function inner() {
    alert(s);
  }
  return inner;
}

var sayHello = outer(quot;Helloquot;);
var sayGoodbye = outer(quot;Goodbyequot;);
sayHello();
sayGoodbye();
Common library
   features
DOM selection


• document.getElementById shortcut
• Get elements by class name
• Get elements by CSS selector
CSS manipulation


• Manipulate and toggle classes
• Set styles (including opacity)
• Introspect applied styles
Event handling
• Cross-browser “run this function when this
  event happens to this element”
• Cross-browser “on DOM ready” support
• Cross-browser event introspection: where
  was the event targetted?
• Event triggering
• Custom events
Ajax

• Cross-browser XMLHttpRequest
• Easier API for GET, POST and URL and form
  manipulation
• Support for Ajax formats: HTML fragments,
  JSON, XML
Effects and animation

• Fades, wipes and transitions
• Custom animation of any CSS property
• Automatic frame-rate management
• Easing
Widgets
• Packaged widgets for things like...
 • Sliders
 • Calendar date pickers
 • Fake “windows”
 • Auto-completers
 • Grids and treeviews
• Support for drag-and-drop
Language tools

• Iteration over objects and arrays
• Utilities for managing prototypal inheritance
• Traditional class-based inheritance
• Tools for managing scope and callbacks
• Dynamic code loading
Array manipulation
for (var i = 0; i < arr.length; i++) {
   var item = arr[i];
   // process item
}

forEach(arr, function(item) {
  // process item
});

doubles = map(arr, function(i) { return i * 2 });
evens = filter(arr, function(i) { return i % 2 == 0 });
Other characteristics
• Do they modify built in types?
• Global namespace impact
• Library size and componentization
• Support for accessibility (esp. for widgets)
• Browser support
• Documentation
• Community
The big five
• The Yahoo! User Interface Library
• Prototype (and Script.aculo.us)
• The Dojo Toolkit
• mooTools
• jQuery
The Example

• A login form that shakes its head at you
• Standard POST login form, unobtrusively
  upgraded to use Ajax and shake if the
  password is incorrect
• Behind the scenes, JSON is used for the reply
  to say if the password was correct or not
Simple login JSON API
• Responds to the same POST as the regular
   form, but looks for X-Requested-With:
   XMLHttpRequest header

• If login fails, returns
  {quot;okquot;:false}

• If login succeeds, returns
  {quot;okquot;: true, quot;redirectquot;: quot;loggedin.phpquot;}
The Yahoo! User Interface Library
controls (aka widgets)

autocomplete           calendar           container


  menu                slider            treeview



    animation                       dragdrop


  dom                event              connection

                     utilities
YAHOO.util.Event.onDOMReady(function() {
    var $E = YAHOO.util.Event;
    var $D = YAHOO.util.Dom;
    var $C = YAHOO.util.Connect;
    var query = YAHOO.util.Selector.query;

    $D.get('username').focus();
    var form = query('form')[0];
YAHOO.util.Event.onDOMReady(function() {
    var $E = YAHOO.util.Event;
    var $D = YAHOO.util.Dom;
    var $C = YAHOO.util.Connect;
    var query = YAHOO.util.Selector.query;

    $D.get('username').focus();
    var form = query('form')[0];
YAHOO.util.Event.onDOMReady(function() {
    var $E = YAHOO.util.Event;
    var $D = YAHOO.util.Dom;
    var $C = YAHOO.util.Connect;
    var query = YAHOO.util.Selector.query;

    $D.get('username').focus();
    var form = query('form')[0];
YAHOO.util.Event.onDOMReady(function() {
    var $E = YAHOO.util.Event;
    var $D = YAHOO.util.Dom;
    var $C = YAHOO.util.Connect;
    var query = YAHOO.util.Selector.query;

    $D.get('username').focus();
    var form = query('form')[0];
$E.on(form, 'submit', function(ev) {
    $E.preventDefault(ev);
    var url = form.action;
    $C.setForm(form);
    $C.asyncRequest(
        'POST', url, {
            success: function() { ... }
        }
    );
});
success: function(response) {
  var json = eval('(' +
    response.responseText + ')');
  if (json.ok) {
    window.location = json.redirect;
  } else {
    $D.get('password').value = '';
    $D.get('password').focus();
    shake(form, function() {
      if (!query('p.error').length) {
        var p = document.createElement('p');
        p.className = 'error';
        p.innerHTML = 'Incorrect password.';
        form.insertBefore(p, form.firstChild);
      }
    });
  }
function shake(el, onComplete) {
    var $D = YAHOO.util.Dom;
    $D.setStyle(el, 'position', 'relative');
    var anim = new YAHOO.util.Anim(el, {
        left: {to: -10}
    }, 0.1, YAHOO.util.Easing.easeOut);
    anim.onComplete.subscribe(function() {
        // ...
    }
    anim.animate();
}
function shake(el, onComplete) {
    var $D = YAHOO.util.Dom;
    $D.setStyle(el, 'position', 'relative');
    var anim = new YAHOO.util.Anim(el, {
        left: {to: -10}
    }, 0.1, YAHOO.util.Easing.easeOut);
    anim.onComplete.subscribe(function() {
        var anim2 = new YAHOO.util.Anim(el, {
            left: {to: 10}
        }, 0.1, YAHOO.util.Easing.easeOut);
        anim2.onComplete.subscribe(function() {
            var anim3 = new YAHOO.util.Anim(el, {
                left: {to: -10}
            }, 0.1, YAHOO.util.Easing.easeOut);
            anim3.onComplete.subscribe(function() {
                var anim4 = new YAHOO.util.Anim(el, {
                    left: {to: 10}
                }, 0.1, YAHOO.util.Easing.easeOut);
                anim4.onComplete.subscribe(function() {
                    var anim5 = new YAHOO.util.Anim(el, {
                         left: {to: 0}
                    }, 0.1, YAHOO.util.Easing.easeOut);
                    if (onComplete) {
                         anim5.onComplete.subscribe(onComplete);
                    }
                    anim5.animate();
                });
                anim4.animate();
            });
            anim3.animate();
        });
        anim2.animate();
    });
    anim.animate();
}
• Nice animation library, but a better way of
  chaining animations would be useful

• Severe namespacing (YAHOO was picked
  because it was so ugly no one would ever
  have used it for an existing variable)

• Not too many shortcuts outside of dealing
  with browser difficulties

• Excellent documentation
Download
                                                            Get the latest version—1.5.1


                                                            Learn
Prototype is a JavaScript Framework that aims to            Online documentation and resources.
ease development of dynamic web applications.
Featuring a unique, easy-to-use toolkit for class-driven    Discuss
development and the nicest Ajax library around, Prototype   Mailing list and IRC
is quickly becoming the codebase of choice for web
application developers everywhere.
                                                            Contribute
                Prototype and Script.aculo.us
Prototype and script.aculo.us: The quot;Bungee
bookquot; has landed!
                                                            Submit patches and report bugs.


                                                            Who's using Prototype?
                                                            Meet the developers
                    Core team member Christophe
                    Porteneuve has been hard at work
                    for the past few months tracking
document.observe('dom:loaded', function() {
    $('username').focus();
    var form = $$('form')[0];
    form.observe('submit', function(ev) {
        ev.preventDefault();
        var url = form.action;
        new Ajax.Request(url, {
            parameters: form.serialize(),
            onSuccess: ...
        });
    });
});
onSuccess: function(response) {
    var json = response.responseJSON;
    if (json.ok) {
        window.location = json.redirect;
    } else {
        form.shake();
        // No apparent way of setting an
        // quot;on finishedquot; callback
        setTimeout(function() {
             if (!$$('p.error').length) {
                 var p = new Element(
                     'p', {'class': 'error'}
                 ).insert('Incorrect...');
                 form.insertBefore(p, form.firstChild);
             }
        }, 500);
        $('password').value = '';
        $('password').focus();
    }
}
• Adds many functions to the global
  namespace ($, $$ etc) and extensively
  modifies built in types

• Heavily inspired by Ruby and Ruby on Rails
• Useful shortcuts and nice effects
• Documentation still leaves something to be
  desired - API docs for Prototype, incomplete
  wiki docs for Scriptaculous
The Dojo Toolkit
dojo.require('dojox.fx');
djConfig.usePlainJson = true;

dojo.addOnLoad(function() {
  dojo.byId('username').focus();
  dojo.query('form').connect('submit', function(ev) {
    dojo.stopEvent(ev);
    var form = this;
    var url = form.action;
    dojo.xhrPost({
      handleAs: 'json',
      headers: {'X-Requested-With': 'XMLHttpRequest'},
      url: url,
      form: form,
      load: function(json) { ... }
    });
  });
});
load: function(json) {
  if (json.ok) {
    window.location = json.redirect;
  } else {
    form.style.position = 'relative';
    var last = dojo.animateProperty({
       node: form, duration: 100,
       properties: {left: {end: 0}}
    });
    var leftArgs = {
       node: form, duration: 100,
       properties: {left: {end: -10}}
    };
    var rightArgs = {
       node: form, duration: 100,
       properties: {left: {end: 10}}
    };
    dojo.fx.chain([
       dojo.animateProperty(leftArgs),
       dojo.animateProperty(rightArgs),
       dojo.animateProperty(leftArgs),
       dojo.animateProperty(rightArgs),
       last
    ]).play();
dojo.connect(last, 'onEnd', function() {
  if (!dojo.query('p.error').length) {
    var p = document.createElement('p');
    p.className = 'error';
    p.innerHTML = 'Incorrect username or password.';
    form.insertBefore(p, form.firstChild);
  }
});
dojo.byId('password').value = '';
dojo.byId('password').focus();
• core, dijit and dojox:
 • Small, powerful abstraction library
 • Widget creation tools plus many widgets
 • “The future today” genius extensions
• Documentation has improved with the Dojo
  Book, but still patchy in places
mooTools
window.addEvent('domready', function() {
    $('username').focus();
    $$('form').addEvent('submit', function(ev) {
        new Event(ev).stop();
        var form = this;
        var url = form.action;
        form.send({
            onComplete: function(data) {
                var json = Json.evaluate(data);
                if (json.ok) {
                    window.location = json.redirect;
                } else {
                    form.style.position = 'relative';
                    // ... animation here
                    $('password').value = '';
                    $('password').focus();
                }
            }
        });
    });
});
var fx = form.effects({
    duration: 100,
    transition: Fx.Transitions.Quart.easeOut
});
fx.start({left: -10}).chain(function(){
    this.start({left: 10});
}).chain(function(){
    this.start({left: -10});
}).chain(function(){
    this.start({left: 10});
}).chain(function(){
    this.start({left: 0});
}).chain(function() {
    if (!$$('p.error').length) {
        var p = new Element('p').
          addClass('error').setHTML(
             'Incorrect username or password.'
          );
        form.insertBefore(p, form.firstChild);
    }
});
•   Started as an effects library for Prototype, now its
    own thing but Prototype influences are clear

•   No intention at all of playing nicely with other
    libraries

•   Good API documentation (including a mootorial)
    but not much else, and major changes between
    library versions

•   I found the API unintuitive compared to the others
jQuery
jQuery(function($) {
  $('#username').focus();
  $('form').submit(function() {
    var $this = $(this);
    var url = $this.attr('action');
    var data = $this.serialize();
    jQuery.post(url, data, function(json) {
      if (json.ok) {
        window.location = json.redirect;
      } else {
        $('#password').val('').focus();
        $this.shake(function() {
          if (!$this.find('p.error').length) {
            $this.prepend('<p class=quot;errorquot;>Incorrect ...</p>');
          }
        });
      }
    }, 'json');
    return false;
  });
});
jQuery.fn.shake = function(callback) {
    this.css({'position': 'relative'});
    return this.animate(
        {left: '-10px'}, 100
    ).animate(
        {left: '+10px'}, 100
    ).animate(
        {left: '-10px'}, 100
    ).animate(
        {left: '+10px'}, 100
    ).animate(
        {left: '0px'}, 100, callback
    );
};
• Powerful, concise API based around CSS
  selector querying and chaining

• Excellent namespace management -
  everything lives on the one jQuery symbol
  which is aliased to $, with the option to
  revert

• Excellent support for plugins
• The best documentation out of all of the
  libraries
Unobtrusive scripting
   with jQuery
Why jQuery

• It has the best balance between simplicity,
  productivity and good manners
• It has excellent documentation
• You can learn the whole library in less than
  an hour
Why jQuery instead of...?

•   Unlike Prototype and mooTools...

    •   ... it doesn’t populate your global namespace

•   Unlike YUI...

    •   ... it’s extremely succinct

•   Unlike Dojo...

    •   ... you can learn it in 45 minutes!
Learning

jQuery
in 45 minutes
jQuery philosophy

• Focus on the interaction between JavaScript
  and HTML
• (Almost) every operation boils down to:
 • Find some stuff
 • Do something to it
Sidenotes with jQuery

jQuery(function($) {
  $('a.sidenote').click(function() {
    window.open($(this).attr('href'), 'popup',
      'height=500,width=400,toolbar=no');
    return false;
  });
});
Only one function!
• Absolutely everything* starts with a call to
  the jQuery() function
• Since it’s called so often, the $ variable is set
  up as an alias to jQuery
• If you’re also using another library you can
  revert to the previous $ function with
  jQuery.noConflict();

                 * not entirely true
jQuery('#nav')

jQuery('div#intro h2')

jQuery('#nav li.current a')
$('#nav')

$('div#intro h2')

$('#nav li.current a')
CSS 2 and 3 selectors

a[rel]

a[rel=quot;friendquot;]

a[href^=quot;http://quot;]

ul#nav > li

li#current ~ li (li siblings that follow #current)

li:first-child, li:last-child, li:nth-child(3)
Magic selectors
div:first, h3:last
:header
:hidden, :visible
:animated
:input, :text, :password, :radio, :submit...
div:contains(Hello)
jQuery collections
 •   $('div.section') returns a jQuery collection


 •   You can treat it like an array
$('div.section').length = no. of matched elements

$('div.section')[0] - the first div DOM element

$('div.section')[1]

$('div.section')[2]
jQuery collections
 •    $('div.section') returns a jQuery collection


 •    You can call methods on it
$('div.section').size() = no. of matched elements

$('div.section').each(function() {

      console.log(this);

});
jQuery collections
 •    $('div.section') returns a jQuery collection


 •    You can call methods on it
$('div.section').size() = no. of matched elements

$('div.section').each(function(i) {

      console.log(quot;Item quot; + i + quot; is quot;, this);

});
HTML futzing


$('span#msg').text('The thing was updated!');



$('div#intro').html('<em>Look, HTML</em>');
Attribute futzing

$('a.nav').attr('href', 'http://flickr.com/');

$('a.nav').attr({

  'href': 'http://flickr.com/',

  'id': 'flickr'

});

$('#intro').removeAttr('id');
CSS futzing

$('#intro').addClass('highlighted');

$('#intro').removeClass('highlighted');

$('#intro').toggleClass('highlighted');



$('p').css('font-size', '20px');

$('p').css({'font-size': '20px', color: 'red'});
Grabbing values
 • Some methods return results from the first
    matched element
var height = $('div#intro').height();

var src = $('img.photo').attr('src');

var lastP = $('p:last').html()

var hasFoo = $('p').hasClass('foo');

var email = $('input#email').val();
Traversing the DOM
 • jQuery provides enhanced methods for
    traversing the DOM
$('div.section').parent()

$('div.section').next()

$('div.section').prev()

$('div.section').nextAll('div')

$('h1:first').parents()
Handling events

$('a:first').click(function(ev) {

  $(this).css({backgroundColor: 'orange'});

  return false; // Or ev.preventDefault();

});
Handling events

$('a:first').click(function(ev) {

  $(this).css({backgroundColor: 'orange'});

  return false; // Or ev.preventDefault();

});

$('a:first').click();
Going unobtrusive


$(document).ready(function() {

  alert('The DOM is ready!');

});
Going unobtrusive


$(function() {

  alert('The DOM is ready!');

});
Going unobtrusive


jQuery(function($) {

  alert('The DOM is ready!');

});
Chaining

 • Most jQuery methods return another
    jQuery object - usually one representing the
    same collection. This means you can chain
    methods together:
$('div.section').hide().addClass('gone');
Advanced chaining
• Some methods return a different collection
• You can call .end() to revert to the previous
  collection
Advanced chaining

 • Some methods return a different collection
 • You can call .end() to revert to the previous
    collection
$('#intro').css('color', '#cccccc').

find('a').addClass('highlighted').end().

find('em').css('color', 'red').end()
Ajax
 •   jQuery has excellent support for Ajax
$('div#intro').load('/some/file.html');

 •   More advanced methods include:
$.get(url, params, callback)

$.post(url, params, callback)

$.getJSON(url, params, callback)

$.getScript(url, callback)
Animation

 • jQuery has built in effects:
$('h1').hide('slow');

$('h1').slideDown('fast');

$('h1').fadeOut(2000);

 • You can chain them:
$('h1').fadeOut(1000).slideDown()
Or roll your own...

$(quot;#blockquot;).animate({

   width: quot;+=60pxquot;,

   opacity: 0.4,

   fontSize: quot;3emquot;,

   borderWidth: quot;10pxquot;

}, 1500);
Plugins


• jQuery is extensible through plugins, which
  can add new methods to the jQuery object
Further reading
• http://jquery.com/
• http://docs.jquery.com/
• http://visualjquery.com/ - API reference
• http://simonwillison.net/tags/jquery/
• http://simonwillison.net/2007/Aug/15/jquery/
• http://24ways.org/2007/unobtrusively-
  mapping-microformats-with-jquery

More Related Content

What's hot

Performance, Games, and Distributed Testing in JavaScript
Performance, Games, and Distributed Testing in JavaScriptPerformance, Games, and Distributed Testing in JavaScript
Performance, Games, and Distributed Testing in JavaScriptjeresig
 
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)Nicholas Zakas
 
Keypoints html5
Keypoints html5Keypoints html5
Keypoints html5dynamis
 
Learning from the Best jQuery Plugins
Learning from the Best jQuery PluginsLearning from the Best jQuery Plugins
Learning from the Best jQuery PluginsMarc Grabanski
 
Web versus Native: round 1!
Web versus Native: round 1!Web versus Native: round 1!
Web versus Native: round 1!Chris Mills
 
Empowering the "mobile web"
Empowering the "mobile web"Empowering the "mobile web"
Empowering the "mobile web"Chris Mills
 
Progressive Enhancement 2.0 (Conference Agnostic)
Progressive Enhancement 2.0 (Conference Agnostic)Progressive Enhancement 2.0 (Conference Agnostic)
Progressive Enhancement 2.0 (Conference Agnostic)Nicholas Zakas
 
APIs, now and in the future
APIs, now and in the futureAPIs, now and in the future
APIs, now and in the futureChris Mills
 
[jqconatx] Adaptive Images for Responsive Web Design
[jqconatx] Adaptive Images for Responsive Web Design[jqconatx] Adaptive Images for Responsive Web Design
[jqconatx] Adaptive Images for Responsive Web DesignChristopher Schmitt
 
Browser Wars Episode 1: The Phantom Menace
Browser Wars Episode 1: The Phantom MenaceBrowser Wars Episode 1: The Phantom Menace
Browser Wars Episode 1: The Phantom MenaceNicholas Zakas
 
APIs for modern web apps
APIs for modern web appsAPIs for modern web apps
APIs for modern web appsChris Mills
 
Speeding up mobile web apps
Speeding up mobile web appsSpeeding up mobile web apps
Speeding up mobile web appsIvano Malavolta
 
Making your Angular.js Application accessible
Making your Angular.js Application accessibleMaking your Angular.js Application accessible
Making your Angular.js Application accessibleDirk Ginader
 
Get Ahead with HTML5 on Moible
Get Ahead with HTML5 on MoibleGet Ahead with HTML5 on Moible
Get Ahead with HTML5 on Moiblemarkuskobler
 
Don't Over-React - just use Vue!
Don't Over-React - just use Vue!Don't Over-React - just use Vue!
Don't Over-React - just use Vue!Raymond Camden
 
HTML5 vs Silverlight
HTML5 vs SilverlightHTML5 vs Silverlight
HTML5 vs SilverlightMatt Casto
 

What's hot (20)

Performance, Games, and Distributed Testing in JavaScript
Performance, Games, and Distributed Testing in JavaScriptPerformance, Games, and Distributed Testing in JavaScript
Performance, Games, and Distributed Testing in JavaScript
 
What is HTML 5?
What is HTML 5?What is HTML 5?
What is HTML 5?
 
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
 
Keypoints html5
Keypoints html5Keypoints html5
Keypoints html5
 
Learning from the Best jQuery Plugins
Learning from the Best jQuery PluginsLearning from the Best jQuery Plugins
Learning from the Best jQuery Plugins
 
Web versus Native: round 1!
Web versus Native: round 1!Web versus Native: round 1!
Web versus Native: round 1!
 
Empowering the "mobile web"
Empowering the "mobile web"Empowering the "mobile web"
Empowering the "mobile web"
 
Progressive Enhancement 2.0 (Conference Agnostic)
Progressive Enhancement 2.0 (Conference Agnostic)Progressive Enhancement 2.0 (Conference Agnostic)
Progressive Enhancement 2.0 (Conference Agnostic)
 
Always on! Or not?
Always on! Or not?Always on! Or not?
Always on! Or not?
 
HTML 5 - Overview
HTML 5 - OverviewHTML 5 - Overview
HTML 5 - Overview
 
WordPress and Ajax
WordPress and AjaxWordPress and Ajax
WordPress and Ajax
 
APIs, now and in the future
APIs, now and in the futureAPIs, now and in the future
APIs, now and in the future
 
[jqconatx] Adaptive Images for Responsive Web Design
[jqconatx] Adaptive Images for Responsive Web Design[jqconatx] Adaptive Images for Responsive Web Design
[jqconatx] Adaptive Images for Responsive Web Design
 
Browser Wars Episode 1: The Phantom Menace
Browser Wars Episode 1: The Phantom MenaceBrowser Wars Episode 1: The Phantom Menace
Browser Wars Episode 1: The Phantom Menace
 
APIs for modern web apps
APIs for modern web appsAPIs for modern web apps
APIs for modern web apps
 
Speeding up mobile web apps
Speeding up mobile web appsSpeeding up mobile web apps
Speeding up mobile web apps
 
Making your Angular.js Application accessible
Making your Angular.js Application accessibleMaking your Angular.js Application accessible
Making your Angular.js Application accessible
 
Get Ahead with HTML5 on Moible
Get Ahead with HTML5 on MoibleGet Ahead with HTML5 on Moible
Get Ahead with HTML5 on Moible
 
Don't Over-React - just use Vue!
Don't Over-React - just use Vue!Don't Over-React - just use Vue!
Don't Over-React - just use Vue!
 
HTML5 vs Silverlight
HTML5 vs SilverlightHTML5 vs Silverlight
HTML5 vs Silverlight
 

Viewers also liked

Rediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The LibrariesRediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The LibrariesSimon Willison
 
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...Charles Beyer
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQueryKnoldus Inc.
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)Doris Chen
 
Why everything is an A/B Test at Pinterest
Why everything is an A/B Test at PinterestWhy everything is an A/B Test at Pinterest
Why everything is an A/B Test at PinterestKrishna Gade
 
A/B Testing at Pinterest: Building a Culture of Experimentation
A/B Testing at Pinterest: Building a Culture of Experimentation A/B Testing at Pinterest: Building a Culture of Experimentation
A/B Testing at Pinterest: Building a Culture of Experimentation WrangleConf
 
jQuery Presentation
jQuery PresentationjQuery Presentation
jQuery PresentationRod Johnson
 

Viewers also liked (9)

Rediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The LibrariesRediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The Libraries
 
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
Hyperion EPM APIs - Added value from HFM, Workspace, FDM, Smartview, and Shar...
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
JSP Custom Tags
JSP Custom TagsJSP Custom Tags
JSP Custom Tags
 
Why everything is an A/B Test at Pinterest
Why everything is an A/B Test at PinterestWhy everything is an A/B Test at Pinterest
Why everything is an A/B Test at Pinterest
 
A/B Testing at Pinterest: Building a Culture of Experimentation
A/B Testing at Pinterest: Building a Culture of Experimentation A/B Testing at Pinterest: Building a Culture of Experimentation
A/B Testing at Pinterest: Building a Culture of Experimentation
 
jQuery
jQueryjQuery
jQuery
 
jQuery Presentation
jQuery PresentationjQuery Presentation
jQuery Presentation
 

Similar to Jazz up your JavaScript: Unobtrusive scripting with JavaScript libraries

How to make Ajax Libraries work for you
How to make Ajax Libraries work for youHow to make Ajax Libraries work for you
How to make Ajax Libraries work for youSimon Willison
 
JavaScript Libraries: The Big Picture
JavaScript Libraries: The Big PictureJavaScript Libraries: The Big Picture
JavaScript Libraries: The Big PictureSimon Willison
 
jQuery Presentation to Rails Developers
jQuery Presentation to Rails DevelopersjQuery Presentation to Rails Developers
jQuery Presentation to Rails DevelopersYehuda Katz
 
Drupal 6 JavaScript and jQuery
Drupal 6 JavaScript and jQueryDrupal 6 JavaScript and jQuery
Drupal 6 JavaScript and jQueryMatt Butcher
 
Reverse Engineering Malicious Javascript
Reverse Engineering Malicious JavascriptReverse Engineering Malicious Javascript
Reverse Engineering Malicious JavascriptYusuf Motiwala
 
WebGL: GPU acceleration for the open web
WebGL: GPU acceleration for the open webWebGL: GPU acceleration for the open web
WebGL: GPU acceleration for the open webpjcozzi
 
7 tips for javascript rich ajax websites
7 tips for javascript rich ajax websites7 tips for javascript rich ajax websites
7 tips for javascript rich ajax websitesoazabir
 
Integrating React.js Into a PHP Application
Integrating React.js Into a PHP ApplicationIntegrating React.js Into a PHP Application
Integrating React.js Into a PHP ApplicationAndrew Rota
 
Usability in the GeoWeb
Usability in the GeoWebUsability in the GeoWeb
Usability in the GeoWebDave Bouwman
 
Ajax Tutorial
Ajax TutorialAjax Tutorial
Ajax Tutorialoscon2007
 
Intro To Django
Intro To DjangoIntro To Django
Intro To DjangoUdi Bauman
 
Learning jQuery @ MIT
Learning jQuery @ MITLearning jQuery @ MIT
Learning jQuery @ MITjeresig
 
JavaScript 2.0 in Dreamweaver CS4
JavaScript 2.0 in Dreamweaver CS4JavaScript 2.0 in Dreamweaver CS4
JavaScript 2.0 in Dreamweaver CS4alexsaves
 
More efficient, usable web
More efficient, usable webMore efficient, usable web
More efficient, usable webChris Mills
 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoojeresig
 
Web Apps and more
Web Apps and moreWeb Apps and more
Web Apps and moreYan Shi
 
Web app and more
Web app and moreWeb app and more
Web app and morefaming su
 
Efficient JavaScript Development
Efficient JavaScript DevelopmentEfficient JavaScript Development
Efficient JavaScript Developmentwolframkriesing
 

Similar to Jazz up your JavaScript: Unobtrusive scripting with JavaScript libraries (20)

How to make Ajax Libraries work for you
How to make Ajax Libraries work for youHow to make Ajax Libraries work for you
How to make Ajax Libraries work for you
 
JavaScript Libraries: The Big Picture
JavaScript Libraries: The Big PictureJavaScript Libraries: The Big Picture
JavaScript Libraries: The Big Picture
 
jQuery Presentation to Rails Developers
jQuery Presentation to Rails DevelopersjQuery Presentation to Rails Developers
jQuery Presentation to Rails Developers
 
Drupal 6 JavaScript and jQuery
Drupal 6 JavaScript and jQueryDrupal 6 JavaScript and jQuery
Drupal 6 JavaScript and jQuery
 
Reverse Engineering Malicious Javascript
Reverse Engineering Malicious JavascriptReverse Engineering Malicious Javascript
Reverse Engineering Malicious Javascript
 
WebGL: GPU acceleration for the open web
WebGL: GPU acceleration for the open webWebGL: GPU acceleration for the open web
WebGL: GPU acceleration for the open web
 
7 tips for javascript rich ajax websites
7 tips for javascript rich ajax websites7 tips for javascript rich ajax websites
7 tips for javascript rich ajax websites
 
Integrating React.js Into a PHP Application
Integrating React.js Into a PHP ApplicationIntegrating React.js Into a PHP Application
Integrating React.js Into a PHP Application
 
Usability in the GeoWeb
Usability in the GeoWebUsability in the GeoWeb
Usability in the GeoWeb
 
Ajax Tutorial
Ajax TutorialAjax Tutorial
Ajax Tutorial
 
Intro To Django
Intro To DjangoIntro To Django
Intro To Django
 
Javascript
JavascriptJavascript
Javascript
 
Learning jQuery @ MIT
Learning jQuery @ MITLearning jQuery @ MIT
Learning jQuery @ MIT
 
JavaScript 2.0 in Dreamweaver CS4
JavaScript 2.0 in Dreamweaver CS4JavaScript 2.0 in Dreamweaver CS4
JavaScript 2.0 in Dreamweaver CS4
 
More efficient, usable web
More efficient, usable webMore efficient, usable web
More efficient, usable web
 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoo
 
Web Apps and more
Web Apps and moreWeb Apps and more
Web Apps and more
 
Web app and more
Web app and moreWeb app and more
Web app and more
 
Efficient JavaScript Development
Efficient JavaScript DevelopmentEfficient JavaScript Development
Efficient JavaScript Development
 
Webpack
Webpack Webpack
Webpack
 

More from Simon Willison

Cheap tricks for startups
Cheap tricks for startupsCheap tricks for startups
Cheap tricks for startupsSimon Willison
 
The Django Web Framework (EuroPython 2006)
The Django Web Framework (EuroPython 2006)The Django Web Framework (EuroPython 2006)
The Django Web Framework (EuroPython 2006)Simon Willison
 
How we bootstrapped Lanyrd using Twitter's social graph
How we bootstrapped Lanyrd using Twitter's social graphHow we bootstrapped Lanyrd using Twitter's social graph
How we bootstrapped Lanyrd using Twitter's social graphSimon Willison
 
Web Services for Fun and Profit
Web Services for Fun and ProfitWeb Services for Fun and Profit
Web Services for Fun and ProfitSimon Willison
 
Tricks & challenges developing a large Django application
Tricks & challenges developing a large Django applicationTricks & challenges developing a large Django application
Tricks & challenges developing a large Django applicationSimon Willison
 
Advanced Aspects of the Django Ecosystem: Haystack, Celery & Fabric
Advanced Aspects of the Django Ecosystem: Haystack, Celery & FabricAdvanced Aspects of the Django Ecosystem: Haystack, Celery & Fabric
Advanced Aspects of the Django Ecosystem: Haystack, Celery & FabricSimon Willison
 
How Lanyrd uses Twitter
How Lanyrd uses TwitterHow Lanyrd uses Twitter
How Lanyrd uses TwitterSimon Willison
 
Building Things Fast - and getting approval
Building Things Fast - and getting approvalBuilding Things Fast - and getting approval
Building Things Fast - and getting approvalSimon Willison
 
Building crowdsourcing applications
Building crowdsourcing applicationsBuilding crowdsourcing applications
Building crowdsourcing applicationsSimon Willison
 
Evented I/O based web servers, explained using bunnies
Evented I/O based web servers, explained using bunniesEvented I/O based web servers, explained using bunnies
Evented I/O based web servers, explained using bunniesSimon Willison
 
Cowboy development with Django
Cowboy development with DjangoCowboy development with Django
Cowboy development with DjangoSimon Willison
 
Crowdsourcing with Django
Crowdsourcing with DjangoCrowdsourcing with Django
Crowdsourcing with DjangoSimon Willison
 
Class-based views with Django
Class-based views with DjangoClass-based views with Django
Class-based views with DjangoSimon Willison
 
Web App Security Horror Stories
Web App Security Horror StoriesWeb App Security Horror Stories
Web App Security Horror StoriesSimon Willison
 
Web Security Horror Stories
Web Security Horror StoriesWeb Security Horror Stories
Web Security Horror StoriesSimon Willison
 
When Zeppelins Ruled The Earth
When Zeppelins Ruled The EarthWhen Zeppelins Ruled The Earth
When Zeppelins Ruled The EarthSimon Willison
 

More from Simon Willison (20)

How Lanyrd does Geo
How Lanyrd does GeoHow Lanyrd does Geo
How Lanyrd does Geo
 
Cheap tricks for startups
Cheap tricks for startupsCheap tricks for startups
Cheap tricks for startups
 
The Django Web Framework (EuroPython 2006)
The Django Web Framework (EuroPython 2006)The Django Web Framework (EuroPython 2006)
The Django Web Framework (EuroPython 2006)
 
Building Lanyrd
Building LanyrdBuilding Lanyrd
Building Lanyrd
 
How we bootstrapped Lanyrd using Twitter's social graph
How we bootstrapped Lanyrd using Twitter's social graphHow we bootstrapped Lanyrd using Twitter's social graph
How we bootstrapped Lanyrd using Twitter's social graph
 
Web Services for Fun and Profit
Web Services for Fun and ProfitWeb Services for Fun and Profit
Web Services for Fun and Profit
 
Tricks & challenges developing a large Django application
Tricks & challenges developing a large Django applicationTricks & challenges developing a large Django application
Tricks & challenges developing a large Django application
 
Advanced Aspects of the Django Ecosystem: Haystack, Celery & Fabric
Advanced Aspects of the Django Ecosystem: Haystack, Celery & FabricAdvanced Aspects of the Django Ecosystem: Haystack, Celery & Fabric
Advanced Aspects of the Django Ecosystem: Haystack, Celery & Fabric
 
How Lanyrd uses Twitter
How Lanyrd uses TwitterHow Lanyrd uses Twitter
How Lanyrd uses Twitter
 
ScaleFail
ScaleFailScaleFail
ScaleFail
 
Building Things Fast - and getting approval
Building Things Fast - and getting approvalBuilding Things Fast - and getting approval
Building Things Fast - and getting approval
 
Building crowdsourcing applications
Building crowdsourcing applicationsBuilding crowdsourcing applications
Building crowdsourcing applications
 
Evented I/O based web servers, explained using bunnies
Evented I/O based web servers, explained using bunniesEvented I/O based web servers, explained using bunnies
Evented I/O based web servers, explained using bunnies
 
Cowboy development with Django
Cowboy development with DjangoCowboy development with Django
Cowboy development with Django
 
Crowdsourcing with Django
Crowdsourcing with DjangoCrowdsourcing with Django
Crowdsourcing with Django
 
Django Heresies
Django HeresiesDjango Heresies
Django Heresies
 
Class-based views with Django
Class-based views with DjangoClass-based views with Django
Class-based views with Django
 
Web App Security Horror Stories
Web App Security Horror StoriesWeb App Security Horror Stories
Web App Security Horror Stories
 
Web Security Horror Stories
Web Security Horror StoriesWeb Security Horror Stories
Web Security Horror Stories
 
When Zeppelins Ruled The Earth
When Zeppelins Ruled The EarthWhen Zeppelins Ruled The Earth
When Zeppelins Ruled The Earth
 

Recently uploaded

Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeCzechDreamin
 
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...FIDO Alliance
 
WSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxWSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxJennifer Lim
 
Buy Epson EcoTank L3210 Colour Printer Online.pptx
Buy Epson EcoTank L3210 Colour Printer Online.pptxBuy Epson EcoTank L3210 Colour Printer Online.pptx
Buy Epson EcoTank L3210 Colour Printer Online.pptxEasyPrinterHelp
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Julian Hyde
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceSamy Fodil
 
The UX of Automation by AJ King, Senior UX Researcher, Ocado
The UX of Automation by AJ King, Senior UX Researcher, OcadoThe UX of Automation by AJ King, Senior UX Researcher, Ocado
The UX of Automation by AJ King, Senior UX Researcher, OcadoUXDXConf
 
A Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyA Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyUXDXConf
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераMark Opanasiuk
 
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...CzechDreamin
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101vincent683379
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfFIDO Alliance
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfFIDO Alliance
 
IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024IoTAnalytics
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2DianaGray10
 
Designing for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastDesigning for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastUXDXConf
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...CzechDreamin
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlPeter Udo Diehl
 
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FIDO Alliance
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?Mark Billinghurst
 

Recently uploaded (20)

Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
 
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
 
WSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxWSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptx
 
Buy Epson EcoTank L3210 Colour Printer Online.pptx
Buy Epson EcoTank L3210 Colour Printer Online.pptxBuy Epson EcoTank L3210 Colour Printer Online.pptx
Buy Epson EcoTank L3210 Colour Printer Online.pptx
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
The UX of Automation by AJ King, Senior UX Researcher, Ocado
The UX of Automation by AJ King, Senior UX Researcher, OcadoThe UX of Automation by AJ King, Senior UX Researcher, Ocado
The UX of Automation by AJ King, Senior UX Researcher, Ocado
 
A Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyA Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System Strategy
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджера
 
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2
 
Designing for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastDesigning for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at Comcast
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 

Jazz up your JavaScript: Unobtrusive scripting with JavaScript libraries

  • 1. Jazz up your JavaScript Unobtrusive scripting with JavaScript libraries Simon Willison Webstock, 11th February 2008
  • 2. This tutorial • Unobtrusive scripting • JavaScript libraries • Writing unobtrusive scripts with jQuery
  • 3. But first... let’s travel back in time to 2004
  • 4. (The only photo I could find of me in 2004)
  • 5. JavaScript was the ugly duckling of the web standards world
  • 7. DHTML scripts copied and pasted from dynamicdrive.com
  • 8. 3 revolutions since 2004 • Ajax • Unobtrusive scripting • High quality open-source libraries
  • 10.
  • 11.
  • 12. The quieter revolutions were just as important
  • 14. Progressive enhancement Rather than hoping for graceful degradation, PE builds documents for the least capable or differently capable devices first, then moves on to enhance those documents with separate logic for presentation, in ways that don't place an undue burden on baseline devices but which allow a richer experience for those users with modern graphical browser software. Steven Champeon and Nick Finck, 2003
  • 15. Applied to JavaScript • Build a site that works without JavaScript • Use JavaScript to enhance that site to provide a better user experience: easier to interact with, faster, more fun
  • 17.
  • 18.
  • 19. • Start with Plain Old Semantic HTML • Layer on some CSS (in an external stylesheet) to apply the site’s visual design • Layer on some JavaScript (in an external script file) to apply the site’s enhanced behaviour
  • 21. • There are legitimate reasons to switch it off • Some companies strip JavaScript at the firewall • Some people run the NoScript Firefox extension to protect themselves from common XSS and CSRF vulnerabilities • Many mobile devices ignore JS entirely • Screen readers DO execute JavaScript, but accessibility issues mean that you may not want them to
  • 24. labels.js • One of the earliest examples of this technique, created by Aaron Boodman (now of Greasemonkey and Google Gears fame)
  • 25.
  • 26.
  • 27. How it works <label for=quot;searchquot;>Search</label> <input type=quot;textquot; id=quot;searchquot; name=quot;qquot;> • Once the page has loaded, the JavaScript: • Finds any label elements linked to a text field • Moves their text in to the associated text field • Removes them from the DOM • Sets up the event handlers to remove the descriptive text when the field is focused • Clean, simple, reusable
  • 28. easytoggle.js • An unobtrusive technique for revealing panels when links are clicked <ul> <li><a href=quot;#panel1quot; class=quot;togglequot;>Panel 1</a></li> <li><a href=quot;#panel2quot; class=quot;togglequot;>Panel 2</a></li> <li><a href=quot;#panel3quot; class=quot;togglequot;>Panel 3</a></li> </ul> <div id=quot;panel1quot;>...</div> <div id=quot;panel2quot;>...</div> <div id=quot;panel3quot;>...</div>
  • 29.
  • 30.
  • 31. How it works • When the page has loaded... • Find all links with class=quot;togglequot; that reference an internal anchor • Collect the elements that are referenced by those anchors • Hide all but the first • Set up event handlers to reveal different panels when a link is clicked • Without JavaScript, links still jump to the right point
  • 32. Django filter lists • Large multi-select boxes aren't much fun • Painful to scroll through • Easy to lose track of what you have selected • Django's admin interface uses unobtrusive JavaScript to improve the usability here
  • 33.
  • 34.
  • 35. Mapping Microformats • The hCard microformat provides a standard set of CSS classes for marking up an address • Wouldn’t it be great if we could unobtrusively plot them on a Google Map...
  • 36.
  • 37.
  • 38. When the page loads... • Scan through for hCards (by looking for class=quot;vCardquot;) • Extract the street address and postcode for each one • Pass it to the Google Maps geocoder to get the lat/long point • Insert a div for the Google Map, instantiate it and add the points as markers
  • 39. How about Ajax? • Ajax is frequently used to avoid page refreshes • So... • Write an app that uses full page refreshes • Use unobtrusive JS to quot;hijackquot; links and form buttons and use Ajax instead • Jeremy Keith coined the term quot;Hijaxquot; to describe this
  • 41.
  • 42. Bad Have you read our <a href=quot;javascript:window.open( 'terms.html', 'popup', 'height=500,width=400,toolbar=no' );quot;>terms and conditions</a>?
  • 43. Also bad Have you read our <a href=quot;#quot; onclick=quot;window.open( 'terms.html', 'popup', 'height=500,width=400,toolbar=no' ); return false;quot; >terms and conditions</a>?
  • 44. Better Have you read our <a href=quot;terms.htmlquot; onclick=quot;window.open( 'terms.html', 'popup', 'height=500,width=400,toolbar=no' ); return false;quot; >terms and conditions</a>?
  • 45. Better still Have you read our <a href=quot;terms.htmlquot; onclick=quot;window.open( this.href, 'popup', 'height=500,width=400,toolbar=no' ); return false;quot; >terms and conditions</a>?
  • 46. Best Have you read our <a href=quot;terms.htmlquot; class=quot;sidenotequot; >terms and conditions</a>?
  • 47. Characteristics of unobtrusive scripts • No in-line event handlers • All code is contained in external .js files • The site remains usable without JavaScript • Existing links and forms are repurposed • JavaScript dependent elements are dynamically added to the page
  • 48. Handling events function makeLinkPopup(link) { if (link.addEventListener) { // W3C spec browsers link.addEventListener('click', popupClicked, false); } else if (link.attachEvent) { // Internet Explorer link.attachEvent('onclick', popupClicked); } else { return; // Fail silently in ancient browsers } }
  • 49. Handling events (2) function popupClicked(ev) { // Find the link that was clicked ev = ev || window.event; var link = ev.target || ev.srcElement; if (link.nodeType == 3) { // Safari bug fix link = link.parentNode; } window.open(link.href, 'popup', 'height=500,width=400,toolbar=no'); // Now prevent the default link action if (ev.preventDefault) { ev.preventDefault(); // W3C spec browsers } else { ev.returnValue = false; // Internet Explorer } }
  • 50. Handling events (3) function setupLinks() { var links = document.getElementsByTagName('a'); for (var i = 0, link; link = links[i]; i++) { if (link.className == 'sidenote') { makeLinkPopup(link); } } } if (window.addEventListener) { window.addEventListener('load', setupLinks, false); } else if (window.attachEvent) { window.attachEvent('onload', setupLinks); }
  • 51. That’s way too much nasty boilerplate
  • 52. Unobtrusive challenges • Adding events from pure script (avoiding inline script handlers) works differently between IE and other browsers • Cancelling default actions (link navigation, form submission) also works differently • Scripts that add behaviour need to execute as soon as the DOM is available
  • 53. The onload problem • All of these examples use code that runs when the window quot;loadquot; event is fired • Wait until page is loaded, then manipulate the DOM • Problem: If the page takes a while to load (large inline images) there will be a Flash Of Unstyled Content (FOUC) • Also, if the user clicks things before the setup code has fired they won't get the expected behaviour.
  • 54. onDOMReady • A number of attempts have been made to create an onDOMReady event that fires when the DOM has been constructed but before the page has loaded • dean.edwards.name/weblog/2006/06/again/ • Modern libraries all support this in some form • One caveat: CSS may not have loaded, so calculated dimensions may be incorrect
  • 55. So we need libraries • Writing this stuff by hand is madness • Boilerplate code to deal with browser inconsistencies is the number one enemy of unobtrusive scripting • Thankfully, today these are all solved problems
  • 57. Controversial statement • A year ago, there was a sizable debate over whether libraries were worth using at all - many people preferred to just “roll their own” • Today, that argument is over. Libraries have won. • (some may disagree)
  • 58. “The bad news: JavaScript is broken. The good news: It can be fixed with more JavaScript!” Geek folk saying
  • 59. JavaScript characteristics • Highly dynamic language • Most things can be introspected • Most things can be modified at runtime • Functional programming, anonymous functions and closures • Ability to modify behaviour of built-in types • Prototypal inheritance - arguably more powerful than class-based inheritance, though much less widely understood
  • 60. Modifying built-in types var s = quot;This is a stringquot;; alert(s.dasherize()); // Throws an error String.prototype.dasherize = function() { return this.toLowerCase().replace(/s+/g, '-'); } alert(s.dasherize()); // this-is-a-string
  • 61. Functional programming function hello() { alert(quot;helloquot;); } var hello = function() { alert(quot;helloquot;); } (function() { alert(quot;helloquot;); })();
  • 62. Functional programming function hello() { alert(quot;helloquot;); } var hello = function() { alert(quot;helloquot;); } (function() { alert(quot;helloquot;); })();
  • 63. Functional programming function hello() { alert(quot;helloquot;); } var hello = function() { alert(quot;helloquot;); } (function() { alert(quot;helloquot;); })();
  • 64. Closures function outer() { var s = quot;This is a stringquot;; function inner() { alert(s); } inner(); }
  • 65. Closures function outer() { var s = quot;This is a stringquot;; function inner() { alert(s); } return inner; } var func = outer(); func(); // Alerts quot;This is a stringquot;;
  • 66. Closures function outer(s) { function inner() { alert(s); } return inner; } var sayHello = outer(quot;Helloquot;); var sayGoodbye = outer(quot;Goodbyequot;); sayHello(); sayGoodbye();
  • 67. Common library features
  • 68. DOM selection • document.getElementById shortcut • Get elements by class name • Get elements by CSS selector
  • 69. CSS manipulation • Manipulate and toggle classes • Set styles (including opacity) • Introspect applied styles
  • 70. Event handling • Cross-browser “run this function when this event happens to this element” • Cross-browser “on DOM ready” support • Cross-browser event introspection: where was the event targetted? • Event triggering • Custom events
  • 71. Ajax • Cross-browser XMLHttpRequest • Easier API for GET, POST and URL and form manipulation • Support for Ajax formats: HTML fragments, JSON, XML
  • 72. Effects and animation • Fades, wipes and transitions • Custom animation of any CSS property • Automatic frame-rate management • Easing
  • 73. Widgets • Packaged widgets for things like... • Sliders • Calendar date pickers • Fake “windows” • Auto-completers • Grids and treeviews • Support for drag-and-drop
  • 74. Language tools • Iteration over objects and arrays • Utilities for managing prototypal inheritance • Traditional class-based inheritance • Tools for managing scope and callbacks • Dynamic code loading
  • 75. Array manipulation for (var i = 0; i < arr.length; i++) { var item = arr[i]; // process item } forEach(arr, function(item) { // process item }); doubles = map(arr, function(i) { return i * 2 }); evens = filter(arr, function(i) { return i % 2 == 0 });
  • 76. Other characteristics • Do they modify built in types? • Global namespace impact • Library size and componentization • Support for accessibility (esp. for widgets) • Browser support • Documentation • Community
  • 77. The big five • The Yahoo! User Interface Library • Prototype (and Script.aculo.us) • The Dojo Toolkit • mooTools • jQuery
  • 78. The Example • A login form that shakes its head at you • Standard POST login form, unobtrusively upgraded to use Ajax and shake if the password is incorrect • Behind the scenes, JSON is used for the reply to say if the password was correct or not
  • 79. Simple login JSON API • Responds to the same POST as the regular form, but looks for X-Requested-With: XMLHttpRequest header • If login fails, returns {quot;okquot;:false} • If login succeeds, returns {quot;okquot;: true, quot;redirectquot;: quot;loggedin.phpquot;}
  • 80. The Yahoo! User Interface Library
  • 81. controls (aka widgets) autocomplete calendar container menu slider treeview animation dragdrop dom event connection utilities
  • 82. YAHOO.util.Event.onDOMReady(function() { var $E = YAHOO.util.Event; var $D = YAHOO.util.Dom; var $C = YAHOO.util.Connect; var query = YAHOO.util.Selector.query; $D.get('username').focus(); var form = query('form')[0];
  • 83. YAHOO.util.Event.onDOMReady(function() { var $E = YAHOO.util.Event; var $D = YAHOO.util.Dom; var $C = YAHOO.util.Connect; var query = YAHOO.util.Selector.query; $D.get('username').focus(); var form = query('form')[0];
  • 84. YAHOO.util.Event.onDOMReady(function() { var $E = YAHOO.util.Event; var $D = YAHOO.util.Dom; var $C = YAHOO.util.Connect; var query = YAHOO.util.Selector.query; $D.get('username').focus(); var form = query('form')[0];
  • 85. YAHOO.util.Event.onDOMReady(function() { var $E = YAHOO.util.Event; var $D = YAHOO.util.Dom; var $C = YAHOO.util.Connect; var query = YAHOO.util.Selector.query; $D.get('username').focus(); var form = query('form')[0];
  • 86. $E.on(form, 'submit', function(ev) { $E.preventDefault(ev); var url = form.action; $C.setForm(form); $C.asyncRequest( 'POST', url, { success: function() { ... } } ); });
  • 87. success: function(response) { var json = eval('(' + response.responseText + ')'); if (json.ok) { window.location = json.redirect; } else { $D.get('password').value = ''; $D.get('password').focus(); shake(form, function() { if (!query('p.error').length) { var p = document.createElement('p'); p.className = 'error'; p.innerHTML = 'Incorrect password.'; form.insertBefore(p, form.firstChild); } }); }
  • 88. function shake(el, onComplete) { var $D = YAHOO.util.Dom; $D.setStyle(el, 'position', 'relative'); var anim = new YAHOO.util.Anim(el, { left: {to: -10} }, 0.1, YAHOO.util.Easing.easeOut); anim.onComplete.subscribe(function() { // ... } anim.animate(); }
  • 89. function shake(el, onComplete) { var $D = YAHOO.util.Dom; $D.setStyle(el, 'position', 'relative'); var anim = new YAHOO.util.Anim(el, { left: {to: -10} }, 0.1, YAHOO.util.Easing.easeOut); anim.onComplete.subscribe(function() { var anim2 = new YAHOO.util.Anim(el, { left: {to: 10} }, 0.1, YAHOO.util.Easing.easeOut); anim2.onComplete.subscribe(function() { var anim3 = new YAHOO.util.Anim(el, { left: {to: -10} }, 0.1, YAHOO.util.Easing.easeOut); anim3.onComplete.subscribe(function() { var anim4 = new YAHOO.util.Anim(el, { left: {to: 10} }, 0.1, YAHOO.util.Easing.easeOut); anim4.onComplete.subscribe(function() { var anim5 = new YAHOO.util.Anim(el, { left: {to: 0} }, 0.1, YAHOO.util.Easing.easeOut); if (onComplete) { anim5.onComplete.subscribe(onComplete); } anim5.animate(); }); anim4.animate(); }); anim3.animate(); }); anim2.animate(); }); anim.animate(); }
  • 90. • Nice animation library, but a better way of chaining animations would be useful • Severe namespacing (YAHOO was picked because it was so ugly no one would ever have used it for an existing variable) • Not too many shortcuts outside of dealing with browser difficulties • Excellent documentation
  • 91. Download Get the latest version—1.5.1 Learn Prototype is a JavaScript Framework that aims to Online documentation and resources. ease development of dynamic web applications. Featuring a unique, easy-to-use toolkit for class-driven Discuss development and the nicest Ajax library around, Prototype Mailing list and IRC is quickly becoming the codebase of choice for web application developers everywhere. Contribute Prototype and Script.aculo.us Prototype and script.aculo.us: The quot;Bungee bookquot; has landed! Submit patches and report bugs. Who's using Prototype? Meet the developers Core team member Christophe Porteneuve has been hard at work for the past few months tracking
  • 92. document.observe('dom:loaded', function() { $('username').focus(); var form = $$('form')[0]; form.observe('submit', function(ev) { ev.preventDefault(); var url = form.action; new Ajax.Request(url, { parameters: form.serialize(), onSuccess: ... }); }); });
  • 93. onSuccess: function(response) { var json = response.responseJSON; if (json.ok) { window.location = json.redirect; } else { form.shake(); // No apparent way of setting an // quot;on finishedquot; callback setTimeout(function() { if (!$$('p.error').length) { var p = new Element( 'p', {'class': 'error'} ).insert('Incorrect...'); form.insertBefore(p, form.firstChild); } }, 500); $('password').value = ''; $('password').focus(); } }
  • 94. • Adds many functions to the global namespace ($, $$ etc) and extensively modifies built in types • Heavily inspired by Ruby and Ruby on Rails • Useful shortcuts and nice effects • Documentation still leaves something to be desired - API docs for Prototype, incomplete wiki docs for Scriptaculous
  • 96. dojo.require('dojox.fx'); djConfig.usePlainJson = true; dojo.addOnLoad(function() { dojo.byId('username').focus(); dojo.query('form').connect('submit', function(ev) { dojo.stopEvent(ev); var form = this; var url = form.action; dojo.xhrPost({ handleAs: 'json', headers: {'X-Requested-With': 'XMLHttpRequest'}, url: url, form: form, load: function(json) { ... } }); }); });
  • 97. load: function(json) { if (json.ok) { window.location = json.redirect; } else { form.style.position = 'relative'; var last = dojo.animateProperty({ node: form, duration: 100, properties: {left: {end: 0}} }); var leftArgs = { node: form, duration: 100, properties: {left: {end: -10}} }; var rightArgs = { node: form, duration: 100, properties: {left: {end: 10}} }; dojo.fx.chain([ dojo.animateProperty(leftArgs), dojo.animateProperty(rightArgs), dojo.animateProperty(leftArgs), dojo.animateProperty(rightArgs), last ]).play();
  • 98. dojo.connect(last, 'onEnd', function() { if (!dojo.query('p.error').length) { var p = document.createElement('p'); p.className = 'error'; p.innerHTML = 'Incorrect username or password.'; form.insertBefore(p, form.firstChild); } }); dojo.byId('password').value = ''; dojo.byId('password').focus();
  • 99. • core, dijit and dojox: • Small, powerful abstraction library • Widget creation tools plus many widgets • “The future today” genius extensions • Documentation has improved with the Dojo Book, but still patchy in places
  • 101. window.addEvent('domready', function() { $('username').focus(); $$('form').addEvent('submit', function(ev) { new Event(ev).stop(); var form = this; var url = form.action; form.send({ onComplete: function(data) { var json = Json.evaluate(data); if (json.ok) { window.location = json.redirect; } else { form.style.position = 'relative'; // ... animation here $('password').value = ''; $('password').focus(); } } }); }); });
  • 102. var fx = form.effects({ duration: 100, transition: Fx.Transitions.Quart.easeOut }); fx.start({left: -10}).chain(function(){ this.start({left: 10}); }).chain(function(){ this.start({left: -10}); }).chain(function(){ this.start({left: 10}); }).chain(function(){ this.start({left: 0}); }).chain(function() { if (!$$('p.error').length) { var p = new Element('p'). addClass('error').setHTML( 'Incorrect username or password.' ); form.insertBefore(p, form.firstChild); } });
  • 103. Started as an effects library for Prototype, now its own thing but Prototype influences are clear • No intention at all of playing nicely with other libraries • Good API documentation (including a mootorial) but not much else, and major changes between library versions • I found the API unintuitive compared to the others
  • 104. jQuery
  • 105. jQuery(function($) { $('#username').focus(); $('form').submit(function() { var $this = $(this); var url = $this.attr('action'); var data = $this.serialize(); jQuery.post(url, data, function(json) { if (json.ok) { window.location = json.redirect; } else { $('#password').val('').focus(); $this.shake(function() { if (!$this.find('p.error').length) { $this.prepend('<p class=quot;errorquot;>Incorrect ...</p>'); } }); } }, 'json'); return false; }); });
  • 106. jQuery.fn.shake = function(callback) { this.css({'position': 'relative'}); return this.animate( {left: '-10px'}, 100 ).animate( {left: '+10px'}, 100 ).animate( {left: '-10px'}, 100 ).animate( {left: '+10px'}, 100 ).animate( {left: '0px'}, 100, callback ); };
  • 107. • Powerful, concise API based around CSS selector querying and chaining • Excellent namespace management - everything lives on the one jQuery symbol which is aliased to $, with the option to revert • Excellent support for plugins • The best documentation out of all of the libraries
  • 108. Unobtrusive scripting with jQuery
  • 109. Why jQuery • It has the best balance between simplicity, productivity and good manners • It has excellent documentation • You can learn the whole library in less than an hour
  • 110. Why jQuery instead of...? • Unlike Prototype and mooTools... • ... it doesn’t populate your global namespace • Unlike YUI... • ... it’s extremely succinct • Unlike Dojo... • ... you can learn it in 45 minutes!
  • 112. jQuery philosophy • Focus on the interaction between JavaScript and HTML • (Almost) every operation boils down to: • Find some stuff • Do something to it
  • 113. Sidenotes with jQuery jQuery(function($) { $('a.sidenote').click(function() { window.open($(this).attr('href'), 'popup', 'height=500,width=400,toolbar=no'); return false; }); });
  • 114. Only one function! • Absolutely everything* starts with a call to the jQuery() function • Since it’s called so often, the $ variable is set up as an alias to jQuery • If you’re also using another library you can revert to the previous $ function with jQuery.noConflict(); * not entirely true
  • 117. CSS 2 and 3 selectors a[rel] a[rel=quot;friendquot;] a[href^=quot;http://quot;] ul#nav > li li#current ~ li (li siblings that follow #current) li:first-child, li:last-child, li:nth-child(3)
  • 118. Magic selectors div:first, h3:last :header :hidden, :visible :animated :input, :text, :password, :radio, :submit... div:contains(Hello)
  • 119. jQuery collections • $('div.section') returns a jQuery collection • You can treat it like an array $('div.section').length = no. of matched elements $('div.section')[0] - the first div DOM element $('div.section')[1] $('div.section')[2]
  • 120. jQuery collections • $('div.section') returns a jQuery collection • You can call methods on it $('div.section').size() = no. of matched elements $('div.section').each(function() { console.log(this); });
  • 121. jQuery collections • $('div.section') returns a jQuery collection • You can call methods on it $('div.section').size() = no. of matched elements $('div.section').each(function(i) { console.log(quot;Item quot; + i + quot; is quot;, this); });
  • 122. HTML futzing $('span#msg').text('The thing was updated!'); $('div#intro').html('<em>Look, HTML</em>');
  • 123. Attribute futzing $('a.nav').attr('href', 'http://flickr.com/'); $('a.nav').attr({ 'href': 'http://flickr.com/', 'id': 'flickr' }); $('#intro').removeAttr('id');
  • 125. Grabbing values • Some methods return results from the first matched element var height = $('div#intro').height(); var src = $('img.photo').attr('src'); var lastP = $('p:last').html() var hasFoo = $('p').hasClass('foo'); var email = $('input#email').val();
  • 126. Traversing the DOM • jQuery provides enhanced methods for traversing the DOM $('div.section').parent() $('div.section').next() $('div.section').prev() $('div.section').nextAll('div') $('h1:first').parents()
  • 127. Handling events $('a:first').click(function(ev) { $(this).css({backgroundColor: 'orange'}); return false; // Or ev.preventDefault(); });
  • 128. Handling events $('a:first').click(function(ev) { $(this).css({backgroundColor: 'orange'}); return false; // Or ev.preventDefault(); }); $('a:first').click();
  • 129. Going unobtrusive $(document).ready(function() { alert('The DOM is ready!'); });
  • 130. Going unobtrusive $(function() { alert('The DOM is ready!'); });
  • 131. Going unobtrusive jQuery(function($) { alert('The DOM is ready!'); });
  • 132. Chaining • Most jQuery methods return another jQuery object - usually one representing the same collection. This means you can chain methods together: $('div.section').hide().addClass('gone');
  • 133. Advanced chaining • Some methods return a different collection • You can call .end() to revert to the previous collection
  • 134. Advanced chaining • Some methods return a different collection • You can call .end() to revert to the previous collection $('#intro').css('color', '#cccccc'). find('a').addClass('highlighted').end(). find('em').css('color', 'red').end()
  • 135. Ajax • jQuery has excellent support for Ajax $('div#intro').load('/some/file.html'); • More advanced methods include: $.get(url, params, callback) $.post(url, params, callback) $.getJSON(url, params, callback) $.getScript(url, callback)
  • 136. Animation • jQuery has built in effects: $('h1').hide('slow'); $('h1').slideDown('fast'); $('h1').fadeOut(2000); • You can chain them: $('h1').fadeOut(1000).slideDown()
  • 137. Or roll your own... $(quot;#blockquot;).animate({ width: quot;+=60pxquot;, opacity: 0.4, fontSize: quot;3emquot;, borderWidth: quot;10pxquot; }, 1500);
  • 138. Plugins • jQuery is extensible through plugins, which can add new methods to the jQuery object
  • 139. Further reading • http://jquery.com/ • http://docs.jquery.com/ • http://visualjquery.com/ - API reference • http://simonwillison.net/tags/jquery/ • http://simonwillison.net/2007/Aug/15/jquery/ • http://24ways.org/2007/unobtrusively- mapping-microformats-with-jquery