NinjaScript 2010-10-14

1,646 views
1,545 views

Published on

This is our first presentation on NinjaScript, a tool by Logical Reality Design. Evan Dorn presented this to the LA Ruby Meetup on October 14, 2010.

NinjaScript: Javascript so unobtrusive, you'll never see it coming.

NinjaScript, which runs on top of jQuery, provides extremely easy-to-use UJS tools including instant conversion of regular forms and links into AJAX equivalents. NS provides for reusable behaviors and automatic rebinding of events in a way that is more flexible than event-delegation methods like jQuery live().

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,646
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide































































  • NinjaScript 2010-10-14

    1. 1. NinjaScript JavaScript so unobtrusive, you’ll never see it coming.
    2. 2. Evan Dorn Owner and Lead Developer, Logical Reality Design
    3. 3. Credits NinjaScript was invented and (almost) entirely coded by Judson Lester Co-owner and Senior Developer
    4. 4. NinjaScript Provides • A behavior layer built on jQuery • Easy UJS AJAX that degrades gracefully • Persistent behavior that just works • CSS-like syntax for rich JS behavior • Cool prepackaged behaviors
    5. 5. What do we want? (In an AJAXy, RESTful Rails app)
    6. 6. What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive
    7. 7. What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive • AJAX actions should degrade gracefully
    8. 8. What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive • AJAX actions should degrade gracefully • RESTful methods should degrade gracefully
    9. 9. What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive • AJAX actions should degrade gracefully • RESTful methods should degrade gracefully • This shouldn’t take any extra work!
    10. 10. Rails 2 Approach • AJAX helpers: link_to_remote and form_remote_for • REST methods (PUT and DELETE) simulated via a hidden form field • link_to_remote() arguments aren’t the same format as link_to()
    11. 11. Rails 2 Approach: links link_to_remote(‘click me’, :url => some_path) <a href=”#” onclick=”bleaaaaaaaaaaaaaaaaaaaarghh oh please just kill me now my eyes are bleeding”> click me </a>
    12. 12. Rails 2 Approach: links link_to_remote(‘click me’, :url => some_path) <a href=”#” onclick=”bleaaaaaaaaaaaaaaaaaaaarghh oh please just kill me now my eyes are bleeding”> click me </a> Graceful degradation requires an extra argument: link_to_remote(‘click me’, { :url => some_path }, { :href => some_path } )
    13. 13. Rails 2 Approach: forms form_remote_for(@object) <form action=”/objects/1” method=”post” onsubmit=”lots more. Horrible_JavaScript_crap_here uglifying_my_html”> <input name=”_method” type=”hidden” value=”put”> ... your fields here ... </a> Non - POST/GET requests simulated via hidden input.
    14. 14. Rails 3 Approach: links link_to with :remote => true <%= link_to ‘click me’, ‘/foo’, :remote => true, :method => :delete %> Generates: <a href=”/foo” data-method=”delete” data-remote=”true”> click me </a> Unobtrusive invisible form created by rails.js
    15. 15. Rails 3 Approach: forms form_for with :remote => true <%= form_for @product, :remote => true do |form| %> <%= ... your inputs here ... %> Generates: <form action=”/products/1” data-method=”put” data- remote=”true”> ... your inputs here ... </form> Hidden _method input added by rails.js upon submit
    16. 16. Rails 3 Approach: forms
    17. 17. Rails 3 Approach: forms • So Rails 3 gives us UJS ...
    18. 18. Rails 3 Approach: forms • So Rails 3 gives us UJS ... • ... At the cost of making REST dependent on JavaScript
    19. 19. Rails 3 Approach: forms • So Rails 3 gives us UJS ... • ... At the cost of making REST dependent on JavaScript • A fresh scaffold - non AJAX - won’t even work without JS in Rails 3
    20. 20. Rails 3 Approach: forms • So Rails 3 gives us UJS ... • ... At the cost of making REST dependent on JavaScript • A fresh scaffold - non AJAX - won’t even work without JS in Rails 3 • End-to-end integration testing can’t be done without Selenium or similar
    21. 21. Rails 3 Approach: forms • So Rails 3 gives us UJS ... • ... At the cost of making REST dependent on JavaScript • A fresh scaffold - non AJAX - won’t even work without JS in Rails 3 • End-to-end integration testing can’t be done without Selenium or similar • ... oops
    22. 22. Use jQuery? • Bind event handler to each form that submits via AJAX. • ... kind of a pain, though ...
    23. 23. Use jQuery? $(document.ready(function() { $(‘form#make_me_ajax’).submit(function (){ $.post( ”/products”, $(“form#make_me_ajax”).serialize(), function(data) { ... some return behavior ... } ); }); }); ( To be fair, there are plugins that make this easier, like jQuery Form etc. )
    24. 24. The NinjaScript Way Here’s what it looks like in NinjaScript. Don’t change your form (or link) at all.
    25. 25. The NinjaScript Way $.behavior({ 'form#product': submits_as_ajax() })
    26. 26. The NinjaScript Way Specify behaviors of many elements in a CSS-like format. $.behavior({ 'form#product': submits_as_ajax(), ‘a.delete_link’: submits_as_ajax(), ‘flash.error’: decays() })
    27. 27. Let’s see it in action ( Demo )
    28. 28. What’s the Score? AJAX REST Unobtrusive Easy degrades degrades Rails 2 Rails 3 jQuery NinjaScript
    29. 29. Persistent Behavior
    30. 30. Persistent Behavior (CSS is awesome, JavaScript sucks)
    31. 31. Persistent Behavior
    32. 32. Persistent Behavior • We take CSS’s default behavior for granted. • CSS styles apply to everything in the DOM, even if it changes. • Why aren’t JS behaviors the same way?
    33. 33. DOM Reconstruction and Event Bindings
    34. 34. DOM Reconstruction and Event Bindings div#content a.has_tooltip a.has_tooltip
    35. 35. DOM Reconstruction and Event Bindings • Bind a tooltip behavior div#content to $(‘.has_tooltip’) a.has_tooltip a.has_tooltip
    36. 36. DOM Reconstruction and Event Bindings • Bind a tooltip behavior div#content to $(‘.has_tooltip’) • Dynamically add a new .tooltip element a.has_tooltip a.has_tooltip a.has_tooltip
    37. 37. DOM Reconstruction and Event Bindings • Bind a tooltip behavior div#content to $(‘.has_tooltip’) • Dynamically add a new .tooltip element a.has_tooltip a.has_tooltip • New element has no bound event handler! a.has_tooltip
    38. 38. DOM Reconstruction and Event Bindings • Bind a tooltip behavior div#content to $(‘.has_tooltip’) • Dynamically add a new .tooltip element a.has_tooltip a.has_tooltip • New element has no bound event handler! a.has_tooltip • This is really lame ...
    39. 39. What we want
    40. 40. What we want • Our JS should specify, via CSS selectors, behaviors that apply to elements
    41. 41. What we want • Our JS should specify, via CSS selectors, behaviors that apply to elements • Those behaviors should always apply in all conditions
    42. 42. What we want • Our JS should specify, via CSS selectors, behaviors that apply to elements • Those behaviors should always apply in all conditions • The coder shouldn’t have to waste braincycles on it
    43. 43. Solution 1: Event Delegation
    44. 44. Solution 1: Event Delegation • jQuery live() and similar
    45. 45. Solution 1: Event Delegation • jQuery live() and similar • Bind handlers to root element of the DOM
    46. 46. Solution 1: Event Delegation • jQuery live() and similar • Bind handlers to root element of the DOM • Since browsers bubble unhandled events up the DOM, the root handles all events
    47. 47. Solution 1: Event Delegation • jQuery live() and similar • Bind handlers to root element of the DOM • Since browsers bubble unhandled events up the DOM, the root handles all events This is pretty awesome.
    48. 48. The Problem with Event Delegation
    49. 49. The Problem with Event Delegation • live() can’t handle element transformations
    50. 50. The Problem with Event Delegation • live() can’t handle element transformations • ... like giving <div>s rounded corners ...
    51. 51. The Problem with Event Delegation • live() can’t handle element transformations • ... like giving <div>s rounded corners ... • Because there’s no event to process when we insert new elements into the DOM
    52. 52. The Problem with Event Delegation • live() can’t handle element transformations • ... like giving <div>s rounded corners ... • Because there’s no event to process when we insert new elements into the DOM • ECMA-compliant browsers are suppossed to send DOMSubtreeModified and DOMNodeInserted
    53. 53. The Problem with Event Delegation • live() can’t handle element transformations • ... like giving <div>s rounded corners ... • Because there’s no event to process when we insert new elements into the DOM • ECMA-compliant browsers are suppossed to send DOMSubtreeModified and DOMNodeInserted (Bad IE! No Biscuit!)
    54. 54. Any other transformations?
    55. 55. Any other transformations? • How about taking degradable DELETE forms and turning them into links? (demo)
    56. 56. Solution 1I: Automatic Rebinding • Bind to and/or transform the element, not the root. • NinjaScript examines new DOM elements to see if any known behaviors match. • NinjaScript fires its own event when the DOM is reconstructed so it works in IE.
    57. 57. How do I use it?
    58. 58. Defining a Behavior
    59. 59. Defining a Behavior • Make a mapping of selectors to behaviors and pass it to $.behavior()
    60. 60. Defining a Behavior • Make a mapping of selectors to behaviors and pass it to $.behavior() • Each behavior can include an events block and a transform.
    61. 61. Defining a Behavior • Make a mapping of selectors to behaviors and pass it to $.behavior() • Each behavior can include an events block and a transform. • Transform is applied as soon as the element is in the DOM.
    62. 62. Defining a Behavior • Make a mapping of selectors to behaviors and pass it to $.behavior() • Each behavior can include an events block and a transform. • Transform is applied as soon as the element is in the DOM. • Events blocks are a mapping of click:, focus:, mouseover: etc. to behaviors.
    63. 63. Defining a Behavior $.behavior({ '.awesome': { transform: function(elem){... do something ...}, events: { click: function(evnt,elem){... handle click ...}, mouseover: function(evnt,elem){... pop tooltip ...} } } }) All awesome elements will get the transform applied, no matter when they’re added.
    64. 64. Defining a Behavior Shortcut: skip the ‘events:’ mapping if you’re just handling an event. $.behavior({ '.awesome': { click: function(event,elem){ ... handle click ...}, } })
    65. 65. Reusable Behaviors You can easily define and name behaviors for reuse.
    66. 66. Reusable Behaviors You can easily define and name behaviors for reuse. function sings_and_dances(){ return new behavior({ transform: function(elem) { elem.add_a_tutu() }, click: function(evnt,elem){ elem.pirouette() }, mouseover: function(evnt,elem){ elem.sing_an_aria()} }) }
    67. 67. Reusable Behaviors You can easily define and name behaviors for reuse. function sings_and_dances(){ return new behavior({ transform: function(elem) { elem.add_a_tutu() }, click: function(evnt,elem){ elem.pirouette() }, mouseover: function(evnt,elem){ elem.sing_an_aria()} }) } $.behavior({ ‘#dhh’: sings_and_dances(), ‘#katz’: sings_and_dances(), ‘.code_monkey’: signs_and_dances() })
    68. 68. Pre-Defined Behaviors These work today - built into NinjaScript • submits_as_ajax • submits_as_ajax_form • submits_as_ajax_link • becomes_ajax_link (for forms) • decays (fades away after 10 sec)
    69. 69. Nifty Feature: ‘Busy’ spinner ( Demo )
    70. 70. Planned Behaviors Coming Soon! • pops_tooltip • gets_round_corners • validates_local • gets_drop_shadow • validates_via_ajax • replaced_by_image • autocompletes • watermarked • has_ajax_observer • sortable • editable_via_ajax • sortable_via_ajax
    71. 71. Future Plans • Complete replacement for rails.js • NinjaHelper Rails plugin/gem to make links and forms with non GET/POST methods degrade gracefully • Prototype / MooTools / YUI support (maybe)
    72. 72. Come Help Us! NinjaScript is at version 0.6 fork: http://github.com/lrdesign/NinjaScript http://groups.google.com/group/lrd-ninjascript

    ×