• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
NinjaScript 2010-10-14
 

NinjaScript 2010-10-14

on

  • 1,576 views

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....

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().

Statistics

Views

Total Views
1,576
Views on SlideShare
1,576
Embed Views
0

Actions

Likes
0
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

NinjaScript 2010-10-14 NinjaScript 2010-10-14 Presentation Transcript

  • NinjaScript JavaScript so unobtrusive, you’ll never see it coming.
  • Evan Dorn Owner and Lead Developer, Logical Reality Design
  • Credits NinjaScript was invented and (almost) entirely coded by Judson Lester Co-owner and Senior Developer
  • 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
  • What do we want? (In an AJAXy, RESTful Rails app)
  • What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive
  • What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive • AJAX actions should degrade gracefully
  • What do we want? (In an AJAXy, RESTful Rails app) • JavaScript should be unobtrusive • AJAX actions should degrade gracefully • RESTful methods should degrade gracefully
  • 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!
  • 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()
  • 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>
  • 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 } )
  • 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.
  • 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
  • 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
  • Rails 3 Approach: forms
  • Rails 3 Approach: forms • So Rails 3 gives us UJS ...
  • Rails 3 Approach: forms • So Rails 3 gives us UJS ... • ... At the cost of making REST dependent on JavaScript
  • 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
  • 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
  • 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
  • Use jQuery? • Bind event handler to each form that submits via AJAX. • ... kind of a pain, though ...
  • 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. )
  • The NinjaScript Way Here’s what it looks like in NinjaScript. Don’t change your form (or link) at all.
  • The NinjaScript Way $.behavior({ 'form#product': submits_as_ajax() })
  • 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() })
  • Let’s see it in action ( Demo )
  • What’s the Score? AJAX REST Unobtrusive Easy degrades degrades Rails 2 Rails 3 jQuery NinjaScript
  • Persistent Behavior
  • Persistent Behavior (CSS is awesome, JavaScript sucks)
  • Persistent Behavior
  • 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?
  • DOM Reconstruction and Event Bindings
  • DOM Reconstruction and Event Bindings div#content a.has_tooltip a.has_tooltip
  • DOM Reconstruction and Event Bindings • Bind a tooltip behavior div#content to $(‘.has_tooltip’) a.has_tooltip a.has_tooltip
  • 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
  • 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
  • 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 ...
  • What we want
  • What we want • Our JS should specify, via CSS selectors, behaviors that apply to elements
  • What we want • Our JS should specify, via CSS selectors, behaviors that apply to elements • Those behaviors should always apply in all conditions
  • 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
  • Solution 1: Event Delegation
  • Solution 1: Event Delegation • jQuery live() and similar
  • Solution 1: Event Delegation • jQuery live() and similar • Bind handlers to root element of the DOM
  • 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
  • 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.
  • The Problem with Event Delegation
  • The Problem with Event Delegation • live() can’t handle element transformations
  • The Problem with Event Delegation • live() can’t handle element transformations • ... like giving <div>s rounded corners ...
  • 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
  • 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
  • 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!)
  • Any other transformations?
  • Any other transformations? • How about taking degradable DELETE forms and turning them into links? (demo)
  • 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.
  • How do I use it?
  • Defining a Behavior
  • Defining a Behavior • Make a mapping of selectors to behaviors and pass it to $.behavior()
  • 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.
  • 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.
  • 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.
  • 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.
  • Defining a Behavior Shortcut: skip the ‘events:’ mapping if you’re just handling an event. $.behavior({ '.awesome': { click: function(event,elem){ ... handle click ...}, } })
  • Reusable Behaviors You can easily define and name behaviors for reuse.
  • 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()} }) }
  • 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() })
  • 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)
  • Nifty Feature: ‘Busy’ spinner ( Demo )
  • 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
  • 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)
  • Come Help Us! NinjaScript is at version 0.6 fork: http://github.com/lrdesign/NinjaScript http://groups.google.com/group/lrd-ninjascript