Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.
-
Upload
lionel-porter -
Category
Documents
-
view
219 -
download
3
Transcript of Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.
![Page 1: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/1.jpg)
Events & Callbacks(ESaaS §6.5)
© 2013 Armando Fox & David Patterson, all rights reserved
![Page 2: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/2.jpg)
Events
• What: occurrences that affect the user interface– User interacts with a page element– Previously-set timer expires– Data received from server in response to AJAX
call (later)• Events are usually (not always) associated
with a DOM element• Bind a handler (function) for a particular
event type on one or more elements2
![Page 3: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/3.jpg)
Manipulating the DOM Using Events: Overview
1. Identify element(s) you will want to do stuff to, make sure they’re conveniently selectable using $()
2. Similarly, identify element(s) on which interactions will trigger stuff to happen
3. Write handler function(s) that cause the desired stuff to happen
4. In a setup function, bind the handlers (third way to call $() )
3
2.5. Create failing test for handler using TDD
http://pastebin.com/RSVXzgLR
![Page 4: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/4.jpg)
Handlers on Buttons & Links
• A good summary of recognized handlers:http://www.chipchapin.com/WebTools/JavaScript/example1-04.html
• What about links & buttons that are clickable without JavaScript?– handler runs first– if handler returns false, no other action taken– otherwise, other actions follow handler– example use: client-side form validation
![Page 5: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/5.jpg)
Summary: jQuery & DOM
• Select elements with $() (or wrapto give them secret jQuery powers)
• Inspect them…
text() or html()is(:checked), is(:selected), etc.
attr('src')• Add/remove CSS classes, hide/show• Create setup function that binds handler(s) on
element(s)– common ones: onclick, onsubmit, onchange– Pass func to $() (alias for document.ready())
![Page 6: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/6.jpg)
6
END
![Page 7: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/7.jpg)
Browser will complain, but only when form’s Submit button clicked
The form will be submitted, but without inputs being checked
Nothing will happen when submit button is clicked (form won’t be submitted)
Browser will complain about malformed HTML when page is loaded (server should respect browser version and not send JavaScript)
☐
☐
☐
☐
7
<form onSubmit='checkInputs()'> <input type="text"/> <input type="submit"/></form>If this form is loaded in a non-JS-aware browser:
![Page 8: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/8.jpg)
8
END
![Page 9: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/9.jpg)
AJAX: Asynchronous JavaScript and XML
(ESaaS §6.6)
© 2013 Armando Fox & David Patterson, all rights reserved
![Page 10: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/10.jpg)
AJAX ==Asynchronous Javascript And XML
• JSAPI call XmlHttpRequest (a/k/a xhr) contacts server asynchronously (in background) and without redrawing page – Normal HTTP request, w/special header:X-Requested-With: XmlHttpRequest
• Controller action receives request via route• What should it render in response?
render :layout => falserender :partial => 'movies/show'
render :json => @movies (calls to_json)render :xml => @movies (calls to_xml)render :text => @movie.title render :nothing => true
![Page 11: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/11.jpg)
The Basic AJAX Cycle, As Seen From Browser JSAPI
r = new XmlHttpRequest;r.open(method,URL,async);
method GET,POST,HEAD,PUT,DELETE...async: true means script should not block (important!)
r.send("request content");r.abort();
• Callbacks during XHR processingr.onReadyStateChange=function(XmlHttpRequest r) { ... }
– function inspects r.readyState uninitialized,open, sent,receiving,loaded
• r.status contains HTTP status of response• r.responseText contains response content string
![Page 12: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/12.jpg)
The jQuery Way
$.ajax({type: 'GET', url: URL, timeout: milliseconds, success: function, error: function
// many other options possible });
![Page 13: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/13.jpg)
Rails Cookery:AJAX with Rails+jQuery
• javascript_include_tag 'application'• your code in app/assets/javascripts/*.js• Define handler function that...
– optionally inspects element state, attributes, …– calls $.ajax()
• Define controller action & route to receive request, and determine what will be returned
• Define callback function to receive server reply– Unpack JSON objects & modify DOM?– Replace existing HTML element (e.g. <div>) in place?– Add/change/remove CSS classes/properties?
![Page 14: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/14.jpg)
A Simple Example
Server side:
class MoviesController < ApplicationController def show @movie = Movie.find(params[:id]) render :partial=>'movie', :object=>@movie if request.xhr? # else render default (show.html.haml) endend
Client side:14
http://pastebin.com/zZPKvmVW
![Page 15: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/15.jpg)
15
END
![Page 16: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/16.jpg)
In general, the server must rely on explicit hints (like headers) to detect XHRThe response to an AJAX request can be any content type (not just HMTL)If the server fails to respond to an XHR request, the browser’s UI will freeze
AJAX requests can be handled with their own separate controller actions
☐
☐
☐
☐
16
Which is FALSE concerning AJAX/XHR vs. non-AJAX interactions?
![Page 17: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/17.jpg)
17
END
![Page 18: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/18.jpg)
Intro to Jasmine: TDD for JavaScript and AJAX
(ESaaS §6.7)
© 2013 Armando Fox & David Patterson, all rights reserved
![Page 19: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/19.jpg)
Jasmine: Testing JavaScript
• Idea: run your tests in browser– Install jasmine gem & jasmine-jquery add-on– rails generate jasmine:install
• Jasmine “server” (rake jasmine) on localhost:8888 serves Jasmine test “page”– Reload page == rerun tests!
• How to construct tests?• How do tests “see” the page on which they
would normally operate?
19
![Page 20: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/20.jpg)
Jasmine is Like RSpec
• Sets of related examplesdescribe "things" do it "..." do...endend describe("things", function() { it("...", function() { ... } );});
• Setup/teardownbefore(:each) do...end beforeEach(function() {...})
20
![Page 21: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/21.jpg)
Expectations
expect {...}.to == "foo" expect(expr).toEqual("foo") .toBeTruthy(),.toBeFalsy() .toBeHidden() .toHaveClass() .toContainText()
21
![Page 22: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/22.jpg)
Expectations: Jasmine-jQuery
toBeSelected(), toBeChecked()toBeDisabled(), toBeVisible(), toBeHidden()toHaveClass("foo"), toHaveId("foo") toHaveAttr("href", "http://saasbook.info")
• Putting it together example:describe('Clicking Hide button', function() { it('hides Movie div', function() { $('a#hide').trigger('click'); expect($('div#movie')).toBeHidden(); });});
22
![Page 23: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/23.jpg)
23
END
![Page 24: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/24.jpg)
(a) & (c)
(b) & (c)
(a), (b) & (c)
(a) & (b)☐
☐
☐
☐
24
Which are always true of Jasmine’s it() method:(a) it can take a named function as its 2nd arg(b) it can take an anonymous function as its 2nd arg(c) it executes asynchronously
![Page 25: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/25.jpg)
25
END
![Page 26: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/26.jpg)
More Jasmine:Spies & Fixtures
(ESaaS §6.7)
© 2013 Armando Fox & David Patterson, all rights reserved
![Page 27: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/27.jpg)
Stubs (Spies)
• Strategy: create “spy” method that replaces real method that is a property of an object
spyOn(MoviePopup,'new').andReturn(value) .andCallThrough() .andCallFake(func)
– Why no quotes around MoviePopup?
• Examine calls on spy:expect(MoviePopup.new.mostRecentCall.args). toContain("Gravity")
expect($.ajax.mostRecentCall.args[0]['url']). toEqual("/movies/1")
27
![Page 28: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/28.jpg)
HTML Fixtures
• Goal: provide enough HTML for JS code to do its thing in a familiar environment<table id="movies"> <tbody> <tr class="adult"> <td>Casablanca</td> <td>PG</td> <td><a href="/movies/1">More about Casablanca</a></td> </tr> </tbody></table>
• loadFixtures('movie_row.html') loads this into div#jasmine-fixtures (automatically cleaned out)
• Fallacies & Pitfalls for §6.7 shows how to auto-generate these fixtures from real views
28
![Page 29: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/29.jpg)
Stubbing Redux
29
![Page 30: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/30.jpg)
Putting it all together example
• Example
• Jasmine tests• (why no call to MoviePopup.setup?)
30
http://pastebin.com/9xRk1CW1
http://pastebin.com/QNAuLLAt
![Page 31: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/31.jpg)
31
END
![Page 32: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/32.jpg)
$.ajax doesn't actually return the server reply content, so andReturn won't workajaxArgs is in the wrong scope, so its value is not "visible" to andReturnWe needed to be able to spy on (monitor) the AJAX call
We could have done it either way; just a matter of choice
☐
☐
☐
☐
32
In the example, why did we use andCallFake() to pass ajaxArgs in stubbing the AJAX call, rather than just andReturn(ajaxArgs) ?
![Page 33: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/33.jpg)
33
END
![Page 34: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/34.jpg)
Single-Page Apps and JSON APIs
(ESaaS §6.8)
© 2013 Armando Fox & David Patterson, all rights reserved
![Page 35: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/35.jpg)
Single-Page Apps
• Load page once; no further page reloads, since everything else done via AJAX
• Uses same MVC flows we already know!– but rendered content from server is handed to
your JS code, not to browser• So, what should controller method render?
– Certainly not a full HTML page– HTML snippet? incorporate into page– “Raw” text? hard to send structured data– XML or JSON!
35
![Page 36: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/36.jpg)
A Simple Example
Server side:
class MoviesController < ApplicationController def show @movie = Movie.find(params[:id]) render :json => @movie if request.xhr? # else render default (show.html.haml) endend
Client side:
36
http://pastebin.com/QNAuLLAt
![Page 37: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/37.jpg)
37
END
![Page 38: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/38.jpg)
In an association such as Movie has-many Reviews, the owned objects must be returned in 1 or more separate JSON objects
JSON objects can only be consumed by a JavaScript-capable clientNone of the above are true
A JSON object’s properties must exactly match the corresponding ActiveRecord model
☐
☐
☐
☐
38
Which, if any, of the following statements are TRUE regarding JSON objects in Rails apps?
![Page 39: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/39.jpg)
39
END
![Page 40: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/40.jpg)
And In Conclusion:JavaScript Wrapup
(ESaaS §6.9-6.11)
© 2012 Armando Fox & David PattersonLicensed under
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
![Page 41: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/41.jpg)
Emerging JS Use Cases
• Server-side frameworks: Node.js– JS library for creating server-side apps– Uses event-driven programming in JS– Potentially much more memory-efficient per user
compared to traditional server-side frameworks– LinkedIn – Node.js 20x faster than Rails
• Client-side frameworks: Backbone.js– Express views & models entirely in JS– Server just returns JSON
• Client-side frameworks: Yahoo Mojito• CoffeeScript
http://pastebin.com/JJ9rEBDz
![Page 42: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/42.jpg)
JavaScript & Performance
• The browser is increasingly the “client-side OS” that matters
• CSS has made layout increasingly sophisticated
• JavaScript + AJAX has made UI increasingly rich & desktop-like
• What’s the cost of all this?
![Page 43: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/43.jpg)
Where Does the Time Go?
• CSS selectors + JavaScript interpreter = 41% of total client rendering time– Esp. selectors that require walking
DOM tree, e.g. div > li
• Browsers compete on speed of JavaScript interpreter => selector/parser performance increasingly important
• Use GPU for rendering
parserDOM CSS rules
rendering
21%
23%
12%
29%
9%
JavaScript interpreter
layout engine
HTML parser
selector engine
rendering
JavaScript interpreter
Courtesy Leo Meyerovich, UC Berkeley
![Page 44: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/44.jpg)
Pitfall: “Adding JavaScript will make my app more responsive”
• Risk: too-wide API to server, with needlessly expensive database calls
• Risk: at mercy of JS interpreter on a wide variety of devices
• Risk: testing/debugging is more complicated, since must handle client-side errors
![Page 45: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/45.jpg)
45
END
![Page 46: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/46.jpg)
Slow database queries associated with AJAX actionsNetwork delays due to sending too much data to browser in AJAX responsesCan’t tell without further information
Slow JavaScript interpreter (for example, users with very old browsers/computers)
☐
☐
☐
☐
46
Some of the AJAX interactions in Ben Bitdiddle’s AJAX-intensive SaaS app “feel sluggish”. The likeliest cause is:
![Page 47: Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved.](https://reader033.fdocuments.in/reader033/viewer/2022051516/56649e205503460f94b0bed7/html5/thumbnails/47.jpg)
47
END