+ All Categories
Home > Documents > UC Berkeley Intro to AJAX

UC Berkeley Intro to AJAX

Date post: 19-Jan-2015
Category:
Upload: sampetruda
View: 797 times
Download: 8 times
Share this document with a friend
Description:
 
Popular Tags:
31
UC Berkeley Intro to AJAX & Rails [email protected] Ito learn about april 11-12 CSUA hackathon CS 98-10/CS 198-10 Web 2.0 Programming Using Ruby on Rails Armando Fox
Transcript
Page 1: UC Berkeley Intro to AJAX

UC Berkeley

Intro to AJAX & [email protected] Ito learn

about april 11-12 CSUA hackathon

CS 98-10/CS 198-10

Web 2.0 Programming Using Ruby on Rails

Armando Fox

Page 2: UC Berkeley Intro to AJAX

Review: Partials

• Reusable chunk of a view– e.g., one line of a Student table– e.g., form to display/capture Student info that can be used as

part of Edit, Show, Create,...– file naming convention: the partial foo for model bar is in

app/views/bar/_foo.rhtml

• by default, partial expects a local (not instance) variable whose name matches partial’s filename

• in “caller”: render :partial => 'student'

– sets local student from instance var @student– override with (e.g.) :object => @other_student– useful when calling same partial from different views

• in partial: use student (not @student)

Page 3: UC Berkeley Intro to AJAX

Review: collection of partials

• Common idiom:@students.each do |student|

render :partial => 'student'

• Captured by:render :partial => 'student',

:collection => @good_students

– local student in partial is set successively to each value in @good_students (using each)

– other options allow specifying “divider” template

• Can also pass local variables :locals => {:stu_info => @other_info}

Page 4: UC Berkeley Intro to AJAX

Ajax: Web 1.0 Web 2.0

• Web 1.0 (“old world”) GUI: click page reload• Web 2.0: click page updates in place

– also timer-based interactions, drag-and-drop, animations, etc.

How is this done?1. Document Object Model (c.1998, W3C) represents document

as a hierarchy of elements

2. JavaScript (c.1995; now ECMAScript) makes DOM available programmatically, allowing modification of page elements after page loaded

3. XMLHttpRequest (MSIE 5, c.2000; others, c.2002) allows async HTTP transactions decoupled from page reload

Page 5: UC Berkeley Intro to AJAX

DOM & JavaScript:Document = tree of objects

• A platform-independent (?) hierarchical object model representing HTML or XML doc– part of a separate standards effort; in practice,

implementations vary

• Exposed to JavaScript interpreter– Inspect DOM element value/attribs– Change value/attribs redisplay

• Key concept: every element can be given a unique ID (separate from its name), which can be referenced from within JavaScript handlers– Can also “walk the DOM” to find an element but it’s not

recommended

QuickTime™ and aTIFF (Uncompressed) decompressor

are needed to see this picture.

<input type="text" name="phone_number" id="phone_number"/><script type="text/javascript"> var phone = document.getElementById('phone_number'); phone.value='555-1212'; phone.disabled=true; document.images[0].src="http://.../some_other_image.jpg";</script>

Page 6: UC Berkeley Intro to AJAX

JavaScript

• A dynamic, interpreted, object-oriented browser-side scripting language– JavaScript interpreter is part of the browser– embedded in most browsers since c.1998

• Browser exposes some of its rendering engine & attributes to JavaScript environment– eg, window, document objects– eg, XmlHttpRequest browser method

• JavaScript handlers allow associating JavaScript functions with events on DOM elements– e.g., onClick, onMouseOver, onFocus...

Page 7: UC Berkeley Intro to AJAX

DOM: Attributes

• Attributes: the state of a DOM element– current text typed into a text box?– current selection of a dropdown menu?

• A common idiom:m = document.getElementById("course_menu");menuText=m.options[m.selectedIndex].value;

• In an element’s handler, this is set to the object representing the element<a href="#" onClick="this.innerHTML='Presto!'">Click me</a>

Page 8: UC Berkeley Intro to AJAX

Handlers on Buttons & Links

• A good summary of recognized handlers:http://www.chipchapin.com/WebTools/JavaScript/example1-04.html

– a few common ones: onClick, onSubmit, onChange, onLoad/onUnload, onChange

– not every handler applies to every HTML element

• What about links & buttons?– if handler returns false, no other action taken– otherwise, other actions follow handler– example: client-side form validation

• Handler code can be inline or functions...let’s see an example

Page 9: UC Berkeley Intro to AJAX

XMLHttpRequest (aka xhr)

• separates HTTP request/response from page render– Web 1.0: every HTTP request renders page anew– Web 2.0: HTTP requests can occur “in the

background” after page is rendered– XHR’s do not re-render page, but can selectively

change DOM objects

• Requires support in browser– Originally: Microsoft IE 5 (c.2000), now in all major

browsers (some minor incompatibilities)

Page 10: UC Berkeley Intro to AJAX

So: What’s AJAX?

• Asynchronous JavaScript And XML– Early showcase app: Google Maps

• Recipe (to a zeroth order):– attach JavaScript handlers to various events on browser objects

(so you get notified when user interacts with page elements)– in callback, inspect/modify DOM elements and optionally do an

asynchronous HTTP req. to server– on server response, pass result to yet another JavaScript

function that will monkey with DOM again

• Rails integrates seamless Ajax support– Prototype to deal with cross-browser issues, common Ajax

functionality, etc.– Script.aculo.us, a JavaScript library of visual effects

Page 11: UC Berkeley Intro to AJAX

XHR (simplified)

r=XmlHttpRequest.newr.open(method,URL,async)

method GET,POST,HEAD,PUT,DELETE...async: should script continue without waiting?

r.send(request_content)r.abort()

• Callbacks during XHR processing– r.onReadyStateChange = (Javascript function

reference)– function inspects r.readyState uninitialized,open,

sent,receiving,loaded• r.status contains HTTP status of response• r.responseText contains response content string

Page 12: UC Berkeley Intro to AJAX

Javascript handlers (simplified)

<input type="button" value="Extra Contact Info..." onClick="Effect.toggle('contact','slide',{});" />

• example: onClick handler called when form button is clicked• handler calls JavaScript function toggle in Effect class

(which happens to be part of script.aculo.us)– for this function, first arg refers to a DOM element ID, second arg

refers to name of visual effect to apply, third arg is hash of optional additional params (empty in this call)

– function toggles whether contact element is hidden or showing, and uses slide effect to transition between!

– compare simpler:onClick="e=getElementById('contact');

if e.style.display=='none' {e.style.display='inline'; } else { e.style.display='none'; }"

Page 13: UC Berkeley Intro to AJAX

Other common uses of “inline” JavaScript

• Rails provides Javascript helpers that generate Javascript code in your RHTML templates

• Example: “Are you sure?” dialog<%= button_to("Remove",

{:action=>'destroy_something',:id=>@voucher}, {:confirm=>"Are you sure?"}) %>

Note careful use of braces!!

<form method="post" action="/vouchers/remove_voucher/707" class="button-to"><div> <input onclick="return confirm('Are you sure?');"

type="submit" value="Remove"/></div></form> • Example: popup alert box: <%= alert('You suck.') %>

Page 14: UC Berkeley Intro to AJAX

Inline JS, continued

• Example: “Processing...” form button:<%= submit_tag 'Submit', {:disable_with => 'Please

Wait'} %>

• produces: <input name="commit"

onclick="this.disabled=true;this.value='Please Wait';this.form.submit();" type="submit" value="Download Report in Excel format" />

Page 15: UC Berkeley Intro to AJAX

Updating page content using JavaScript

• General strategy– “containerize” the updatable content in a DOM

element (can always use <span>)– use the innerHTML property to modify the

HTML inside the element tags

• A really trivial example....

Page 16: UC Berkeley Intro to AJAX

prototype Javascript library captures common xhr usage

• Common pattern: encapsulate xhr call to update-in-place some content on page– URL to call on remote server– DOM ID tag of element whose “inner HTML” (i.e.

content) should be replaced with result

• Example: do something in response to immediate user input (e.g. auto-completion)– DOM ID tag(s) of element(s) on page to monitor for

user input (text fields, menus, whole form, etc.)– URL to call on remote server when content changes

(passes new content as argument)

Page 17: UC Berkeley Intro to AJAX

prototype (prototypejs.org) & Scriptaculous (script.aculo.us)

• prototype also hides some cross-browsers differences in Javascript/XHR implementations– eg, portable $() function to dereference DOM element by its ID$("submit_btn").disabled = true;

var AjaxOpts = {

method: "get",

parameters: "id=3&user=" + $("usrname").value,

onComplete: displayResponse };

var AjaxReq = new Ajax.Request (url,AjaxOpts);

function displayResponse() {...}

• script.aculo.us encapsulates various visual effects obtained by careful manipulation of DOM properties– e.g. blind up, blind down to show/hide some text

Page 18: UC Berkeley Intro to AJAX

Putting it together: AJAX the Rails way

• Event handlers are just controller methods!– Rails wrappers around prototype library

functions marshal arguments & do XHR call

• Method can tell how it was called by using respond_to do |wants| wants.js { ... }– But may be cleaner to have separate

controller methods for xhr vs. regular forms

Page 19: UC Berkeley Intro to AJAX

Getting Results from the Server, the Rails way

• Typically, results replace content of an HTML element– Remember you can “elementize” (almost) any

arbitrary chunk using <span id="foo"> or <div id="foo">

• Controller method can use render :partial to produce a result– Typical example: table with collapsible entries– or render :text to send raw content back

Page 20: UC Berkeley Intro to AJAX

An example: rhtml & JS

<% @donations.each do d %><div id="donation_<%=d.id-%>">....<%= link_to_remote 'Mark Sent', :update=>"donation_#{d.id}",

:url=>{:action=>'mark_ltr_sent', :id=>d.id} %>

The rendered page looks like this:<div id='donation_751'>

<a href="#" onclick="new Ajax.Updater('donation_751', '/donation/mark_ltr_sent/751',

{asynchronous:true, evalScripts:true}); return false;">Mark Sent</a>

Page 21: UC Berkeley Intro to AJAX

The controller method...

def mark_ltr_sent begin t = Donation.find(params[:id])

c = Customer.find(logged_in_id) t.update_attributes(:letter_sent => now, :processed_by => c.id) render :text => "#{Time.now} by #{c.login}" rescue render :text => "(ERROR)" end end

Page 22: UC Berkeley Intro to AJAX

Listening For Events

• Not surprisingly, Rails lets you listen at the element or form level

observe_field('student[last_name]', :url => {:controller=>'students',

         :action=>'lookup_by_lastname'}, :update=>'lastname_completions')

• when student[last_name] field changes, call method lookup_by_lastname in StudentController with new field value

• returned text from controller method will replace the “inner contents” of element ID lastname_completions– typically using render :partial or render :text

Page 23: UC Berkeley Intro to AJAX

Listening on a Whole Form

observe_form('student_form', :url => {:controller => 'students',          :action => 'process_form'},

:update => 'student_info_panel')

• When any element of student_form changes, call process_form method in StudentsController, marshalling all elements into params[]

Page 24: UC Berkeley Intro to AJAX

State changes & visual effects

• Additional arguments allow specifying callbacks– states: server contacted, waiting, receiving,

donelink_to_remote('Show article',

:update => 'article_content',:url => {:action => 'get_article_text',:id => article},:before => "Element.show('spinner')",:complete => "Element.hide('spinner')",404 => alert("Article text not found!"))

Page 25: UC Berkeley Intro to AJAX

Important to remember...

• All of these types of JS “helpers” expand to JavaScript code in your .rhtml template

1. <%= javascript_include_tag :defaults %> in RHTML template expands to:

<script src="/javascripts/prototype.js" type="text/javascript"></script> ...various other script files loaded...<script src="/javascripts/application.js" type="text/javascript"></script>

2. <%= link_to_remote ... %> in RHTML expands to more JS3. Browser loads page with all expansions4. User clicks link, invoking JavaScript function5. Your app server gets called, returns something6. That something replaces content of tag ID in :update

argument

Page 26: UC Berkeley Intro to AJAX

script.aculo.us

• Captures common patterns for visual effects on Web pages– e.g.: “blind down/blind up” to hide/show an element

button_to_function "Extra Contact Info...", visual_effect(:toggle_slide, :contact)

• One strategy: preload all page content, then selectively show

• Another strategy: lazily fetch content using XHRlink_to_remote('Show article',

:url => {:action => 'get_article_text',:id => article},:complete =>   visual_effect(:toggle_slide,'article_content',  :duration=>0.5),404 => alert("Article text not found!"),:failure => alert("Error: "+request.status))

Page 27: UC Berkeley Intro to AJAX

Graceful Fallback to Web 1.0

• What if AJAX support not available in user’s browser?

• Specifying a fallback in the AJAX tags– :html => options– how does view “know” whether to use it or

not?

Page 28: UC Berkeley Intro to AJAX

How to think of cool GUI tasks in terms of AJAX...

• “Auto-completion” of a text field• “Update now” button• Periodically polling for updates

(periodically_call_remote)• Repopulate popup menus constrained to

choices in other menus– One approach: use AJAX call to re-render the

whole <select> item

Page 29: UC Berkeley Intro to AJAX

Remote Javascript (RJS)

• a/k/a “writing JS without writing JS” a/k/a “there is no spoon”

• idea: when rendering response to XHR call, instead of text (HTML), return more JS that will execute at client side and do something.– helper methods provided in Ruby that

generate the necessary JS

Page 30: UC Berkeley Intro to AJAX

Simple RJS example

respond_to do |wants| wants.js do render :update do |page| page['some_div'].hide page['other_div'].replace_html('old','new')

page.alert "Something's wrong" page.call('some_function') endend

• Even better: put the above code in a view template action.js.rjs

Page 31: UC Berkeley Intro to AJAX

The dark side of AJAX, RJS, etc.

• Lots of layers of code; can be hard to debug• Browsers tend to fail silently when they choke on

JS-related errors– View JS console/log in most decent browsers– install Firefox Developer Toolbar & Firebug

• On the plus side...– eminently more maintainable– probably more robust and browser-neutral


Recommended