Unobtrusive Ajax
With Rails

Dan Webb (dan@danwebb. net)
Overview

air A bit of history
fir What is unobtrusive scripting? 
* The UJS Plugin

air Casestudy
* Ranti+= ig—Upcoming UJ...
The dark days of
DHTML
an

  H 
 ‘/ ’i: ’~l‘7'

This is best viewed in 800 x 600 resolution.  We strongly suggest that you have
"Internet Explore...
'3“ Microsoft
Internet
Explorer

la 4. l3‘lllit

M: 

This site is best viewed with 4.0 and up versions of
Netscape Naviga...
on-line CIV

This site has been optimised for lE4+ and Netscape
4+ with 800x600 resolution. 

Flash site

2-2. HTl/ ll_ site
Then web standards
arrived
DEN HEBB. N£: T

The C| ient—side Cake

Style - CSS

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

* More maintainable

at More accessible

fir Leaner pages

* Platform independent (print,  m...
JavaScript got a
bad name
It deserved it
Web 2.0
llllll ll

‘ ‘:3 l:  l  l:  ji i all   

In

35

$333.-sin‘
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 Ul design
It's about separating
content and style
from behaviour
DEN HEBB. Nt: T

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 notju_st about
putting JavaScript in
a different file
It's not rocket
science
It's not the
‘Rails Way‘
An example: 
1ink_to_remote
DEN HEBB. NeT

<%=  1ink_to_remote ‘View description‘, 
zcontroller = > 'product', 
:action = > 'desc', 
zid = > @product....
DEN HEBB. NeT

<a href= ”#" onc1ick= "new Ajax. Request('/ product/ 
desc/1',  {asynchronous true,  eva1Scripts: true}); 
...
DEN HEBB. NeT

<a href= ”/product/ desc/1” onc1ick= ”new
Ajax. Request(this. href,  {asynchronous true, 
eva1Scripts: true...
It's not possible to
do that with
| ink_to_remote
DEN HEBB. NeT

<% @products. each do lproductl %>

<%=  link_to_remote ‘View description‘, 
zcontroller = > 'product‘, 
:a...
DEN HEBB. NeT

     

vrcduct

 

<a href=  onc1ick= “"on A1ax. Roq _
return la se; ”>View description</ a>

'4'

{as ch"o...
(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a

(a...
Getting started
DllN llEBB. Nt: T

The UJS Plugin

A plugin to aid unobtrusive scripting
with Rails

Allows you to define behaviours via
C...
Remote Links
DEN HEBB. NeT

<u1 id= "outline">
<% @items. each do liteml %>

<li><%=  1ink_to : action = > ‘more’, 
zid = > @item. id %...
DEN HEBB. NeT

<u1 id= "out1ine">
<% @items. each do liteml %>

<1i><%=  1ink_to : action = > ‘more’, 
zid = > @item. id %...
DEN HEBB. NeT

<u1 id= "out1ine">
<% @items. each do liteml %>

<li><%=  link_to : action = > ‘more’, 
:id = > @item. id %...
What about links
with side-effects?
Links should never
have side effects
DllN llEBB. Nt: T

Use a button

<%=  button_to ‘Remove from basket‘, 
zmethod = > zdelete %>
[_lnN HEBB. NeT

<for'm c1ass= "button-to" action= "/basket/2" method= "post">
<input type= "hidden" name= “_method" va1ue...
DllN llEBB. Nt: T

Then attach the behaviour

<%=  button_to ‘Remove from basket‘, 
zmethod = > zdelete %>

<% apply_behav...
Hijacking forms
DEN HEBB. NeT

<%=  form_tag zurl = > entries_ur1, zid = > ‘comment’ %>
<%=  text_field : name %>
<%=  text_field zemail %...
DEN HEBB. NeT

<%=  form_tag : ur1 = > entries_ur1, zid = > ‘comment’ %>
<%=  text_field : name %>
<%=  text_fie1d : email...
DEN HEBB. NeT

<%=  form_tag : ur1 = > entries_ur1, zid = > ‘comment’ %>
<%=  text_fie1d : name %>
<%=  text_field : email...
l]llN llEBB. Nt: T

A Case Study

Sneakr. com:  A Web 2.0, Ajax Trainer Shop
DllN llEBB. Nt: T

routes. rb

map. resource zproducts
map. resource zbasket,  zcontroller = > ‘basket’, 

zcollection = >...
The Product Controller

class ProductContro11er < App1icationContro11er
def index # show all products
@products =  Product...
DllN llEBB. Nt: T

index. rhtml

<div id= "cata1ogue">
<%=  render zpartial
</ div>

<div id= "basket">
<%=  render zparti...
DllN llEBB. Nt: T

_products. rhtm| 

<ul>
<% @products. each do lproductl %>

<1i id= "<%=  product. id %>_prod">

<%=  1...
DllN llEBB. Nt: T

show. rhtm| 

<h1><%=  @product. name %></ h1>
<p><%=  image_tag @product. photo. pub1ic_fi1ename %></ ...
DllN llEBB. Nt: T

The Basket Controller

class BasketController < ApplicationController
def update

@product =  Product. ...
We're done!
now to add the Ajax
DEN HEBB. NeT

<% apply_behaviours do

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

end %>
DEN HEBB. NeT

on ’#basket’,  make_drop_receiving(
zurl = > basket_url, 
zwith = > "’_method= put&id= ' +
encodeURICompone...
So how do we deal
With this on the
server—side?
respond_to
DEN HEBB. NeT

class BasketController < ApplicationController
def update

@product =  Product. find params[ id]
@basket <<...
DEN HEBB. NeT

respond_to do ltypel
type. html { redirect_to products_url }

type. js
end
DllN llEBB. Nt: T

update. rjs

page. replace_html ‘basket’, 
:partial = > ‘basket’
llllN llEBB. Nt: T

Take a look for
yourself. ..

http: //www. danwebb. net/ rai| sconf2006/ujs_shopping. zip
We have no control
overthe
environment our
JavaScript runs in
Code defensively
DllN llEBB. Nt: T

The path to enlightenment

Write a working application using
semantic HTML

Style it with CSS

Write Ja...
DllN llEBB. Nt: T

Further Reading

The JavaScript articles on A List Apart
(alistapart. com)

Unobtrusive Scripting by Ch...
DllN llEBB. Nt: T

Upcoming in UJS

Improved testing (custom assertions)
Improved debugging
More behaviour helpers

More t...
DllN llEBB. Nt: T

And finally. ..

<%=  apply_behaviour @products,  make_draggable %>
DEN HEBB. NeT

<% div_for @product,  zbehavior = > make_draggable do %>

<hZ><%=  @product. name %></ h2>
<p><%=  @product...
' iltl llbfliiisltr

l . l l . l   ‘ ii i if I ll
Upcoming SlideShare
Loading in …5
×

Unobtrusive Ajax With Rails

15,482 views

Published on

Dan Webb (dan@danwebb.net) From: www.danwebb.net/railsconf2006/ujs_railsconf.pdf

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

No Downloads
Views
Total views
15,482
On SlideShare
0
From Embeds
0
Number of Embeds
61
Actions
Shares
0
Downloads
1
Comments
0
Likes
32
Embeds 0
No embeds

No notes for slide

Unobtrusive Ajax With Rails

  1. 1. Unobtrusive Ajax With Rails Dan Webb (dan@danwebb. net)
  2. 2. Overview air A bit of history fir What is unobtrusive scripting? * The UJS Plugin air Casestudy * Ranti+= ig—Upcoming UJS Features
  3. 3. The dark days of DHTML
  4. 4. an H ‘/ ’i: ’~l‘7' This is best viewed in 800 x 600 resolution. We strongly suggest that you have "Internet Explorer 5.0”. Can be viewed with lntemet Explorer 3.0 and Netscape Navigator 3.0. If your computer is not 800 x 600 res. You would not be able to view this site property. 1 / /
  5. 5. '3“ Microsoft Internet Explorer la 4. l3‘lllit M: This site is best viewed with 4.0 and up versions of Netscape Navigator/ Communicator or Microsoft Intemet Explorer. Some downloadable documents can only be viewed with Adobe® Acrobat® Reader. Click on any of the Icon's to download the latest software.
  6. 6. on-line CIV This site has been optimised for lE4+ and Netscape 4+ with 800x600 resolution. Flash site 2-2. HTl/ ll_ site
  7. 7. Then web standards arrived
  8. 8. DEN HEBB. N£: T The C| ient—side Cake Style - CSS Content - (X)HTML
  9. 9. What web standards did for us * More maintainable at More accessible fir Leaner pages * Platform independent (print, mobile. ..) * ‘Future-proof‘ as well as backwards compatible
  10. 10. JavaScript got a bad name
  11. 11. It deserved it
  12. 12. Web 2.0
  13. 13. llllll ll ‘ ‘:3 l: l l: ji i all In 35 $333.-sin‘
  14. 14. Massive text boxes
  15. 15. Social software
  16. 16. and Ajax. ..
  17. 17. JavaScript is trendy again!
  18. 18. Browser support is much better
  19. 19. We learnt our lessons from the DHTML days
  20. 20. What did we learn?
  21. 21. Unobtrusive DOM Scripting
  22. 22. It's an approach to browser Ul design
  23. 23. It's about separating content and style from behaviour
  24. 24. DEN HEBB. Nt: T Behaviour: A new layer for the client—side cake Behaviour - JavaScript Style - CSS Content - (X)HTML
  25. 25. It's enhancing a working application
  26. 26. so it degrades gracefully when things don't work
  27. 27. It's notju_st about putting JavaScript in a different file
  28. 28. It's not rocket science
  29. 29. It's not the ‘Rails Way‘
  30. 30. An example: 1ink_to_remote
  31. 31. DEN HEBB. NeT <%= 1ink_to_remote ‘View description‘, zcontroller = > 'product', :action = > 'desc', zid = > @product. id %>
  32. 32. DEN HEBB. NeT <a href= ”#" onc1ick= "new Ajax. Request('/ product/ desc/1', {asynchronous true, eva1Scripts: true}); return fa1se; ”>View description</ a>
  33. 33. DEN HEBB. NeT <a href= ”/product/ desc/1” onc1ick= ”new Ajax. Request(this. href, {asynchronous true, eva1Scripts: true}); return fa1se; ”>View description</ a>
  34. 34. It's not possible to do that with | ink_to_remote
  35. 35. DEN HEBB. NeT <% @products. each do lproductl %> <%= link_to_remote ‘View description‘, zcontroller = > 'product‘, :action = > 'desc', zid = > @product. id %> <% end %>
  36. 36. DEN HEBB. NeT vrcduct <a href= onc1ick= “"on A1ax. Roq _ return la se; ”>View description</ a> '4' {as ch"o"cus: truo. ova Scr17ts: trao} <a href= ”W' onclick= vrcduct roturn la so; ”>View description</ a> rn A1ax. {oq {usy"th"o"cus: . ' Str1vts: truo}); <a href= ”t' onc1ick= in Aiax. <oqJcst(‘ vrcduct roturn la sr ”>View description</ a> {usy"th"o"cus: truo. ova Scr1vts: truo}); <a href= ”¢' onc1ick= “~ou Aiax. “ "vrcdutt dost ‘. {asyethro —: trao. ova Str1its: truo}); return la ”>View description</ a> <a href= ”"' onc1ick= “ren A]ax. ’eaJest{' ~rcduct ; h"o"cus: true. eva Scr17ts: true}): return la ' ”>View description</ a> <a href= ”v' onc1ick= “"on Aiax. “ vrcduct 'h"o"cus: truo. ova Scr1vts: trao}); "Oturn fa so; ”>View description</ a> <a href= ”v' onc1ick= “"on A1ax.1oqJos vrcduct JCBC '. {asvrch"o"cus: truo. ova Scr1vts: trao}); return la se; ”>View description</ a> vrcduct <a href= ”t' onc1ick= “ jn Aiax. <oqJcst( return fa se; ”>View description</ a> {usy"th"o"cus: truo. ova Scr1vts: truo}); Lt‘ vrcduct <a href= ”t' onc1ick= “ on A}ax. {oq roturn la sr ”>View description</ a> {usy"th"o"cus: . ' Scr1vts: truo}); <a href= ‘¢ onc1ick= “~on A1ax. ?oqJost(">rcdutt dost ‘. {asy"chro"cJ2:trao. ova Str1its: truo}); roturn la so; ”>View description</ a> <a href= ”¢' onc1ick= “ren A]ax. ’eaJest{' ~rcduct descr ; h"o"cus: true. eva Scr17ts: true}): roturn la so; ”>View description</ a> <a href= ”¢' onc1ick= “ren A]ax. ’eaJest{' ~rcduct descr ‘. {asv"ch"o"cus: true. eva Scr17ts: true}): roturn la so; ”>View description</ a> <a href= ”v' onc1ick= “"on Aiax. “ vrcduct {asvrch"o"cus: truo. ova Scr1vts: trao}); "Oturn fa so; ”>View description</ a> <a href= onc1ick= “"on A1ax.1oqJost(' vrcduct JCBC '. {asvrch"o"cus: truo. ova Scr1vts: trao}); return la >View description</ a>
  37. 37. (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a (a href-“I” href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" href-"I" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-" oncltck-' oncltck-" nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu nu ‘nu nu Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax. Ajax Ajax RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( ' / product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , RegJest( '/ product/ desc/1' , .RegJest( ' / product/ desc/1' , .RegJest( '/ product/ desc/1' , (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: (asynchronous: true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: eval Scrlpts: (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): (Welt): f| 'U¢)): (Welt): (Welt): return return return return return return return return return return return return return return return return return return return return return return return return return return return return return return return return false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " false; " >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vien >Vi en descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a> descr1ption</ as descr1ption</ a>
  38. 38. Getting started
  39. 39. DllN llEBB. Nt: T 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 wvvw. ujs4rai| s.com - check it out!
  40. 40. Remote Links
  41. 41. DEN HEBB. NeT <u1 id= "outline"> <% @items. each do liteml %> <li><%= 1ink_to : action = > ‘more’, zid = > @item. id %></ li> <% end %> </ u1>
  42. 42. DEN HEBB. NeT <u1 id= "out1ine"> <% @items. each do liteml %> <1i><%= 1ink_to : action = > ‘more’, zid = > @item. id %></ li> <% end %> </ u1> <% app1y_behaviour '#outline a click‘, ‘new Ajax. Request(this. href); return false; ' %>
  43. 43. DEN HEBB. NeT <u1 id= "out1ine"> <% @items. each do liteml %> <li><%= link_to : action = > ‘more’, :id = > @item. id %></ li> <% end %> </ ul> <% app1y_behaviour ‘#out1ine a‘, make_remote_1ink %>
  44. 44. What about links with side-effects?
  45. 45. Links should never have side effects
  46. 46. DllN llEBB. Nt: T Use a button <%= button_to ‘Remove from basket‘, zmethod = > zdelete %>
  47. 47. [_lnN HEBB. NeT <for'm c1ass= "button-to" action= "/basket/2" method= "post"> <input type= "hidden" name= “_method" va1ue= "de1ete" / > <input type= “submit" value= "Remove from basket" / > </ form>
  48. 48. DllN llEBB. Nt: T Then attach the behaviour <%= button_to ‘Remove from basket‘, zmethod = > zdelete %> <% apply_behaviour 'form. button—to', make_remote_form %>
  49. 49. Hijacking forms
  50. 50. DEN HEBB. NeT <%= form_tag zurl = > entries_ur1, zid = > ‘comment’ %> <%= text_field : name %> <%= text_field zemail %> <%= text_area : comment %> <%= submit_tag ‘Post comment‘ %> <%= end_Form_tag %>
  51. 51. DEN HEBB. NeT <%= form_tag : ur1 = > entries_ur1, zid = > ‘comment’ %> <%= text_field : name %> <%= text_fie1d : 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. 52. DEN HEBB. NeT <%= form_tag : ur1 = > entries_ur1, zid = > ‘comment’ %> <%= text_fie1d : name %> <%= text_field : email %> <%= text_area : comment %> <%= submit_tag ‘Post comment‘ %> <%= end_form_tag %> <% app1y_behaviour ‘#comment‘, make_remote_form %>
  53. 53. l]llN llEBB. Nt: T A Case Study Sneakr. com: A Web 2.0, Ajax Trainer Shop
  54. 54. DllN llEBB. Nt: T routes. rb map. resource zproducts map. resource zbasket, zcontroller = > ‘basket’, zcollection = > {zclear = > zpost}
  55. 55. The Product Controller class ProductContro11er < App1icationContro11er def index # show all products @products = Product. find : a11 end def show # show the details of a product @product = Product. find params[: id] end end
  56. 56. DllN llEBB. Nt: T index. rhtml <div id= "cata1ogue"> <%= render zpartial </ div> <div id= "basket"> <%= render zpartial </ div> = > = > ‘products’ %> ‘basket’ %>
  57. 57. DllN llEBB. Nt: T _products. rhtm| <ul> <% @products. each do lproductl %> <1i id= "<%= product. id %>_prod"> <%= 1ink_to product. name, product_url(product) %> <%= product. description %> </1i> <% end %> </ u1>
  58. 58. DllN llEBB. Nt: T show. rhtm| <h1><%= @product. name %></ h1> <p><%= image_tag @product. photo. pub1ic_fi1ename %></ p> <p><%= @product. description %></ p> <p><%= button_to ‘Add To Basket’, basket_ur1 (@product), zmethod = > zput %></ p>
  59. 59. DllN llEBB. Nt: T The Basket Controller class BasketController < ApplicationController def update @product = Product. find params[: id] @basket << @product redirect_to products_url end end
  60. 60. We're done!
  61. 61. now to add the Ajax
  62. 62. DEN HEBB. NeT <% apply_behaviours do on ’#catalogue li’, make_draggable(: revert = > true) end %>
  63. 63. DEN HEBB. NeT on ’#basket’, make_drop_receiving( zurl = > basket_url, zwith = > "’_method= put&id= ' + encodeURIComponent(element. id)"
  64. 64. So how do we deal With this on the server—side?
  65. 65. respond_to
  66. 66. DEN HEBB. NeT class BasketController < ApplicationController def update @product = Product. find params[ id] @basket << @product redirect_to products_url end end
  67. 67. DEN HEBB. NeT respond_to do ltypel type. html { redirect_to products_url } type. js end
  68. 68. DllN llEBB. Nt: T update. rjs page. replace_html ‘basket’, :partial = > ‘basket’
  69. 69. llllN llEBB. Nt: T Take a look for yourself. .. http: //www. danwebb. net/ rai| sconf2006/ujs_shopping. zip
  70. 70. We have no control overthe environment our JavaScript runs in
  71. 71. Code defensively
  72. 72. DllN llEBB. Nt: T 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. 73. DllN llEBB. Nt: T Further Reading The JavaScript articles on A List Apart (alistapart. com) Unobtrusive Scripting by Christian Heilmann (on| inetools. org) Jeremy Keith's presentations, book and articles (domscripting. com) Google it!
  74. 74. DllN llEBB. Nt: T Upcoming in UJS Improved testing (custom assertions) Improved debugging More behaviour helpers More tutorials on ujs4rai| s.com
  75. 75. DllN llEBB. Nt: T And finally. .. <%= apply_behaviour @products, make_draggable %>
  76. 76. DEN HEBB. NeT <% div_for @product, zbehavior = > make_draggable do %> <hZ><%= @product. name %></ h2> <p><%= @product. description %></ p> <% end %>
  77. 77. ' iltl llbfliiisltr l . l l . l ‘ ii i if I ll

×