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

script.aculo.us

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

 script.aculo.us

Avatar for Christophe Porteneuve

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