Directing JavaScript with Arrows Khoo Yit Phang , Michael Hicks, Jeffrey S. Foster, Vibha Sazawal University of Maryland October 26, 2009 1
JavaScript: de-facto language for Web 2.0 • JavaScript increasingly used to write sophisticated, interactive web applications: Productivity Applications Development Environments Games 2
UI programming with JavaScript • JavaScript is single-threaded; event-driven programming only way for interactive apps • E.g., trigger when “click” on HTML element: element. addEventListener ( “click”, function(){alert(“clicked!”)}) • E.g., break-up long-running computation: function longcompute() { /* ... */ setTimeout (longcompute, 0) } 3
Understanding event- driven control flow • Often interested in sequences of events 4
Understanding event- driven control flow • Often interested in sequences of events mousedown start mouseup stop 4
Understanding event- driven control flow • Often interested in sequences of events mousedown start mouseup stop function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; } function stop(event) { A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } A.addEventListener(“mousedown”, start); 4
Understanding event- driven control flow • Often interested in sequences of events mousedown start mouseup stop function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; } function stop(event) { A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } Control flow is indirect, convoluted, A.addEventListener(“mousedown”, start); hard to understand 4
Understanding event- driven control flow • Often interested in sequences of events mousedown start mouseup stop function start(event) { Control flow A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); “plumbing” A.style.background = “yellow”; interspersed } with function stop(event) { “action” A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } Control flow is indirect, convoluted, A.addEventListener(“mousedown”, start); hard to understand 5
Maintaining event-driven programs • Modifications are annoyingly difficult mousedown start mouseup stop function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; } function stop(event) { A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } A.addEventListener(“mousedown”, start); 6
Maintaining event-driven programs • Modifications are annoyingly difficult mousedown start mouseup stop mousemove nudge function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; } function stop(event) { A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } A.addEventListener(“mousedown”, start); 6
Maintaining event-driven programs • Modifications are annoyingly difficult mousedown start mouseup stop mousemove nudge function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.addEventListener(“mousemove”, nudge); A.style.background = “yellow”; } function stop(event) { A.removeEventListener(“mouseup”, stop); A.removeEventListener(“mousemove”, nudge); A.style.background = “white”; } function nudge(event) { /* ... */ } A.addEventListener(“mousedown”, start); 7
Maintaining event-driven programs • Modifications are annoyingly difficult mousedown start mouseup stop mousemove nudge function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.addEventListener(“mousemove”, nudge); A.style.background = “yellow”; Changes strewn } throughout code function stop(event) { A.removeEventListener(“mouseup”, stop); A.removeEventListener(“mousemove”, nudge); A.style.background = “white”; } function nudge(event) { /* ... */ } A.addEventListener(“mousedown”, start); 7
Maintaining event-driven programs • What if you want old and new behavior? mousedown mousedown start1 start mouseup mouseup stop1 stop mousemove nudge function start1(event) { function start(event) { A.removeEventListener(“mousedown”, start); A.removeEventListener(“mousedown”, start1); A.addEventListener(“mouseup”, stop); A.addEventListener(“mouseup”, stop1); A.addEventListener(“mousemove”, nudge); A.style.background = “yellow”; } A.style.background = “yellow”; } function stop(event) { function stop1(event) { A.removeEventListener(“mouseup”, stop); A.removeEventListener(“mouseup”, stop1); A.style.background = “white”; A.removeEventListener(“mousemove”, nudge); } A.style.background = “white”; } A.addEventListener(“mousedown”, start1); function nudge(event) { /* ... */ } A.addEventListener(“mousedown”, start); 8
Maintaining event-driven programs • What if you want old and new behavior? mousedown start mouseup stop mousedown start1 mouseup stop1 mousemove nudge function start1(event) { function start(event) { A.removeEventListener(“mousedown”, start1); A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop1); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; A.addEventListener(“mousemove”, nudge); } A.style.background = “yellow”; } function stop1(event) { function stop(event) { A.removeEventListener(“mouseup”, stop1); A.removeEventListener(“mouseup”, stop); A.style.background = “white”; A.removeEventListener(“mousemove”, nudge); } A.style.background = “white”; } A.addEventListener(“mousedown”, start1); function nudge(event) { /* ... */ } A.addEventListener(“mousedown”, start); 8
Maintaining event-driven programs • What if you want old and new behavior? mousedown start mouseup stop mousedown start1 mouseup stop1 mousemove nudge function start1(event) { function start(event) { A.removeEventListener(“mousedown”, start1); A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop1); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; A.addEventListener(“mousemove”, nudge); } A.style.background = “yellow”; } function stop1(event) { function stop(event) { A.removeEventListener(“mouseup”, stop1); A.removeEventListener(“mouseup”, stop); A.style.background = “white”; A.removeEventListener(“mousemove”, nudge); } A.style.background = “white”; } A.addEventListener(“mousedown”, start1); function nudge(event) { /* ... */ } A.addEventListener(“mousedown”, start); 9
Maintaining event-driven programs • What if you want old and new behavior? mousedown start mouseup stop mousedown start1 mouseup stop1 mousemove nudge function start1(event) { function start(event) { A.removeEventListener(“mousedown”, start1); A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop1); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; A.addEventListener(“mousemove”, nudge); } A.style.background = “yellow”; } function stop1(event) { function stop(event) { A.removeEventListener(“mouseup”, stop1); A.removeEventListener(“mouseup”, stop); A.style.background = “white”; A.removeEventListener(“mousemove”, nudge); } A.style.background = “white”; } A.addEventListener(“mousedown”, start1); function nudge(event) { /* ... */ } A.addEventListener(“mousedown”, start); Need to duplicate the entire code, and remember to rename carefully! 9
Re-using event-driven components • Say, want to maximize re-use (it’s good!) mousedown start mouseup stop function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); A.style.background = “yellow”; } function stop(event) { A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } A.addEventListener(“mousedown”, start); 10
Re-using event-driven components • Say, want to maximize re-use (it’s good!) mousedown start mouseup stop A function start(event) { A.removeEventListener(“mousedown”, start); A.addEventListener(“mouseup”, stop); We can factor A.style.background = “yellow”; } out the target function stop(event) { A.removeEventListener(“mouseup”, stop); A.style.background = “white”; } A.addEventListener(“mousedown”, start); 10
Re-using event-driven components • Say, want to maximize re-use (it’s good!) mousedown start mouseup stop A function foo(x) { function start(event) { x.removeEventListener(“mousedown”, start); x.addEventListener(“mouseup”, stop); Parameterize x.style.background = “yellow”; } using a closure function stop(event) { x.removeEventListener(“mouseup”, stop); x.style.background = “white”; } x.addEventListener(“mousedown”, start); } foo(A); foo(B); 11
Recommend
More recommend