Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating...

35
Events & Callbacks (ESaaS §6.5) © 2013 Armando Fox & David Patterson, all rights reserved

Transcript of Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating...

Page 1: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Events & Callbacks(ESaaS §6.5)!

© 2013 Armando Fox & David Patterson, all rights reserved

Page 2: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 elements"2"

Page 3: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Summary: jQuery & DOM"•  Select elements with $() (or wrap

to 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 & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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)

6"

<form onSubmit='checkInputs()'> <input type="text"/> <input type="submit"/> </form> If this form is loaded in a non-JS-aware browser: "

Page 7: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

AJAX: Asynchronous JavaScript and XML

(ESaaS §6.6)!

© 2013 Armando Fox & David Patterson, all rights reserved

Page 8: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 => false render :partial => 'movies/show'"render :json => @movies (calls to_json)"render :xml => @movies (calls to_xml)"render :text => @movie.title "render :nothing => true "

Page 9: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 processing"r.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 10: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

The jQuery way"$.ajax({type: 'GET',

url: URL, timeout: milliseconds, success: function, error: function! // many other options possible

});

Page 11: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 12: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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) end end

Client side:"12"

http://pastebin.com/zZPKvmVW

Page 13: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

In general, the server must rely on explicit hint (like headers) to detect XHR The 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

13"

Which is FALSE concerning AJAX/XHR vs. non-AJAX interactions?

Page 14: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Intro to Jasmine: TDD for JavaScript and AJAX

(ESaaS §6.7)!

© 2013 Armando Fox & David Patterson, all rights reserved

Page 15: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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?!15"

Page 16: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Jasmine is Like RSpec"

•  Sets of related examples"describe "things" do it "..." do...end end describe("things", function() { it("...", function() { ... } ); });

•  Setup/teardown"before(:each) do...end beforeEach(function() {...})"

16"

Page 17: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Expectations"expect {...}.to == "foo" expect(expr).toEqual("foo") .toBeTruthy(),.toBeFalsy()

.toBeHidden()

.toHaveClass()

.toContainText()

17"

Page 18: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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(); });

});

18"

Page 19: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

(a) & (c)

(b) & (c)

(a), (b) & (c)

(a) & (b) ☐

19"

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 20: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

More Jasmine:Spies & Fixtures

(ESaaS §6.7)!

© 2013 Armando Fox & David Patterson, all rights reserved

Page 21: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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")

21"

Page 22: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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"

22"

Page 23: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Stubbing Redux"

23"

Page 24: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Putting it all together example"

•  Example"

•  Jasmine tests"•  (why no call to MoviePopup.setup?)"

24"

http://pastebin.com/9xRk1CW1

http://pastebin.com/QNAuLLAt

Page 25: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

$.ajax doesn't actually return the server reply content, so andReturn won't work ajaxArgs is in the wrong scope, so its value is not "visible" to andReturn We needed to be able to spy on (monitor) the AJAX call

We could have done it either way; just a matter of choice

25"

In the example, why did we use andCallFake() to pass ajaxArgs in stubbing the AJAX call, rather than just andReturn(ajaxArgs) ?"

Page 26: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Single-page Apps and JSON APIs

(ESaaS §6.8)!

© 2013 Armando Fox & David Patterson, all rights reserved

Page 27: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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!"

27"

Page 28: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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) end end

Client side:"

28"

http://pastebin.com/QNAuLLAt

Page 29: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

In an association such as Movie has-many Reviews, the owned objects must be returned in 1 or more separate JSON object JSON objects can only be consumed by a JavaScript-capable client

None of the above are true

A JSON object’s properties must exactly match the corresponding ActiveRecord model

29"

Which, if any, of the following statements are TRUE regarding JSON objects in Rails apps?!

Page 30: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

And In Conclusion:JavaScript Wrapup

(ESaaS §6.9-6.11)!

© 2012 Armando Fox & David Patterson Licensed under

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License

Page 31: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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"•  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 32: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 33: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Where does the time go?"•  CSS selectors + JavaScript

interpreter = 41% of total client rendering time"–  Esp. selectors that require walking

DOM tree, eg div > li •  Browsers compete on speed of

JavaScript interpreter => selector/parser performance increasingly important"

•  Work at UC Berkeley (Prof. Ras Bodík’s group):"–  Parallelizing parsing & CSS

selectors"–  Increasing use of GPU for rendering"

parser"DOM CSS rules

selector engine"

rendering"

21%"

23%"

12%"

29%"

9%"

JavaScript interpreter"

layout engine"

HTML parser"

selector engine"

rendering"

JavaScript interpreter

Courtesy Leo Meyerovich, UC Berkeley

Page 34: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

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 35: Events & CallbacksJan 09, 2014  · • Server-side frameworks: Node.js" – JS library for creating server-side apps" – Uses event-driven programming in JS" – Potentially much

Slow database queries associated with AJAX actions Network delays due to sending too much data to browser in AJAX responses Can’t tell without further information

Slow JavaScript interpreter (for example, users with very old browsers/computers)

35"

Some of the AJAX interactions in Ben Bitdiddle’s AJAX-intensive SaaS app “feel sluggish”. The likeliest cause is:!