SlideShare ist ein Scribd-Unternehmen logo
1 von 77
Downloaden Sie, um offline zu lesen
Unobtrusive Ajax
   With Rails
 Dan Webb (dan@danwebb.net)
Overview
    A bit of history
★

    What is unobtrusive scripting?
★

    The UJS Plugin
★

    Casestudy
★

    Ranting Upcoming UJS Features
★
The dark days of
    DHTML
Then web standards
      arrived
The Client-side Cake

        Style - CSS




     Content - (X)HTML
What web standards
          did for us
    More maintainable
★

    More accessible
★

    Leaner pages
★

    Platform independent (print, mobile...)
★

    'Future-proof' as well as backwards
★
    compatible
JavaScript got a
   bad name
It deserved it
Web 2.0
Folksonomies
Massive text boxes
Social software
and Ajax...
JavaScript is trendy
      again!
Browser support is
   much better
We learnt our
lessons from the
  DHTML days
What did we learn?
Unobtrusive DOM
   Scripting
It's an approach to
browser UI design
It's about separating
   content and style
    from behaviour
Behaviour: A new layer for
   the client-side cake
        Behaviour - JavaScript


             Style - CSS


        Content - (X)HTML
It's enhancing a
working application
so it degrades
 gracefully when
things don't work
It's not just about
putting JavaScript in
    a different file
It's not rocket
     science
It's not the
'Rails Way'
An example:
link_to_remote
<%= link_to_remote 'View description',
                   :controller => 'product',
                   :action => 'desc',
                   :id => @product.id %>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/
desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
# better...

<a href=quot;/product/desc/1quot; onclick=quot;new
Ajax.Request(this.href, {asynchronous:true,
evalScripts:true}); return false;quot;>View
description</a>
It's not possible to
     do that with
   link_to_remote
<% @products.each do |product| %>

<%= link_to_remote 'View description',
                   :controller => 'product',
                   :action => 'desc',
                   :id => @product.id %>

<% end %>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true});
return false;quot;>View description</a>
<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>

<a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>
Getting started
The UJS Plugin
    A plugin to aid unobtrusive scripting
★
    with Rails
    Allows you to define behaviours via
★
    CSS selectors
    Keeps script in an external, cacheable
★
    files
    www.ujs4rails.com - check it out!
★
Remote Links
<ul id=quot;outlinequot;>

  <% @items.each do |item| %>

  <li><%= link_to :action => 'more',
                  :id => @item.id %></li>

  <% end %>

</ul>
<ul id=quot;outlinequot;>

  <% @items.each do |item| %>

  <li><%= link_to :action => 'more',
                  :id => @item.id %></li>

  <% end %>

</ul>

<% apply_behaviour '#outline a:click',
   'new Ajax.Request(this.href); return false;' %>
<ul id=quot;outlinequot;>

  <% @items.each do |item| %>

  <li><%= link_to :action => 'more',
                  :id => @item.id %></li>

  <% end %>

</ul>

<% apply_behaviour '#outline a', make_remote_link %>
What about links
with side-effects?
Links should never
 have side effects
Use a button



<%= button_to 'Remove from basket',
              :method => :delete %>
<form class=quot;button-toquot; action=quot;/basket/2quot; method=quot;postquot;>

  <input type=quot;hiddenquot; name=quot;_methodquot; value=quot;deletequot; />

  <input type=quot;submitquot; value=quot;Remove from basketquot; />

</form>
Then attach the behaviour


<%= button_to 'Remove from basket',
              :method => :delete %>
<% apply_behaviour 'form.button-to',
                   make_remote_form %>
Hijacking forms
<%= form_tag :url => entries_url, :id => 'comment' %>

  <%= text_field :name %>

  <%= text_field :email %>

  <%= text_area :comment %>

  <%= submit_tag 'Post comment' %>

<%= end_form_tag %>
<%= form_tag :url => entries_url, :id => 'comment' %>

  <%= text_field :name %>

  <%= text_field :email %>

  <%= text_area :comment %>

  <%= submit_tag 'Post comment' %>

<%= end_form_tag %>



<% apply_behaviour '#comment:submit',
   'new Ajax.Request(this.action, { parameters :
   Form.serialize(this)}); return false;' %>
<%= form_tag :url => entries_url, :id => 'comment' %>

  <%= text_field :name %>

  <%= text_field :email %>

  <%= text_area :comment %>

  <%= submit_tag 'Post comment' %>

<%= end_form_tag %>



<% apply_behaviour '#comment', make_remote_form %>
A Case Study

Sneakr.com: A Web 2.0, Ajax Trainer Shop
routes.rb


map.resource :products

map.resource :basket, :controller => 'basket',

             :collection => {:clear => :post}
The Product Controller
class ProductController < ApplicationController

  def index # show all products

      @products = Product.find :all

  end

  def show # show the details of a product

      @product = Product.find params[:id]

  end

end
index.rhtml

<div id=quot;cataloguequot;>
  <%= render :partial => 'products' %>
</div>
<div id=quot;basketquot;>
  <%= render :partial => 'basket' %>
</div>
_products.rhtml

<ul>

  <% @products.each do |product| %>

    <li id=quot;<%= product.id %>_prodquot;>
    <%= link_to product.name, product_url(product) %>
    <%= product.description %>
    </li>

  <% end %>

</ul>
show.rhtml


<h1><%= @product.name %></h1>

<p><%= image_tag @product.photo.public_filename %></p>

<p><%= @product.description %></p>

<p><%= button_to 'Add To Basket', basket_url
(@product), :method => :put %></p>
The Basket Controller

class BasketController < ApplicationController

  def update

      @product = Product.find params[:id]
      @basket << @product

      redirect_to products_url

  end

end
We're done!
now to add the Ajax
<% apply_behaviours do


   on '#catalogue li',
       make_draggable(:revert => true)

    on '#basket', make_drop_receiving(
      :url => basket_url,
      :with => quot;'_method=put&id=' +
        encodeURIComponent(element.id)quot;

    )

end %>
<% apply_behaviours do


   on '#catalogue li',
       make_draggable(:revert => true)

    on '#basket', make_drop_receiving(
      :url => basket_url,
      :with => quot;'_method=put&id=' +
        encodeURIComponent(element.id)quot;

    )

end %>
So how do we deal
 with this on the
   server-side?
respond_to
class BasketController < ApplicationController

  def update

      @product = Product.find params[:id]
      @basket << @product

      redirect_to products_url

  end

end
class BasketController < ApplicationController

  def update

      @product = Product.find params[:id]
      @basket << @product

      respond_to do |type|
        type.html { redirect_to products_url }
        type.js
      end

  end

end
update.rjs



page.replace_html 'basket',
                  :partial => 'basket'
Take a look for
           yourself...
http://www.danwebb.net/railsconf2006/ujs_shopping.zip
We have no control
     over the
 environment our
 JavaScript runs in
Code defensively
The path to enlightenment
    Write a working application using
★
    semantic HTML
    Style it with CSS
★

    Write JavaScript that 'hijacks' the page
★
    elements to enhance the UI
    Learn JavaScript and DOM Scripting
★
Further Reading
    The JavaScript articles on A List Apart
★
    (alistapart.com)
    Unobtrusive Scripting by Christian
★
    Heilmann (onlinetools.org)
    Jeremy Keith's presentations, book and
★
    articles (domscripting.com)
    Google it!
★
Upcoming in UJS
    Improved testing (custom assertions)
★

    Improved debugging
★

    More behaviour helpers
★

    More tutorials on ujs4rails.com
★
And finally...



<%= apply_behaviour @products, make_draggable %>
<% div_for @product, :behavior => make_draggable do %>

<h2><%= @product.name %></h2>
<p><%= @product.description %></p>

<% end %>
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

High Performance Ajax Applications
High Performance Ajax ApplicationsHigh Performance Ajax Applications
High Performance Ajax Applications
Julien Lecomte
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
moniguna
 

Was ist angesagt? (20)

Laravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleLaravel 8 export data as excel file with example
Laravel 8 export data as excel file with example
 
High Performance Ajax Applications
High Performance Ajax ApplicationsHigh Performance Ajax Applications
High Performance Ajax Applications
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Jazz up your JavaScript: Unobtrusive scripting with JavaScript libraries
Jazz up your JavaScript: Unobtrusive scripting with JavaScript librariesJazz up your JavaScript: Unobtrusive scripting with JavaScript libraries
Jazz up your JavaScript: Unobtrusive scripting with JavaScript libraries
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
Building a JavaScript Library
Building a JavaScript LibraryBuilding a JavaScript Library
Building a JavaScript Library
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
 
An Introduction to ReactJS
An Introduction to ReactJSAn Introduction to ReactJS
An Introduction to ReactJS
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
 
Choosing a Javascript Framework
Choosing a Javascript FrameworkChoosing a Javascript Framework
Choosing a Javascript Framework
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
React Facebook JavaScript Library
React Facebook JavaScript LibraryReact Facebook JavaScript Library
React Facebook JavaScript Library
 
WordPress and Ajax
WordPress and AjaxWordPress and Ajax
WordPress and Ajax
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
 
SproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFestSproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFest
 
ReactJs presentation
ReactJs presentationReactJs presentation
ReactJs presentation
 
REACT.JS : Rethinking UI Development Using JavaScript
REACT.JS : Rethinking UI Development Using JavaScriptREACT.JS : Rethinking UI Development Using JavaScript
REACT.JS : Rethinking UI Development Using JavaScript
 

Andere mochten auch (8)

Secretsofrubyonrails
SecretsofrubyonrailsSecretsofrubyonrails
Secretsofrubyonrails
 
State Of Rails 05
State Of Rails 05State Of Rails 05
State Of Rails 05
 
Fisl6
Fisl6Fisl6
Fisl6
 
Rails Conf Talk Slides
Rails Conf Talk SlidesRails Conf Talk Slides
Rails Conf Talk Slides
 
Ugo Cei Presentation
Ugo Cei PresentationUgo Cei Presentation
Ugo Cei Presentation
 
Extractingrails
ExtractingrailsExtractingrails
Extractingrails
 
Our Opinions!
Our Opinions!Our Opinions!
Our Opinions!
 
Workin On The Rails Road
Workin On The Rails RoadWorkin On The Rails Road
Workin On The Rails Road
 

Ähnlich wie Dan Webb Presentation

Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
Chris Alfano
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
adamlogic
 
Remote code-with-expression-language-injection
Remote code-with-expression-language-injectionRemote code-with-expression-language-injection
Remote code-with-expression-language-injection
Mickey Jack
 
Spca2014 hillier 3rd party_javascript_libraries
Spca2014 hillier 3rd party_javascript_librariesSpca2014 hillier 3rd party_javascript_libraries
Spca2014 hillier 3rd party_javascript_libraries
NCCOMMS
 
Bulletproof Ajax
Bulletproof AjaxBulletproof Ajax
Bulletproof Ajax
adactio
 
Introduction to angular js july 6th 2014
Introduction to angular js   july 6th 2014Introduction to angular js   july 6th 2014
Introduction to angular js july 6th 2014
Simona Clapan
 

Ähnlich wie Dan Webb Presentation (20)

Working with Javascript in Rails
Working with Javascript in RailsWorking with Javascript in Rails
Working with Javascript in Rails
 
Unobtrusive JavaScript
Unobtrusive JavaScriptUnobtrusive JavaScript
Unobtrusive JavaScript
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Course CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsCourse CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.js
 
1 ppt-ajax with-j_query
1 ppt-ajax with-j_query1 ppt-ajax with-j_query
1 ppt-ajax with-j_query
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
 
Kakunin E2E framework showcase
Kakunin E2E framework showcaseKakunin E2E framework showcase
Kakunin E2E framework showcase
 
243329387 angular-docs
243329387 angular-docs243329387 angular-docs
243329387 angular-docs
 
Get AngularJS Started!
Get AngularJS Started!Get AngularJS Started!
Get AngularJS Started!
 
Ajax Under The Hood
Ajax Under The HoodAjax Under The Hood
Ajax Under The Hood
 
Remote code-with-expression-language-injection
Remote code-with-expression-language-injectionRemote code-with-expression-language-injection
Remote code-with-expression-language-injection
 
Spca2014 hillier 3rd party_javascript_libraries
Spca2014 hillier 3rd party_javascript_librariesSpca2014 hillier 3rd party_javascript_libraries
Spca2014 hillier 3rd party_javascript_libraries
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
Bulletproof Ajax
Bulletproof AjaxBulletproof Ajax
Bulletproof Ajax
 
Bulletproof Ajax
Bulletproof AjaxBulletproof Ajax
Bulletproof Ajax
 
Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016
Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016
Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016
 
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
 
Unit 2.4
Unit 2.4Unit 2.4
Unit 2.4
 
Introduction to angular js july 6th 2014
Introduction to angular js   july 6th 2014Introduction to angular js   july 6th 2014
Introduction to angular js july 6th 2014
 

Mehr von RubyOnRails_dude

Mehr von RubyOnRails_dude (7)

Slides
SlidesSlides
Slides
 
Marcel Molina Jr. Presentation
Marcel Molina Jr. PresentationMarcel Molina Jr. Presentation
Marcel Molina Jr. Presentation
 
Rails4 Days
Rails4 DaysRails4 Days
Rails4 Days
 
Till Vollmer Presentation
Till Vollmer PresentationTill Vollmer Presentation
Till Vollmer Presentation
 
Programminghappiness
ProgramminghappinessProgramminghappiness
Programminghappiness
 
Pursuitofbeauty
PursuitofbeautyPursuitofbeauty
Pursuitofbeauty
 
Worldofresources
WorldofresourcesWorldofresources
Worldofresources
 

Kürzlich hochgeladen

Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...
Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...
Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...
daisycvs
 
Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...
Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...
Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...
amitlee9823
 
Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...
Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...
Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...
Sheetaleventcompany
 
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
Renandantas16
 
Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...
Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...
Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...
lizamodels9
 
Call Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service Bangalore
Call Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service BangaloreCall Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service Bangalore
Call Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service Bangalore
amitlee9823
 
Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...
Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...
Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...
Dipal Arora
 

Kürzlich hochgeladen (20)

Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...
Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...
Quick Doctor In Kuwait +2773`7758`557 Kuwait Doha Qatar Dubai Abu Dhabi Sharj...
 
Forklift Operations: Safety through Cartoons
Forklift Operations: Safety through CartoonsForklift Operations: Safety through Cartoons
Forklift Operations: Safety through Cartoons
 
Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...
Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...
Call Girls Kengeri Satellite Town Just Call 👗 7737669865 👗 Top Class Call Gir...
 
B.COM Unit – 4 ( CORPORATE SOCIAL RESPONSIBILITY ( CSR ).pptx
B.COM Unit – 4 ( CORPORATE SOCIAL RESPONSIBILITY ( CSR ).pptxB.COM Unit – 4 ( CORPORATE SOCIAL RESPONSIBILITY ( CSR ).pptx
B.COM Unit – 4 ( CORPORATE SOCIAL RESPONSIBILITY ( CSR ).pptx
 
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
The Path to Product Excellence: Avoiding Common Pitfalls and Enhancing Commun...
 
Call Girls Service In Old Town Dubai ((0551707352)) Old Town Dubai Call Girl ...
Call Girls Service In Old Town Dubai ((0551707352)) Old Town Dubai Call Girl ...Call Girls Service In Old Town Dubai ((0551707352)) Old Town Dubai Call Girl ...
Call Girls Service In Old Town Dubai ((0551707352)) Old Town Dubai Call Girl ...
 
Value Proposition canvas- Customer needs and pains
Value Proposition canvas- Customer needs and painsValue Proposition canvas- Customer needs and pains
Value Proposition canvas- Customer needs and pains
 
Famous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st CenturyFamous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st Century
 
Falcon Invoice Discounting platform in india
Falcon Invoice Discounting platform in indiaFalcon Invoice Discounting platform in india
Falcon Invoice Discounting platform in india
 
👉Chandigarh Call Girls 👉9878799926👉Just Call👉Chandigarh Call Girl In Chandiga...
👉Chandigarh Call Girls 👉9878799926👉Just Call👉Chandigarh Call Girl In Chandiga...👉Chandigarh Call Girls 👉9878799926👉Just Call👉Chandigarh Call Girl In Chandiga...
👉Chandigarh Call Girls 👉9878799926👉Just Call👉Chandigarh Call Girl In Chandiga...
 
Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...
Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...
Chandigarh Escorts Service 📞8868886958📞 Just📲 Call Nihal Chandigarh Call Girl...
 
Call Girls In Panjim North Goa 9971646499 Genuine Service
Call Girls In Panjim North Goa 9971646499 Genuine ServiceCall Girls In Panjim North Goa 9971646499 Genuine Service
Call Girls In Panjim North Goa 9971646499 Genuine Service
 
BAGALUR CALL GIRL IN 98274*61493 ❤CALL GIRLS IN ESCORT SERVICE❤CALL GIRL
BAGALUR CALL GIRL IN 98274*61493 ❤CALL GIRLS IN ESCORT SERVICE❤CALL GIRLBAGALUR CALL GIRL IN 98274*61493 ❤CALL GIRLS IN ESCORT SERVICE❤CALL GIRL
BAGALUR CALL GIRL IN 98274*61493 ❤CALL GIRLS IN ESCORT SERVICE❤CALL GIRL
 
Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1
 
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
 
Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...
Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...
Call Girls From Pari Chowk Greater Noida ❤️8448577510 ⊹Best Escorts Service I...
 
Call Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service Bangalore
Call Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service BangaloreCall Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service Bangalore
Call Girls Hebbal Just Call 👗 7737669865 👗 Top Class Call Girl Service Bangalore
 
Uneak White's Personal Brand Exploration Presentation
Uneak White's Personal Brand Exploration PresentationUneak White's Personal Brand Exploration Presentation
Uneak White's Personal Brand Exploration Presentation
 
Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...
Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...
Call Girls Navi Mumbai Just Call 9907093804 Top Class Call Girl Service Avail...
 
Mondelez State of Snacking and Future Trends 2023
Mondelez State of Snacking and Future Trends 2023Mondelez State of Snacking and Future Trends 2023
Mondelez State of Snacking and Future Trends 2023
 

Dan Webb Presentation

  • 1. Unobtrusive Ajax With Rails Dan Webb (dan@danwebb.net)
  • 2. Overview A bit of history ★ What is unobtrusive scripting? ★ The UJS Plugin ★ Casestudy ★ Ranting Upcoming UJS Features ★
  • 3. The dark days of DHTML
  • 4.
  • 5.
  • 6.
  • 8. The Client-side Cake Style - CSS Content - (X)HTML
  • 9. What web standards did for us More maintainable ★ More accessible ★ Leaner pages ★ Platform independent (print, mobile...) ★ 'Future-proof' as well as backwards ★ compatible
  • 10. JavaScript got a bad name
  • 18. Browser support is much better
  • 19. We learnt our lessons from the DHTML days
  • 20. What did we learn?
  • 21. Unobtrusive DOM Scripting
  • 22. It's an approach to browser UI design
  • 23. It's about separating content and style from behaviour
  • 24. Behaviour: A new layer for the client-side cake Behaviour - JavaScript Style - CSS Content - (X)HTML
  • 26. so it degrades gracefully when things don't work
  • 27. It's not just about putting JavaScript in a different file
  • 28. It's not rocket science
  • 31. <%= link_to_remote 'View description', :controller => 'product', :action => 'desc', :id => @product.id %>
  • 32. <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/ desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>
  • 33. # better... <a href=quot;/product/desc/1quot; onclick=quot;new Ajax.Request(this.href, {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>
  • 34. It's not possible to do that with link_to_remote
  • 35. <% @products.each do |product| %> <%= link_to_remote 'View description', :controller => 'product', :action => 'desc', :id => @product.id %> <% end %>
  • 36. <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>
  • 37. <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a> <a href=quot;#quot; onclick=quot;new Ajax.Request('/product/desc/1', {asynchronous:true, evalScripts:true}); return false;quot;>View description</a>
  • 39. The UJS Plugin A plugin to aid unobtrusive scripting ★ with Rails Allows you to define behaviours via ★ CSS selectors Keeps script in an external, cacheable ★ files www.ujs4rails.com - check it out! ★
  • 41. <ul id=quot;outlinequot;> <% @items.each do |item| %> <li><%= link_to :action => 'more', :id => @item.id %></li> <% end %> </ul>
  • 42. <ul id=quot;outlinequot;> <% @items.each do |item| %> <li><%= link_to :action => 'more', :id => @item.id %></li> <% end %> </ul> <% apply_behaviour '#outline a:click', 'new Ajax.Request(this.href); return false;' %>
  • 43. <ul id=quot;outlinequot;> <% @items.each do |item| %> <li><%= link_to :action => 'more', :id => @item.id %></li> <% end %> </ul> <% apply_behaviour '#outline a', make_remote_link %>
  • 44. What about links with side-effects?
  • 45. Links should never have side effects
  • 46. Use a button <%= button_to 'Remove from basket', :method => :delete %>
  • 47. <form class=quot;button-toquot; action=quot;/basket/2quot; method=quot;postquot;> <input type=quot;hiddenquot; name=quot;_methodquot; value=quot;deletequot; /> <input type=quot;submitquot; value=quot;Remove from basketquot; /> </form>
  • 48. Then attach the behaviour <%= button_to 'Remove from basket', :method => :delete %> <% apply_behaviour 'form.button-to', make_remote_form %>
  • 50. <%= form_tag :url => entries_url, :id => 'comment' %> <%= text_field :name %> <%= text_field :email %> <%= text_area :comment %> <%= submit_tag 'Post comment' %> <%= end_form_tag %>
  • 51. <%= form_tag :url => entries_url, :id => 'comment' %> <%= text_field :name %> <%= text_field :email %> <%= text_area :comment %> <%= submit_tag 'Post comment' %> <%= end_form_tag %> <% apply_behaviour '#comment:submit', 'new Ajax.Request(this.action, { parameters : Form.serialize(this)}); return false;' %>
  • 52. <%= form_tag :url => entries_url, :id => 'comment' %> <%= text_field :name %> <%= text_field :email %> <%= text_area :comment %> <%= submit_tag 'Post comment' %> <%= end_form_tag %> <% apply_behaviour '#comment', make_remote_form %>
  • 53. A Case Study Sneakr.com: A Web 2.0, Ajax Trainer Shop
  • 54. routes.rb map.resource :products map.resource :basket, :controller => 'basket', :collection => {:clear => :post}
  • 55. The Product Controller class ProductController < ApplicationController def index # show all products @products = Product.find :all end def show # show the details of a product @product = Product.find params[:id] end end
  • 56. index.rhtml <div id=quot;cataloguequot;> <%= render :partial => 'products' %> </div> <div id=quot;basketquot;> <%= render :partial => 'basket' %> </div>
  • 57. _products.rhtml <ul> <% @products.each do |product| %> <li id=quot;<%= product.id %>_prodquot;> <%= link_to product.name, product_url(product) %> <%= product.description %> </li> <% end %> </ul>
  • 58. show.rhtml <h1><%= @product.name %></h1> <p><%= image_tag @product.photo.public_filename %></p> <p><%= @product.description %></p> <p><%= button_to 'Add To Basket', basket_url (@product), :method => :put %></p>
  • 59. The Basket Controller class BasketController < ApplicationController def update @product = Product.find params[:id] @basket << @product redirect_to products_url end end
  • 61. now to add the Ajax
  • 62. <% apply_behaviours do on '#catalogue li', make_draggable(:revert => true) on '#basket', make_drop_receiving( :url => basket_url, :with => quot;'_method=put&id=' + encodeURIComponent(element.id)quot; ) end %>
  • 63. <% apply_behaviours do on '#catalogue li', make_draggable(:revert => true) on '#basket', make_drop_receiving( :url => basket_url, :with => quot;'_method=put&id=' + encodeURIComponent(element.id)quot; ) end %>
  • 64. So how do we deal with this on the server-side?
  • 66. class BasketController < ApplicationController def update @product = Product.find params[:id] @basket << @product redirect_to products_url end end
  • 67. class BasketController < ApplicationController def update @product = Product.find params[:id] @basket << @product respond_to do |type| type.html { redirect_to products_url } type.js end end end
  • 69. Take a look for yourself... http://www.danwebb.net/railsconf2006/ujs_shopping.zip
  • 70. We have no control over the environment our JavaScript runs in
  • 72. The path to enlightenment Write a working application using ★ semantic HTML Style it with CSS ★ Write JavaScript that 'hijacks' the page ★ elements to enhance the UI Learn JavaScript and DOM Scripting ★
  • 73. Further Reading The JavaScript articles on A List Apart ★ (alistapart.com) Unobtrusive Scripting by Christian ★ Heilmann (onlinetools.org) Jeremy Keith's presentations, book and ★ articles (domscripting.com) Google it! ★
  • 74. Upcoming in UJS Improved testing (custom assertions) ★ Improved debugging ★ More behaviour helpers ★ More tutorials on ujs4rails.com ★
  • 75. And finally... <%= apply_behaviour @products, make_draggable %>
  • 76. <% div_for @product, :behavior => make_draggable do %> <h2><%= @product.name %></h2> <p><%= @product.description %></p> <% end %>