Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

NinjaScript and Mizugumo 2011-02-05

1,221 views

Published on

NinjaScript is a javascript framework for enriching web applications with unobtrusive, persistent JavaScript behavior.

Mizugumo is a ruby gem to making completely gracefully-degrading Rails applications. It uses the NinjaScript framework for rich behavior and integrates it tightly with Rails.

This presentation was given to LA RubyConf on February 5, 2011.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

NinjaScript and Mizugumo 2011-02-05

  1. 1. NinjaScriptJavaScript so unobtrusive, you’ll never see it coming. MizugumoMake your Rails app walk on water with NinjaScript.
  2. 2. Evan DornCEO and Lead Developer, Logical Reality Design
  3. 3. CreditsNinjaScript was invented and (almost) entirely coded by Judson Lester Co-owner and Senior Developer
  4. 4. NinjaScript
  5. 5. GOAL 1:CompletelyUnobtrusive
  6. 6. No<HTML> MarkupRequired
  7. 7. GOAL 2:Graceful Degradation
  8. 8. JavaScriptenrichesa fully functional website
  9. 9. Your site should work without JavaScript!
  10. 10. Why do I care?• Spiders & Automation• Accessibility: screen readers• NoScript users
  11. 11. Graceful degradation is a ROYAL PAIN
  12. 12. (Unless you use NinjaScript)
  13. 13. GOAL 3:Persistent Behavior
  14. 14. CSS: is_awesome$(JavaScript){ SUCKS }
  15. 15. JS should be like CSS•CSS styles always apply• Even if the DOM changes• Why aren’t JS behaviors the same?
  16. 16. DOM Reconstruction and Event Bindings
  17. 17. DOM Reconstruction and Event Bindings div#content a.has_tooltip a.has_tooltip
  18. 18. DOM Reconstruction and Event Bindings• Bind a tooltip behavior div#content to $(‘.has_tooltip’) a.has_tooltip a.has_tooltip
  19. 19. 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
  20. 20. 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
  21. 21. 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 ...
  22. 22. What we want
  23. 23. What we want• Specify JS behaviors via CSS selectors
  24. 24. What we want• Specify JS behaviors via CSS selectors• Behaviors should always apply
  25. 25. What we want• Specify JS behaviors via CSS selectors• Behaviors should always apply• Easy for the developer
  26. 26. Solution 1:Event Delegation
  27. 27. Solution 1: Event Delegation• jQuery live() and similar
  28. 28. Solution 1: Event Delegation• jQuery live() and similar• Bind handlers to root element of the DOM
  29. 29. 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
  30. 30. 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.
  31. 31. The Problem withEvent Delegation
  32. 32. The Problem with Event Delegation• live() can’t handle element transformations
  33. 33. The Problem with Event Delegation• live() can’t handle element transformations• ... like giving <div>s rounded corners ...
  34. 34. 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
  35. 35. 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• DOM Level 2-compliant browsers are suppossed to send DOMSubtreeModified and DOMNodeInserted
  36. 36. 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• DOM Level 2-compliant browsers are suppossed to send DOMSubtreeModified and DOMNodeInserted ... bad IE. No Biscuit!
  37. 37. Solution 1I:Automatic Rebinding
  38. 38. Solution 1I: Automatic Rebinding• Bind to and/or transform the element, not the root.
  39. 39. 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.
  40. 40. 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.
  41. 41. So how do I use it?
  42. 42. NinjaScript“Behavior Sheet”
  43. 43. NinjaScript “Behavior Sheet”Ninja.behavior({ form#product: submitsAsAjax, ‘a.delete_product’: submitsAsAjax, ‘#login_form input’: isWatermarked, ‘flash.error’: decays, ‘li.has_tooltip’: showsTooltip})
  44. 44. Defining a BehaviorNinja.behavior({ .awesome: { transform: function(elem){... add to the DOM ...}, events: { click: function(event){... handle click ...}, mouseover: function(event){... pop tooltip ...} } }}) All awesome elements will get the transform applied, no matter when they’re added.
  45. 45. Defining a BehaviorShortcut: skip the ‘events:’ mapping if you’rejust handling an event.Ninja.behavior({ .awesome: { click: function(event){ ... handle click ...}, }})
  46. 46. Reusable BehaviorsYou can easily define and name behaviors forreuse.
  47. 47. Reusable BehaviorsYou can easily define and name behaviors forreuse. singsAndDances(){function return new ninja.does({ transform: function(elem) { elem.addATutu() }, click: function(event) { this.element.pirouette() }, mouseover: function(event) { this.element.singAnAria()} })}
  48. 48. Reusable BehaviorsYou can easily define and name behaviors forreuse. singsAndDances(){function return new ninja.does({ transform: function(elem) { elem.addATutu() }, click: function(event) { this.element.pirouette() }, mouseover: function(event) { this.element.singAnAria()} })}Ninja.behavior({ ‘#dhh’: Ninja.singsAndDances(), ‘#katz’: Ninja.singsAndDances(), ‘.code_monkey’: Ninja.singsAndDances()})
  49. 49. Pre-Defined BehaviorsThese work today - built into NinjaScript• submitsAsAjax (for forms or links)• becomesLink (for forms)• decays (fades away after 10 sec)• isWatermarked (for form inputs)
  50. 50. Planned Behaviors Coming Sometime!• popsTooltip • getsRoundCorners• validatesLocal • getsDropShadow• validatesViaAjax • replacedByImage• autocompletes • isSortable• hasAjaxObserver • isSortableViaAjax• editableViaAjax
  51. 51. CAVEAT!
  52. 52. CAVEAT! NinjaScript 0.8.x depends on jQuery-1.4.2DOES NOT SUPPORT jQuery-1.4.4 or jQuery-1.5
  53. 53. CAVEAT! NinjaScript 0.8.x depends on jQuery-1.4.2DOES NOT SUPPORT jQuery-1.4.4 or jQuery-1.5 (... fix is coming)
  54. 54. Future Plans for NinjaScript
  55. 55. Future Plans for NinjaScript• Lots more prepackaged behaviors
  56. 56. Future Plans for NinjaScript• Lots more prepackaged behaviors• Decouple from jQuery - build NinjaScript behaviors in any framework
  57. 57. Future Plans for NinjaScript• Lots more prepackaged behaviors• Decouple from jQuery - build NinjaScript behaviors in any framework• Handle JSON returns from AJAX calls, not just eval()
  58. 58. The internals are “complicated”.
  59. 59. The internals are “complicated”.But Judson is a ninja rockstar,
  60. 60. The internals are “complicated”.But Judson is a ninja rockstar, 4th dan.
  61. 61. MizugumoLet your Rails app walk on water with NinjaScript
  62. 62. gem install mizugumo
  63. 63. rails generatemizugumo:install
  64. 64. A Mizugumo app is:
  65. 65. A Mizugumo app is:• AJAX by default
  66. 66. A Mizugumo app is:•AJAX by default• Degrades gracefully by default
  67. 67. A Mizugumo app is:•AJAX by default• Degrades gracefully by default• No extra work!
  68. 68. The Rails 3 RESTfail
  69. 69. The Rails 3 RESTfail
  70. 70. The Rails 3 RESTfail• Simulate PUT and DELETE methods!
  71. 71. The Rails 3 RESTfail• Simulate PUT and DELETE methods!• link_to(:method => ‘delete’)
  72. 72. The Rails 3 RESTfail• Simulate PUT and DELETE methods!• link_to(:method => ‘delete’)• <a href=’/product/1’ data- method=‘delete‘>
  73. 73. The Rails 3 RESTfail• Simulate PUT and DELETE methods!• link_to(:method => ‘delete’)• <a href=’/product/1’ data- method=‘delete‘>• Without JS, it’s a show link!
  74. 74. The Rails 3 RESTfail• Simulate PUT and DELETE methods!• link_to(:method => ‘delete’)• <a href=’/product/1’ data- method=‘delete‘>• Without JS, it’s a show link!• ... oops!
  75. 75. The Mizugumo Way
  76. 76. The Mizugumo Waylink_to with :method => ‘delete’<%= link_to ‘click me’, ‘/foo’, :method => :delete %>
  77. 77. The Mizugumo Waylink_to with :method => ‘delete’<%= link_to ‘click me’, ‘/foo’, :method => :delete %>Generates a <form>!<form action=’/foo’ method=‘post’ class=‘mizugumo_graceful_form’> <input type=‘hidden’ name=‘_method’ value=‘delete’> <input type=‘submit’ value=’click me’></a>
  78. 78. The Mizugumo WayBut a default NinjaScript behavior:Ninja.behavior({ ‘.mizugumo_graceful_form’: becomesLink})
  79. 79. The Mizugumo WayBut a default NinjaScript behavior:Ninja.behavior({ ‘.mizugumo_graceful_form’: becomesLink})Converts it back!<a href=’/foo’>click me</a>
  80. 80. The Result
  81. 81. The Result• JavaScript users see a link
  82. 82. The Result•JavaScript users see a link• Non-JS users see a button
  83. 83. The Result•JavaScript users see a link• Non-JS users see a button• DELETE action works for both
  84. 84. The Result•JavaScript users see a link• Non-JS users see a button• DELETE action works for both
  85. 85. The Result•JavaScript users see a link• Non-JS users see a button• DELETE action works for both• ...Rails developer does nothing!
  86. 86. What about AJAX?
  87. 87. No need for markup:
  88. 88. No need for markup:Not this.<%= form_for(@product, :remote => true) do %>
  89. 89. No need for markup:Not this.<%= form_for(@product, :remote => true) do %>Just this:<%= form_for(@product) do %>
  90. 90. Use NinjaScript!Ninja.behavior({ ‘#my_form’: submitsAsAjax})
  91. 91. Ninja.submitsAsAjax
  92. 92. Ninja.submitsAsAjax• Same Data• Same URL• Same Method• Just write a format.js block in your controller, and a js.erb view.
  93. 93. The Mizugumoscaffold does this for you.
  94. 94. (demo)
  95. 95. Future Plans for Mizugumo
  96. 96. Future Plans for Mizugumo• Replace rails.js
  97. 97. Future Plans for Mizugumo•Replace rails.js• Improve generators
  98. 98. Future Plans for Mizugumo•Replace rails.js• Improve generators• Degradable :confirm
  99. 99. Future Plans for Mizugumo•Replace rails.js• Improve generators• Degradable :confirm• Automatic JS validations!
  100. 100. Please Contribute!
  101. 101. http://bit.ly/hFzoAG

×