1. CRASH COURSE

    in Prototype & Scriptaculous

  2. version 1.5.1

    (released just last week)

  3. open-source

    (MIT-licensed; do what you want)

  4. Distributed with Ruby on Rails

    (but lots of people use it outside of Rails)

  5. People like...

    ABC, Amazon, Apple, CNET, Digg, ESPN, Feedburner, last.fm, NBC, Tivo...

  6. Yes, we have documentation

    http://prototypejs.org

    Site
  7. No Ruby experience needed

    (but it wouldn't hurt)

  8. Borrows from Ruby

    (but still feels like JavaScript)

    # Ruby  
    %w{zero one two three three two one}.uniq.reverse
    #-> ["three", "two", "one", "zero"]
    // Prototype-flavored JavaScript
    $w('zero one two three three two one').uniq().reverse()
    //-> ["three", "two", "one", "zero"]
  9. Library or Framework?

  10. A bit of both, really

  11. Library

  12. Framework

  13. Utility methods

    (the really handy stuff)

  14. $: Query by ID

    // why do this...
    document.getElementById('foo');
    // when you can do this?
    $('foo');
    
  15. $: Query by ID

    // especially since getElementById can't do...
    var foo = $('foo');
    //-> <div#foo>
    $(foo);
    //-> <div#foo>
    
    // or this:
    $('foo', 'bar', 'baz');
    //-> [<div#foo>, <div#bar>, <div#baz>]
    
  16. $$: Query by CSS selector

    $$('li.slide');
    //-> [<li.slide>, <li.slide>, <li.slide>...]
    
    $$('li.slide > h1');
    //-> [<h1>, <h1>, <h1>...]
    
    $$('ol.presentation > li:first-child');
    //-> [<li.title-slide>]
    
    $$('a[rel~=external]');
    //-> [<a>, <a>, <a>...]
    
    $$('ol.presentation > li:not(.slide)');
    //-> []
    
  17. Hiding/showing elements

    <div id="show-on-load">
    <!-- first time running the app, blah blah blah -->
    Here's some stuff you need to know...
    </div>
    
  18. Hiding/showing elements

    var showOnLoad = $('show-on-load');
    //-> <div id="show-on-load">
    showOnLoad.hide();
    //-> <div id="show-on-load" style="display: none;">
    
  19. Adding/removing class names

    $('show-on-load').className = 'active';
    // BAD IDEA ↑
    $('show-on-load').addClassName('active');
    $('show-on-load').removeClassName('active');
  20. Add your own instance methods

    Element.addMethods({
      waffles: function() { return "waffles!"; }
    });
    
    $('foo').waffles(); //-> "waffles!"
    
    
  21. Generics

    (all instance methods on elements can be called statically)

    Element.addClassName('show-on-load', 'active');
    Element.waffles('foo') //-> "waffles!"
  22. Dead-simple Ajax

  23. Without a framework

    var xhr;
      
    // Firefox, Opera, Safari, IE7
    if (window.XMLHttpRequest)
      xhr = new XMLHttpRequest();
    
    // IE 5-6
    try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } 
    catch (e) {
      try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } 
      catch (e) { throw 'Ajax not supported!' }
    }

    (and that's just to get the Ajax object)

  24. With Prototype

    new Ajax.Request('/some/url');
    // no, seriously, you're done
  25. Using callbacks

    
    new Ajax.Request('/some/url', {
      onComplete: function(req) { alert(req.responseText); }
      on404: function(req) { alert("file not found"); }
      on500: function(req) { alert("something went wrong"); }
    });
  26. Ajax.Updater

    new Ajax.Updater('show-on-load', '/welcome_message.html');
    //  fills this element ↑   with this URL's content ↑
    
  27. Events

  28. Define a handler

    function makeRed(event) {
      var node = Event.element(event); // the node that was clicked on
      node.style.color = "red";
    }
  29. Wraps two different event systems

    (IE's and everyone else's)

  30. Event.observe

    Event.observe('top_bar', 'click', makeRed);
    // or...
    $('top_bar').observe('click', makeRed);
    
  31. Event.stopObserving

    Event.stopObserving('top_bar', 'click', makeRed);
    // or...
    $('top_bar').stopObserving('click', makeRed);
  32. Huge overhaul coming in 1.6

    (whenever that may be)

  33. Enumerables

    (stuff in groups)

  34. for loops suck

    for (var i = 0; i < nodes.length; i++) {
      node = nodes[i];
      node.hide();
    }
  35. Why do I care about i?

    (don't bother me with implementation details)

  36. We need better enumeration

  37. Enumerable to the rescue

    nodes.each( function(node) { node.hide(); });
  38. Works with named functions, too

    function makeRed(node) {
      node.style.color = "red";
    }
    
    nodes.each(makeRed);
    
  39. Enumerable#map

    [1, 2, 3, 4].map( function(n) { return n * n; });
    //-> [1, 4, 9, 16]
    
  40. Enumerable#select, #reject, #detect, #partition

    function isEven(num) { return num % 2 == 0; }
    var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    numbers.select(isEven);
    //-> [2, 4, 6, 8, 10]
    numbers.reject(isEven);
    //-> [1, 3, 5, 7, 9]
    numbers.detect(isEven);
    //-> 2
    numbers.partition(isEven);
    //-> [ [2, 4, 6, 8, 10], [1, 3, 5, 7, 9] ]
  41. Enumerable#invoke

    "  foo     ".strip(); //-> "foo"
    ["  foo     ", "         bar", "  baz  "].invoke('strip');
    //-> ["foo", "bar", "baz"]
    
  42. Enumerable#invoke

    (passes arguments, too)

    // bulk event listening:
    $$('li.active').invoke('observe', 'click', makeRed);
    
    // zebra-striping tables:        
    $$('table tbody > tr:nth-child(even)').invoke('addClassName', 'stripe');
  43. Enumerable#pluck

    (like invoke, but for properties)

    <ul id="menu">
      <li id="home">Home</li>
      <li id="about">About Us</li>
      <li id="products">Products</li>
      <li id="help">Help</li>
    </ul>
    $$('#menu li').pluck('id');
    //-> ["home", "about", "products", "help"]
    
  44. Working with the DOM

  45. Easy DOM Traversal

    <div id="usa">
      <ol id="tx">
        <li id="hou">Houston</li>
        <li id="dal">Dallas</li>
        <li id="sa">San Antonio</li>
        <li id="aus">Austin</li>
      </ol>
    </div>
  46. Easy DOM Traversal

    $('usa').down(); //-> <ol#tx>
    $('usa').down('li'); //-> <li#hou>
    $('usa').down('li', 1); //-> <li#dal>
    $('aus').up('div'); //-> <div#usa>
    $('sa').next(); //-> <li#aus>
    
  47. Context-specific node queries

    $('usa').descendants();
    //-> [<ol#tx>, <li#hou>, <li#dal>, <li#sa>, <li#aus>]
    
    $('aus').ancestors();
    //-> [<ol#tx>, <div#usa>, ... (all the way up to <body>)]
    
    $('usa').getElementsBySelector('li');
    //-> [<li#hou>, <li#dal>, <li#sa>, <li#aus>]
  48. Forms

  49. $F

    Fetch form values

    <input type="text" id="first_name" name="first_name" value="Andrew" />
    
    $F('first_name'); //-> "Andrew"
  50. Handy instance methods

    (on forms and form controls)

    someForm.disable(); //-> disables entire form
    someFormControl.disable(); //-> disables control
  51. Form Serialization

    <form method="post" action="submit-form.php" id="sample">
      <input type="text" name="first_name" value="Andrew" />
      <input type="text" name="last_name" value="Dupont" />
      <select name="country">
        <option value="USA" selected="selected">United States</option>
        <option value="UK">United Kingdom</option>
      </select>
    </form>
  52. Form Serialization

    $('sample').serialize();
    //-> "first_name=Andrew&last_name=Dupont&country=USA"
  53. Form#request

    (ajax + graceful degradation!)

    $('sample').request({ 
      onSuccess: function(req) {
        $('sample').replace(req.responseText);
      }
    });
  54. JSON

  55. Serializing Objects

    var airports = {
      AUS: "Austin/Bergstrom Int'l",
      IAH: "Houston/Intercontinental",
      HOU: "Houston/Hobby",
      DAL: "Dallas/Love Field",
      DFW: "Dallas-Fort Worth Int'l"
    };
  56. Serializing Objects

    var json = Object.toJSON(airports);
    //-> '{"AUS": "Austin/Bergstrom Int\'l", "IAH": "Houston/Intercontinental", "HOU": "Houston/Hobby", "DAL": "Dallas/Love Field", "DFW": "Dallas-Fort Worth Int\'l"}'
    
    json.evalJSON(); //-> [Object]
  57. Scriptaculous Logo
  58. Prototype + [bells & whistles]

  59. Also distributed with Rails

  60. Also has documentation

    http://wiki.script.aculo.us

    Scriptaculous
  61. Effects

    (modifying CSS properties over time)

  62. Math is hard :-(

    function blackToWhite(node) {
      /* FRUSTRATINGLY COMPLEX ALGORITHM */
      node.style.color = slightlyLighterShadeOfGray(node.style.color);
      
      if (node.style.color != "#FFFFFF")
        window.setTimeout(function() { blackToWhite(node) }, 20);
    }
  63. Tweening

    (getting from A to B)

  64. Effect.Morph figures it out

    new Effect.Morph('morph_example', { 
      style: "background-color: #fff; color: #000", 
      duration: 1.0
    });
    Example
  65. Wait — it gets better

    .warning { background-color: #900; color: #fff; }
    new Effect.Morph('morph_example_2', { style: 'warning' });
    Example
  66. Core effects

    new Effect.Move('move_example', { 
      x: 0, 
      y: 50,
      duration: 1.0
    });
    Example
  67. Core effects

    new Effect.Opacity('opacity_example', { 
      from: 1.0, 
      to: 0.5, 
      duration: 1.5
    });
    Example
  68. Combination effects

    new Effect.Pulsate('pulsate_example', { pulses: 4 });
    Example
  69. Make your own!

    (http://www.thinkvitamin.com/features/ajax/create-your-own-ajax-effects)