1 / 31

Intro to AJAX Rails allyourcodegmail Ito learn about april 11-12 CSUA hackathon

Review: Partials. Reusable chunk of a viewe.g., one line of a Student tablee.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 in

imelda
Download Presentation

Intro to AJAX Rails allyourcodegmail Ito learn about april 11-12 CSUA hackathon

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


    1. Intro to AJAX & Rails allyourcode@gmail.com Ito learn about april 11-12 CSUA hackathon CS 98-10/CS 198-10 Web 2.0 Programming Using Ruby on Rails Armando Fox

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

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

    4. 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? Document Object Model (c.1998, W3C) represents document as a hierarchy of elements JavaScript (c.1995; now ECMAScript) makes DOM available programmatically, allowing modification of page elements after page loaded XMLHttpRequest (MSIE 5, c.2000; others, c.2002) allows async HTTP transactions decoupled from page reload

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

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

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

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

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

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

    11. XHR (simplified) r=XmlHttpRequest.new r.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

    12. 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'; }"

    13. 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.') %>

    14. 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" />

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

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

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

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

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

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

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

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

    23. 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[]

    24. State changes & visual effects Additional arguments allow specifying callbacks states: server contacted, waiting, receiving, done link_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!"))

    25. 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 JS 3. Browser loads page with all expansions 4. User clicks link, invoking JavaScript function 5. Your app server gets called, returns something 6. That something replaces content of tag ID in :update argument

    26. 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 XHR link_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))

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

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

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

    30. 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') end end Even better: put the above code in a view template action.js.rjs

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

More Related