Upgrade to Pro — share decks privately, control downloads, hide ads and more …

script.aculo.us

 script.aculo.us

Christophe Porteneuve

July 25, 2007
Tweet

More Decks by Christophe Porteneuve

Other Decks in Technology

Transcript

  1. This is an intro, yet... • It’s better if you

    do know some Prototype ‣ script.aculo.us relies heavily on it
  2. This is an intro, yet... • It’s better if you

    do know some Prototype ‣ script.aculo.us relies heavily on it ‣ If you just attended one of the Prototype sessions this morning, you should be fine
  3. This is an intro, yet... • It’s better if you

    do know some Prototype ‣ script.aculo.us relies heavily on it ‣ If you just attended one of the Prototype sessions this morning, you should be fine • As for script.aculo.us, we’ll skim the surface and showcast the features.
  4. Who am I? • 29, lives in Paris. Web work

    since 1995 • Prototype Core member
  5. Who am I? • 29, lives in Paris. Web work

    since 1995 • Prototype Core member • Rails & script.aculo.us contributor
  6. Who am I? • 29, lives in Paris. Web work

    since 1995 • Prototype Core member • Rails & script.aculo.us contributor • Prototype doc writer (prototypejs.org)
  7. Who am I? • 29, lives in Paris. Web work

    since 1995 • Prototype Core member • Rails & script.aculo.us contributor • Prototype doc writer (prototypejs.org) • Prototype & script.aculo.us book author
  8. Who am I? • 29, lives in Paris. Web work

    since 1995 • Prototype Core member • Rails & script.aculo.us contributor • Prototype doc writer (prototypejs.org) • Prototype & script.aculo.us book author • Top question batter on the Google Group
  9. What are we going to see? • Visual effects •

    Drag and drop, re-orderable elements
  10. What are we going to see? • Visual effects •

    Drag and drop, re-orderable elements • Autocompletion
  11. What are we going to see? • Visual effects •

    Drag and drop, re-orderable elements • Autocompletion • In-place editing
  12. What are we going to see? • Visual effects •

    Drag and drop, re-orderable elements • Autocompletion • In-place editing • Sliders
  13. What are we going to see? • Visual effects •

    Drag and drop, re-orderable elements • Autocompletion • In-place editing • Sliders • Concise DOM building
  14. Overview • No Flash, no SVG, just plain JS/CSS/DOM! •

    6 Core Effects, 18 Combined Effects
  15. Overview • No Flash, no SVG, just plain JS/CSS/DOM! •

    6 Core Effects, 18 Combined Effects • 9 “transitions” (control acceleration)
  16. Overview • No Flash, no SVG, just plain JS/CSS/DOM! •

    6 Core Effects, 18 Combined Effects • 9 “transitions” (control acceleration) • Fine-tune: 8 generic options, 7 callbacks
  17. Overview • No Flash, no SVG, just plain JS/CSS/DOM! •

    6 Core Effects, 18 Combined Effects • 9 “transitions” (control acceleration) • Fine-tune: 8 generic options, 7 callbacks • Queues to sync timelines
  18. Overview • No Flash, no SVG, just plain JS/CSS/DOM! •

    6 Core Effects, 18 Combined Effects • 9 “transitions” (control acceleration) • Fine-tune: 8 generic options, 7 callbacks • Queues to sync timelines • Custom effects easy to implement
  19. Triggering an effect • new Effect.Name(element[, arg][, options]) ‣ Mandatory

    argument sometimes (e.g. Scale) ‣ As usual, a hash of options. Many effects feature specific options in addition of the 8 generic ones.
  20. Triggering an effect • new Effect.Name(element[, arg][, options]) ‣ Mandatory

    argument sometimes (e.g. Scale) ‣ As usual, a hash of options. Many effects feature specific options in addition of the 8 generic ones. new Effect.Opacity('header', { to: 0.5 });
  21. Triggering an effect • new Effect.Name(element[, arg][, options]) ‣ Mandatory

    argument sometimes (e.g. Scale) ‣ As usual, a hash of options. Many effects feature specific options in addition of the 8 generic ones. new Effect.Opacity('header', { to: 0.5 }); new Effect.Highlight('notice', { duration: 2 });
  22. Triggering an effect • new Effect.Name(element[, arg][, options]) ‣ Mandatory

    argument sometimes (e.g. Scale) ‣ As usual, a hash of options. Many effects feature specific options in addition of the 8 generic ones. new Effect.Opacity('header', { to: 0.5 }); new Effect.Highlight('notice', { duration: 2 }); new Effect.Scale('mugshot', 200, { scaleFromCenter: true });
  23. Core effects • Opacity ‣ Alters an element’s opacity. Relies

    on the generic from/to options to define opacity.
  24. Core effects • Opacity ‣ Alters an element’s opacity. Relies

    on the generic from/to options to define opacity. • Move ‣ Absolute or relative movement
  25. Core effects • Opacity ‣ Alters an element’s opacity. Relies

    on the generic from/to options to define opacity. • Move ‣ Absolute or relative movement • Scale ‣ Resizing (impacting textual contents or not)
  26. Core effects • Highlight ‣ Cross-fading background color • Morph

    ‣ Smoothly migrating any set of measurable CSS properties (colors, sizes) in sync!
  27. Core effects • Highlight ‣ Cross-fading background color • Morph

    ‣ Smoothly migrating any set of measurable CSS properties (colors, sizes) in sync! • Parallel ‣ Synchronized execution of multiple effects
  28. Generic options • When to start ‣ delay, queue •

    How fast to go ‣ fps, sync, transition
  29. Generic options • When to start ‣ delay, queue •

    How fast to go ‣ fps, sync, transition • Cutting corners: where to start and stop ‣ from, to
  30. Core Effects demos • Effect.Morph • Using custom queues •

    “Flash Stompers” ‣ Effect.multiple + Element.tagifyText • Creating a custom effect: Effect.Wave
  31. Combined effects • Just like core, except you don’t need

    new • Many symmetrical ones: ‣ Appear/Fade, BlindDown/Up, SlideDown/Up ‣ Grow/Shrink
  32. Combined effects • Just like core, except you don’t need

    new • Many symmetrical ones: ‣ Appear/Fade, BlindDown/Up, SlideDown/Up ‣ Grow/Shrink • And funky ones to boot: ‣ DropOut, Puff, SwitchOff, Squish, Fold, Pulsate, Shake, Transform...
  33. Overview • Custom use / manual setup ‣ Making an

    element draggable ‣ Setting up an element as a drop zone
  34. Overview • Custom use / manual setup ‣ Making an

    element draggable ‣ Setting up an element as a drop zone ‣ Controlling drag, restricting drops
  35. Overview • Custom use / manual setup ‣ Making an

    element draggable ‣ Setting up an element as a drop zone ‣ Controlling drag, restricting drops • Foremost use-case: re-orderable elements
  36. Making stuff draggable • new Draggable(element[, options]) • How easier

    can it get?! • Can be disabled by calling destroy() on the Draggable instance.
  37. Dragging, my way. • Reverting • Movement restrictions (handle) •

    Using specific handles to drag • Staying within a scrolling container
  38. Dragging, my way. • Reverting • Movement restrictions (handle) •

    Using specific handles to drag • Staying within a scrolling container • Delayed triggering, dragging layer, ghosting...
  39. Dragging, my way. • Reverting • Movement restrictions (handle) •

    Using specific handles to drag • Staying within a scrolling container • Delayed triggering, dragging layer, ghosting... • Callbacks on start, drag step, drag release
  40. Dragging demo • A plump Tux wandering on a mini

    Chess board (now that’s an odd sight)
  41. Here’s your drop zone • Droppables.add(element[, options]) • Droppables.remove(element) •

    Callbacks (dropped element & drop zone) • ...do we actually charge clients for this?!
  42. Not letting anybody in • Restricting on CSS class names

    • Restricting on container of origin
  43. It doesn’t have to be lists... • It can be

    any container element, and any child elements
  44. It doesn’t have to be lists... • It can be

    any container element, and any child elements ‣ It doesn’t even have to be all the children
  45. It doesn’t have to be lists... • It can be

    any container element, and any child elements ‣ It doesn’t even have to be all the children ‣ It doesn’t have to be vertical
  46. It doesn’t have to be lists... • It can be

    any container element, and any child elements ‣ It doesn’t even have to be all the children ‣ It doesn’t have to be vertical ‣ You can even swap elements between containers!
  47. It doesn’t have to be lists... • It can be

    any container element, and any child elements ‣ It doesn’t even have to be all the children ‣ It doesn’t have to be vertical ‣ You can even swap elements between containers! • Two callbacks keep you posted on changes
  48. Re-ordering demos • A regular sorted list with callbacks and

    serialization of the updated order • An horizontal list (you gotta love CSS) • Re-ordering part of the <p>’s in a <div> • Playing with multiple lists
  49. Overview • Assisted typing (e.g. Google Suggest) ‣ Terrific to

    reduce misspellings, duplicates... ‣ Helps accelerate the input process
  50. Overview • Assisted typing (e.g. Google Suggest) ‣ Terrific to

    reduce misspellings, duplicates... ‣ Helps accelerate the input process • Processes a ul/li list ‣ CSS can make it look like anything we want
  51. Overview • Assisted typing (e.g. Google Suggest) ‣ Terrific to

    reduce misspellings, duplicates... ‣ Helps accelerate the input process • Processes a ul/li list ‣ CSS can make it look like anything we want • Full keyboard+mouse operation
  52. Overview • Assisted typing (e.g. Google Suggest) ‣ Terrific to

    reduce misspellings, duplicates... ‣ Helps accelerate the input process • Processes a ul/li list ‣ CSS can make it look like anything we want • Full keyboard+mouse operation • Suggested items can be content-rich
  53. The basics • new Ajax.Autocompleter(element, container, url[, options]) • A

    few CSS rules won’t hurt, too. • Plenty of cool options
  54. The basics • new Ajax.Autocompleter(element, container, url[, options]) • A

    few CSS rules won’t hurt, too. • Plenty of cool options ‣ autoSelect, minChars, frequency...
  55. The basics • new Ajax.Autocompleter(element, container, url[, options]) • A

    few CSS rules won’t hurt, too. • Plenty of cool options ‣ autoSelect, minChars, frequency... ‣ AJAX is 98% of use cases; can also be local...
  56. Dealing with rich contents • Often suggesting texts alone is

    insufficient • Example: company’s internal directory ‣ Just how many “John Smith” are at GE/BofA?
  57. Dealing with rich contents • Often suggesting texts alone is

    insufficient • Example: company’s internal directory ‣ Just how many “John Smith” are at GE/BofA? • Bringing up more info helps the user ‣ Dept. name, photo, dates, file sizes, whatever ‣ But completion should still extract our text
  58. Multiple-field completion • “John Smith, Corporate Accts” looks nice, but

    the server will hate it ‣ Why don’t you send it a nice person_id? ‣ You don’t want your server’s hatred...
  59. Multiple-field completion • “John Smith, Corporate Accts” looks nice, but

    the server will hate it ‣ Why don’t you send it a nice person_id? ‣ You don’t want your server’s hatred... • So we should hook up on the completion and grab more info from the selected entry ‣ Complete multiple fields, visible or hidden...
  60. Autocompletion demo • Consolidated demo ‣ AJAX completion based on

    installed Ruby libraries ‣ Rich contents ‣ Can complete multiple entries in the same field
  61. Overview • Makes any document fragment editable ‣ Right there,

    right then: in place • Numerous options address most needs
  62. Overview • Makes any document fragment editable ‣ Right there,

    right then: in place • Numerous options address most needs ‣ Working on an alternate text (i.e. not HTML)
  63. Overview • Makes any document fragment editable ‣ Right there,

    right then: in place • Numerous options address most needs ‣ Working on an alternate text (i.e. not HTML) ‣ Customize editor controls
  64. Overview • Makes any document fragment editable ‣ Right there,

    right then: in place • Numerous options address most needs ‣ Working on an alternate text (i.e. not HTML) ‣ Customize editor controls ‣ Offer a dropdown list instead of free typing
  65. Overview • Makes any document fragment editable ‣ Right there,

    right then: in place • Numerous options address most needs ‣ Working on an alternate text (i.e. not HTML) ‣ Customize editor controls ‣ Offer a dropdown list instead of free typing • Recently 100% rewritten: clean-slate code
  66. A simple editable fragment • new Ajax.InPlaceEditor(element, url[, options]) ‣

    Uses an OK button and a Cancel link ‣ Binds to Return and Esc
  67. A simple editable fragment • new Ajax.InPlaceEditor(element, url[, options]) ‣

    Uses an OK button and a Cancel link ‣ Binds to Return and Esc ‣ Uses a POST request
  68. A simple editable fragment • new Ajax.InPlaceEditor(element, url[, options]) ‣

    Uses an OK button and a Cancel link ‣ Binds to Return and Esc ‣ Uses a POST request ‣ Works over the native markup
  69. A simple editable fragment • new Ajax.InPlaceEditor(element, url[, options]) ‣

    Uses an OK button and a Cancel link ‣ Binds to Return and Esc ‣ Uses a POST request ‣ Works over the native markup ‣ Uses multiple-line editor only if needed
  70. Nips & tucks • Tweak AJAX persistence ‣ paramName, callback,

    ajaxOptions, htmlResponse • Customize appearance ‣ TONS of options: controls, texts, CSS classes...
  71. Nips & tucks • Tweak AJAX persistence ‣ paramName, callback,

    ajaxOptions, htmlResponse • Customize appearance ‣ TONS of options: controls, texts, CSS classes... • Plenty of callbacks
  72. Working with an alternate textual form • Perhaps you’re storing

    these dynamic markups as something other than HTML
  73. Working with an alternate textual form • Perhaps you’re storing

    these dynamic markups as something other than HTML ‣ Textile? Markdown? Wiki? Something... darker?
  74. Working with an alternate textual form • Perhaps you’re storing

    these dynamic markups as something other than HTML ‣ Textile? Markdown? Wiki? Something... darker? • You’d want your user to edit in that format
  75. Working with an alternate textual form • Perhaps you’re storing

    these dynamic markups as something other than HTML ‣ Textile? Markdown? Wiki? Something... darker? • You’d want your user to edit in that format ‣ Load an alternate text when entering editing
  76. Working with an alternate textual form • Perhaps you’re storing

    these dynamic markups as something other than HTML ‣ Textile? Markdown? Wiki? Something... darker? • You’d want your user to edit in that format ‣ Load an alternate text when entering editing ‣ Respond to persistence with the matching markup, as usual
  77. Using a dropdown list • So your users can’t be

    trusted? • You’d like them to pick from a dropdown list (“combo”) instead...
  78. Using a dropdown list • So your users can’t be

    trusted? • You’d like them to pick from a dropdown list (“combo”) instead... • Just use Ajax.InPlaceCollectionEditor ‣ Collection can be local or AJAX-based
  79. In-place editing demos • Simple editing with a few style

    options • Editing an alternate text representation • Using a collection-based editor
  80. Sliders in 30” (re-enacted by rabbits) • Replaces numerical input

    (free/dropdown) • One or more handles sliding on a track
  81. Sliders in 30” (re-enacted by rabbits) • Replaces numerical input

    (free/dropdown) • One or more handles sliding on a track • Easy customization through CSS + options
  82. Sliders in 30” (re-enacted by rabbits) • Replaces numerical input

    (free/dropdown) • One or more handles sliding on a track • Easy customization through CSS + options ‣ Orientation: vertical or horizontal
  83. Sliders in 30” (re-enacted by rabbits) • Replaces numerical input

    (free/dropdown) • One or more handles sliding on a track • Easy customization through CSS + options ‣ Orientation: vertical or horizontal ‣ Restrict valid positions
  84. Sliders in 30” (re-enacted by rabbits) • Replaces numerical input

    (free/dropdown) • One or more handles sliding on a track • Easy customization through CSS + options ‣ Orientation: vertical or horizontal ‣ Restrict valid positions ‣ Prevent handles from crossing each other
  85. Sliders in 30” (re-enacted by rabbits) • Replaces numerical input

    (free/dropdown) • One or more handles sliding on a track • Easy customization through CSS + options ‣ Orientation: vertical or horizontal ‣ Restrict valid positions ‣ Prevent handles from crossing each other ‣ Using handle pairs to define value ranges
  86. Slider demos • Simple sliders ‣ Vertical & horizontal ‣

    Callbacks • Multiple-handle slider • 3 handles defining 2 ranges, no cross-over
  87. Building DOM fragments “by hand” is booooring • Yet sometimes

    update/insert won’t cut it ‣ Browser innerHTML (or equiv.) weirdness
  88. Building DOM fragments “by hand” is booooring • Yet sometimes

    update/insert won’t cut it ‣ Browser innerHTML (or equiv.) weirdness • Prototype has a nice new Element thing ‣ But one element at a time, no textual content
  89. Building DOM fragments “by hand” is booooring • Yet sometimes

    update/insert won’t cut it ‣ Browser innerHTML (or equiv.) weirdness • Prototype has a nice new Element thing ‣ But one element at a time, no textual content • So how do we manually build DOM fragments in a concise, expressive way?
  90. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!')
  91. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p>
  92. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p> Builder.node('p', { id: 'demo' }, 'Hello world')
  93. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p> Builder.node('p', { id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p>
  94. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p> Builder.node('p', { id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> Builder.node('div', [Builder.node('h2', 'Intro'), 'Hey'])
  95. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p> Builder.node('p', { id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> Builder.node('div', [Builder.node('h2', 'Intro'), 'Hey']) // <div><h2>Intro</h2>Hey</div>
  96. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p> Builder.node('p', { id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> Builder.node('div', [Builder.node('h2', 'Intro'), 'Hey']) // <div><h2>Intro</h2>Hey</div> Builder.node('div', { id: 'demo' }, ['Hey', Builder.node('h2', { className: 'regular' }, 'Intro')])
  97. Builder.node Builder.node('p') // <p></p> Builder.node('p', { id: 'demo', className: 'notice'

    }) // <p id="demo" class="notice"></p> Builder.node('p', 'Hello world!') // <p>Hello world!</p> Builder.node('p', { id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> Builder.node('div', [Builder.node('h2', 'Intro'), 'Hey']) // <div><h2>Intro</h2>Hey</div> Builder.node('div', { id: 'demo' }, ['Hey', Builder.node('h2', { className: 'regular' }, 'Intro')]) // <div id="demo">Hey<h2 class="regular">Intro</h2></div>
  98. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!')
  99. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p>
  100. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p> P({ id: 'demo' }, 'Hello world')
  101. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p> P({ id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p>
  102. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p> P({ id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> DIV('div', [H2('Intro'), 'Hey'])
  103. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p> P({ id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> DIV('div', [H2('Intro'), 'Hey']) // <div><h2>Intro</h2>Hey</div>
  104. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p> P({ id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> DIV('div', [H2('Intro'), 'Hey']) // <div><h2>Intro</h2>Hey</div> DIV({ id: 'demo' }, ['Hey', H2({ className: 'regular' }, 'Intro')])
  105. Builder.dump: shortcuts! Builder.dump(); P() // <p></p> P({ id: 'demo', className:

    'notice' }) // <p id="demo" class="notice"></p> P('Hello world!') // <p>Hello world!</p> P({ id: 'demo' }, 'Hello world') // <p id="demo">Hello world!</p> DIV('div', [H2('Intro'), 'Hey']) // <div><h2>Intro</h2>Hey</div> DIV({ id: 'demo' }, ['Hey', H2({ className: 'regular' }, 'Intro')]) // <div id="demo">Hey<h2 class="regular">Intro</h2></div>
  106. Online resources • The documentation sites ‣ http://prototypejs.org to understand

    the code ‣ http://script.aculo.us to download and read the Wiki (massive overhaul initiated)
  107. Online resources • The documentation sites ‣ http://prototypejs.org to understand

    the code ‣ http://script.aculo.us to download and read the Wiki (massive overhaul initiated) • The official list ‣ http://groups.google.com/rubyonrails-spinoffs
  108. Online resources • The documentation sites ‣ http://prototypejs.org to understand

    the code ‣ http://script.aculo.us to download and read the Wiki (massive overhaul initiated) • The official list ‣ http://groups.google.com/rubyonrails-spinoffs • IRC ‣ #scriptaculous on Freenode
  109. Shameless plug • “The Bungee Book” • Available already (as

    beta) from the Pragmatic Bookshelf ‣ http://books.pragprog.com/titles/cppsu/
  110. Shameless plug • “The Bungee Book” • Available already (as

    beta) from the Pragmatic Bookshelf ‣ http://books.pragprog.com/titles/cppsu/ • 95% content-complete already
  111. Shameless plug • “The Bungee Book” • Available already (as

    beta) from the Pragmatic Bookshelf ‣ http://books.pragprog.com/titles/cppsu/ • 95% content-complete already • Up-to-date on the latest stuff
  112. Shameless plug • “The Bungee Book” • Available already (as

    beta) from the Pragmatic Bookshelf ‣ http://books.pragprog.com/titles/cppsu/ • 95% content-complete already • Up-to-date on the latest stuff • Pre-order the paper book too!
  113. Q&A