sneaking structure into                           your DOM-based                              applicationSunday, April 17,...
ohai                     ☛ Garann    Means                     ☛ Vast                     ☛ Austin   All-Girl Hack Night  ...
$(document).ready(function() {                !       $.get("pages/title.html",function(r) {                !       !     ...
you have a problem.                     ☛ old   code                     ☛ other   people’s code                     ☛ wri...
but..                             http://www.flickr.com/photos/vintagechica/5597949576/Sunday, April 17, 2011
your baby is ugly.                                 http://www.flickr.com/photos/quinnanya/2885102816/in/photostream/Sunday,...
your baby is ugly.                     ☛ window.everything                     ☛ data    in HTML                     ☛ all...
wontfix?                     ☛ performance   gets worse                     ☛ hacks   beget hacks                     ☛ un...
rewrite from scratch?                     ☛ undocumented     business logic                     ☛ new   bugs for old bugs ...
code written under                         duress is probably what                              got you hereSunday, April ...
why ‘sneaky’                     ☛ business   people see their features                     ☛ users   see bugs fixed      ...
it’s gonna get dirty                                    http://www.flickr.com/photos/johnpaulgoguen/3359392738/Sunday, Apri...
it’s gonna get ridiculous                                       http://www.flickr.com/photos/mhaithaca/447863503/Sunday, Ap...
where you want to beSunday, April 17, 2011
where you want to be                     ☛ namespacing                     ☛ data    separate from DOM                    ...
(and then you can think                                 about..)                     ☛ MVC                     ☛ AMD      ...
keep it simple                     ☛ one   release at a time                     ☛ stick   to the plan                    ...
let’s get crackingSunday, April 17, 2011
release 0                     ☛ take   stock                     ☛ add   TODOs                     ☛ basic   reuseSunday, ...
TODO     !        // TODO: find something less icky     !        setInterval(function() {     !        ! var currentpage =...
cache/improve selectors       !       newpage = "";       !       parseInt(pagenum) ?       !       ! $("h3 span").text(pa...
cache/improve selectors       !       // r0: saved .page_image selector       !       var $h = $("h3 span"),       !      ...
avoid repetition       $(document).ready(function() {       ! $.get("pages/title.html",function(r) {       ! ! $(".page_te...
avoid repetition       $(document).ready(function() {       !       ! // r0: removed repeated code (+ link wireups)       ...
now you have..                     ☛ tasks   defined                     ☛ reuse                     ☛ abstractionSunday, ...
release 1                     ☛ all   your code under one namespace                     ☛ that’s   it.                    ...
leave window alone       var newpage = "";       // TODO: is this necessary?       var keys = {       ! "37": "left",     ...
leave window alone       // r1: added this namespace       var cyoa = cyoa || {       ! ! newpage: "",       ! ! // TODO: ...
check for inline JS       <a href=”javascript:goToPage(9)”>click here!!1</a>       <script type=”text/javascript”>       i...
check external code       // r1: added this namespace       var cyoa = cyoa || {       ! ! newpage: "",       ! ! ...     ...
now you have..                     ☛ your   stuff is isolated                     ☛ group   pieces of app                 ...
release 2                     ☛ hidden   fields                     ☛ attributes                     ☛ add    new objects ...
val()       // TODO: fewer arguments       cyoa.goToPage = function(pagenum, pagetext, pageimg) {       !       ...       ...
val()       // TODO: fewer arguments       cyoa.goToPage = function(pagenum, pagetext, pageimg) {       !       ...       ...
attr()       <a rel="4">If you decide to refactor, turn to page 4.</a>       $("div.choose a").click(function(e) {       !...
attr()       <a href="#4">If you decide to refactor, turn to page 4.</a>       (or)       // TODO: add to state object    ...
now you have..                     ☛ DOM   data vs. non-DOM data                     ☛ access   data more quickly         ...
release 3                     ☛ isolate   existing plugins                     ☛ formalize   widgets                     ☛...
wrapping plugins       !       !         var imgs = $p.children();       !       !         if (imgs.length) {       !     ...
wrapping plugins       ! ! // r3: removed plugin setup code       ! ! cyoa.setUpZoom($p.children());       ...       cyoa ...
not $.fn.everything                     ☛ known     element type?                     ☛ known     class?                  ...
now you have..                     ☛ easy   plugin swap/upgrade                     ☛ app-specific   stock of widgets     ...
release 4                     ☛ state      objects                         ☛ steps    in arrays                         ☛ ...
confine state info       // TODO: fewer arguments       cyoa.goToPage = function(pagenum, pagetext, pageimg) {       !    ...
confine state info       // r4: added more structured state management       cyoa.state = {       ! init: function() {    ...
confine state info       // TODO: NOT THIS.       cyoa.goToPage0 = function() {       ! cyoa.goToPage(0,"title.html");    ...
confine state info       // r4: created array with page/state info       cyoa.states = [       ! {page: "title.html"},!   ...
now you have..                     ☛ state   differences encapsulated                     ☛ single   place to switch state...
release 5                     ☛ pub/sub     instead of event handlers                     ☛ reduce   anonymous functions  ...
publish/subscribe       !       !         $.get("pages/" + state.page,function(r) {       !       !         ! $("div.page_...
publish/subscribe       !       !         $.get("pages/" + state.page,function(r) {!                                      ...
pub/sub and get/set       cyoa = {       ! ! _currentPage: 0,       ! ! // r5: getter and setter for currentPage       ! !...
now you have..                     ☛ application   events vs. DOM events                     ☛ no   manual callback chains...
release 6                     ☛ upgrade                     ☛ regression   test                     ☛ swap   out non-forwa...
upgrade and test       !       cyoa.event.subscribe("pageLoaded", function(r) {!       !       !       !       ! $("div.pa...
upgrade and test       !       // r6: dont keep binding this every time       !       $("div.page_text")       !       ! ....
when you can’t upgrade                     ☛ bugs   should be easier to find                     ☛ fix   them             ...
but once you do.. !!                     ☛ dependency     management                     ☛ event    delegation            ...
nobody saw a thing                     ☛ business    people: “Oh I thought you finished                         that five ...
you:                     ☛ “:D”                     ☛ can    develop faster                     ☛ can    fix easier       ...
hey, since you did such a                      super job on that                          refactor...Sunday, April 17, 2011
thanks!                     ☛ who’s   got questions?                     ☛ shy   questions:                         ☛ @gar...
Upcoming SlideShare
Loading in...5
×

Sneaking structure into your DOM-based application

13,028

Published on

You thought you were building a proof of concept, but then that proof of concept went live. Or you had two weeks to build what should have taken two months. Or the handful of progressive enhancements you threw onto a page to make the user experience a little nicer somehow evolved into an entire single-page app. Whatever the reason, you find yourself with a full-blown application built around click events and a staggering number of plugins you can't even remember downloading. If you could rewrite it, you'd use a framework built with your scenario in mind, but it gets 17 zillion hits a day and there's only one of you and starting from scratch isn't an option. No, what you need is the philosophy of a framework broken into discrete pieces that fit into a one- or two-week release cycle. This talk aims to provide bite-sized strategies you can implement in a short amount of time with minimal disruption to unchain your application from the DOM.

Demo code on github: https://github.com/garann/cyoa

Published in: Technology
2 Comments
17 Likes
Statistics
Notes
  • welcome to it !!hi gh quali ty☆ reaso nable pric e☆
    free shi pping accept pay pal,
    if you have interest in it , take action !!!!!
    ***** {{w w w }} {{ happyshopping100 }} {{ com }} ***
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Minor typo: on slide 36 .attr(’rel’) is meant to be changed to .attr(’href’)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
13,028
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
79
Comments
2
Likes
17
Embeds 0
No embeds

No notes for slide

Sneaking structure into your DOM-based application

  1. 1. sneaking structure into your DOM-based applicationSunday, April 17, 2011
  2. 2. ohai ☛ Garann Means ☛ Vast ☛ Austin All-Girl Hack Night ☛ @garannm / garann.comSunday, April 17, 2011
  3. 3. $(document).ready(function() { ! $.get("pages/title.html",function(r) { ! ! $(".page_text").html(r); ! }, "html"); ! setInterval(function() { ! ! var currentpage = parseInt($("#currentpage").val()), ! ! ! num = window.location.hash.substring(1) || 0; ! ! if (currentpage != num) { ! ! ! goToPage(num); ! ! } ! }, 100); ! $(".continue a").click(function(e) { ! ! e.preventDefault(); ! ! goToPage(parseInt($("#currentpage").val())+1); ! });! ! $(".choose a").click(function(e) { ! ! e.preventDefault(); ! ! var newpage = $(this).attr("rel"); ! ! goToPage(newpage); ! });! ! $(document).bind("keydown",function(e) {! ! ! ! clearTimeout(typingPause);! ! ! ! var currentpage = parseInt($("#currentpage").val()); ! ! var k = keys[e.keyCode]; ! ! if (k == "left") { ! ! ! currentpage--; ! ! ! goToPage(currentpage); ! ! } else if (k == "right") { ! ! ! currentpage++; ! ! ! goToPage(currentpage); ! ! } else if (k) { ! ! ! newpage += "" + k; ! ! ! typingPause = setTimeout( ! ! ! ! function() { ! ! ! ! ! goToPage(newpage); ! ! ! ! }, 500); ! ! }! ! ! });! ! $(.pan-container).each(function(){ ! ! var $this=$(this).css({position:relative, overflow:hidden, cursor:move}) ! ! var $img=$this.children().eq(0) //image to pan ! ! var options={$pancontainer:$this, pos:$this.attr(data-orient), curzoom:1, canzoom:$this.attr(data-canzoom), wrappersize:[$this.width(), ! ! $img.imgmover(options) ! }) }); var newpage = ""; var typingPause; function goToPage(pagenum, pagetext, pageimg) {! ! $("#currentpage").val(pagenum); ! window.location.hash = pagenum;! ! newpage = ""; ! parseInt(pagenum) ? $("h3 span").text(pagenum) : $("h3 span").text("");! ! ! $.get("pages/" + pagetext,function(r) { ! ! $(".page_text").html(r);! ! ! ! pageimg ? $(".page_image").html(<img src="img/ + pageimg + " />) : $(".page_image").html(""); ! ! if ($(".page_image").children().length) { ! ! ! $(".page_image").children().each(function() { ! ! ! ! $(this).zoomin({ ! ! ! ! ! bgcolor: "#999" ! ! ! ! }); ! ! ! }); ! ! }! ! ! ! $(".continue a").click(function(e) { ! ! ! e.preventDefault(); ! ! ! goToPage(parseInt($("#currentpage").val())+1); ! ! });! ! ! ! $(".choose a").click(function(e) { ! ! ! e.preventDefault(); ! ! ! var newpage = $(this).attr("rel"); ! ! ! goToPage(newpage); ! ! });Sunday, April 17, 2011
  4. 4. you have a problem. ☛ old code ☛ other people’s code ☛ written too fast ☛ scope creepSunday, April 17, 2011
  5. 5. but.. http://www.flickr.com/photos/vintagechica/5597949576/Sunday, April 17, 2011
  6. 6. your baby is ugly. http://www.flickr.com/photos/quinnanya/2885102816/in/photostream/Sunday, April 17, 2011
  7. 7. your baby is ugly. ☛ window.everything ☛ data in HTML ☛ all the plugins ever!! ☛ $(...).click(manageState) ☛ jQuery 1.oldAndBustedSunday, April 17, 2011
  8. 8. wontfix? ☛ performance gets worse ☛ hacks beget hacks ☛ unmaintainable ☛ un-upgradableSunday, April 17, 2011
  9. 9. rewrite from scratch? ☛ undocumented business logic ☛ new bugs for old bugs ☛ business people will freak out ☛ users will be impatient ☛ how long you got?Sunday, April 17, 2011
  10. 10. code written under duress is probably what got you hereSunday, April 17, 2011
  11. 11. why ‘sneaky’ ☛ business people see their features ☛ users see bugs fixed ☛ you see something other than the back of a giant boulderSunday, April 17, 2011
  12. 12. it’s gonna get dirty http://www.flickr.com/photos/johnpaulgoguen/3359392738/Sunday, April 17, 2011
  13. 13. it’s gonna get ridiculous http://www.flickr.com/photos/mhaithaca/447863503/Sunday, April 17, 2011
  14. 14. where you want to beSunday, April 17, 2011
  15. 15. where you want to be ☛ namespacing ☛ data separate from DOM ☛ not dependent on plugins ☛ state management separate from DOM ☛ jQuery 1.newHotnessSunday, April 17, 2011
  16. 16. (and then you can think about..) ☛ MVC ☛ AMD ☛ unit tests ☛ event delegation ☛ deferreds ☛ etc.Sunday, April 17, 2011
  17. 17. keep it simple ☛ one release at a time ☛ stick to the plan ☛ don’t get scaredSunday, April 17, 2011
  18. 18. let’s get crackingSunday, April 17, 2011
  19. 19. release 0 ☛ take stock ☛ add TODOs ☛ basic reuseSunday, April 17, 2011
  20. 20. TODO ! // TODO: find something less icky ! setInterval(function() { ! ! var currentpage = parseInt($("#currentpage").val()), ! ! ! num = window.location.hash.substring(1) || 0; ! ! if (currentpage != num) { ! ! ! goToPage(num); ! ! } ! }, 100); ! ! // TODO: rethink this whole thing ! $(document).bind("keydown",function(e) { ! ! ! ! clearTimeout(typingPause); ! ! ... ! ! var currentpage = parseInt($("#currentpage").val()); ! ! var k = keys[e.keyCode];Sunday, April 17, 2011
  21. 21. cache/improve selectors ! newpage = ""; ! parseInt(pagenum) ? ! ! $("h3 span").text(pagenum) : ! ! $("h3 span").text("");! ! $.get("pages/" + pagetext,function(r) { ! ! $(".page_text").html(r);! ! ! ! pageimg ? ! ! ! $(".page_image").html(<img src="img/ + pageimg + " ! ! ! $(".page_image").html(""); ! ! if ($(".page_image").children().length) { ! ! ! $(".page_image").children().each(function() { ! ! ! ! $(this).zoomin({ ! ! ! ! ! bgcolor: "#999" ! ! ! ! }); ! ! ! }); ! ! } ! ! ...Sunday, April 17, 2011
  22. 22. cache/improve selectors ! // r0: saved .page_image selector ! var $h = $("h3 span"), ! ! $p = $("div.page_image"); ! newpage = ""; ! parseInt(pagenum) ? $h.text(pagenum) : $h.text("");! ! $.get("pages/" + pagetext,function(r) { ! ! $(".page_text").html(r);! ! ! ! pageimg ? ! ! ! $p.html(<img src="img/ + pageimg + " />) : ! ! ! $p.html(""); ! ! var imgs = $p.children(); ! ! if (imgs.length) { ! ! ! $.each(imgs,function() { ! ! ! ! $(this).zoomin({ ! ! ! ! ! bgcolor: "#999" ! ! ! ! }); ! ! ! });Sunday, April 17, 2011
  23. 23. avoid repetition $(document).ready(function() { ! $.get("pages/title.html",function(r) { ! ! $(".page_text").html(r); ! }, "html"); ! ! $(".continue a").click(function(e) { ! ! e.preventDefault(); ! ! goToPage(parseInt($("#currentpage").val())+1); ! }); ! ! $(".choose a").click(function(e) { ! ! e.preventDefault(); ! ! var newpage = $(this).attr("rel"); ! ! goToPage(newpage); ! }); });Sunday, April 17, 2011
  24. 24. avoid repetition $(document).ready(function() { ! ! // r0: removed repeated code (+ link wireups) ! goToPage(0); });Sunday, April 17, 2011
  25. 25. now you have.. ☛ tasks defined ☛ reuse ☛ abstractionSunday, April 17, 2011
  26. 26. release 1 ☛ all your code under one namespace ☛ that’s it. ☛ find, replace, test ☛ memory laneSunday, April 17, 2011
  27. 27. leave window alone var newpage = ""; // TODO: is this necessary? var keys = { ! "37": "left", ! "39": "right" }; var typingPause; // TODO: fewer arguments function goToPage(pagenum, pagetext, pageimg) { ! ...Sunday, April 17, 2011
  28. 28. leave window alone // r1: added this namespace var cyoa = cyoa || { ! ! newpage: "", ! ! // TODO: is this necessary? ! ! keys: { ! ! ! "37": "left", ! ! ! "39": "right" ! ! }, ! ! typingPause: null ! }; // TODO: fewer arguments cyoa.goToPage = function(pagenum, pagetext, pageimg) {Sunday, April 17, 2011
  29. 29. check for inline JS <a href=”javascript:goToPage(9)”>click here!!1</a> <script type=”text/javascript”> if (newpage == “”) document.write(“no new page to load”); </script>Sunday, April 17, 2011
  30. 30. check external code // r1: added this namespace var cyoa = cyoa || { ! ! newpage: "", ! ! ... ! ! typingPause: null ! }; // r1: well it would have been cool, anyway.. var newpage = function() { ! return cyoa.newpage; };Sunday, April 17, 2011
  31. 31. now you have.. ☛ your stuff is isolated ☛ group pieces of app ☛ good overviewSunday, April 17, 2011
  32. 32. release 2 ☛ hidden fields ☛ attributes ☛ add new objects at the right level ☛ stay out of display code.. for nowSunday, April 17, 2011
  33. 33. val() // TODO: fewer arguments cyoa.goToPage = function(pagenum, pagetext, pageimg) { ! ... ! $("#currentpage").val(pagenum); ! window.location.hash = pagenum;Sunday, April 17, 2011
  34. 34. val() // TODO: fewer arguments cyoa.goToPage = function(pagenum, pagetext, pageimg) { ! ... ! cyoa.currentPage = pagenum; ! window.location.hash = pagenum;Sunday, April 17, 2011
  35. 35. attr() <a rel="4">If you decide to refactor, turn to page 4.</a> $("div.choose a").click(function(e) { ! e.preventDefault(); ! var newpage = $(this).attr("rel"); ! cyoa.goToPage(newpage); });Sunday, April 17, 2011
  36. 36. attr() <a href="#4">If you decide to refactor, turn to page 4.</a> (or) // TODO: add to state object $("div.choose a").click(function(e) { ! e.preventDefault(); ! var newpage = $(this).attr("rel"); ! cyoa.goToPage(newpage); });Sunday, April 17, 2011
  37. 37. now you have.. ☛ DOM data vs. non-DOM data ☛ access data more quickly ☛ change HTML without breaking appSunday, April 17, 2011
  38. 38. release 3 ☛ isolate existing plugins ☛ formalize widgets ☛ my.plugin = function($t) or $.fn.pluginSunday, April 17, 2011
  39. 39. wrapping plugins ! ! var imgs = $p.children(); ! ! if (imgs.length) { ! ! ! $.each(imgs,function() { ! ! ! ! $(this).zoomin({ ! ! ! ! ! bgcolor: "#999" ! ! ! ! }); ! ! ! }); ! ! }Sunday, April 17, 2011
  40. 40. wrapping plugins ! ! // r3: removed plugin setup code ! ! cyoa.setUpZoom($p.children()); ... cyoa = { ! ! setUpZoom: function($t) { ! ! ! if ($t.length) { ! ! ! ! $t.each(function() { ! ! ! ! ! cyoa.zoomin($(this), { ! ! ! ! ! ! bgcolor: "#999" ! ! ! ! ! }); ! ! ! ! }); ! ! ! } ! ! } }Sunday, April 17, 2011
  41. 41. not $.fn.everything ☛ known element type? ☛ known class? ☛ known properties? ☛ known length? ☛ that’s a widget, y’allSunday, April 17, 2011
  42. 42. now you have.. ☛ easy plugin swap/upgrade ☛ app-specific stock of widgets ☛ your junk out of $.fn.* ☛ widgets within relevant state in...Sunday, April 17, 2011
  43. 43. release 4 ☛ state objects ☛ steps in arrays ☛ non-linear states: myApp.states[“thisState”] ☛ state functions ☛ init ☛ change state ☛ errorSunday, April 17, 2011
  44. 44. confine state info // TODO: fewer arguments cyoa.goToPage = function(pagenum, pagetext, pageimg) { ! // TODO: put this logic someplace else ! if (!pagetext) { ! ! switch (parseInt(pagenum)) { ! ! ! case 0: ! ! ! ! cyoa.goToPage0(); ! ! ! ! break; ! ! ! case 1: ! ! ! ! cyoa.goToPage1(); ! ! ! ! break; ! ! ! case 2: ! ! ! ! cyoa.goToPage2(); ! ! ! ! break; ! ! ! ...Sunday, April 17, 2011
  45. 45. confine state info // r4: added more structured state management cyoa.state = { ! init: function() { ! ! var num = window.location.hash.substring(1) || 0; ! ! cyoa.state.goToPage(num); ! }, ! ! goToPage: function(pagenum) { ! ! ! ! // r4: check that page is valid ! ! pagenum = parseInt(pagenum); ! ! if (pagenum < 0 || pagenum >= cyoa.states.length) ! ! ! return; ! ! ! ! cyoa.currentPage = pagenum; ! ! window.location.hash = pagenum;Sunday, April 17, 2011
  46. 46. confine state info // TODO: NOT THIS. cyoa.goToPage0 = function() { ! cyoa.goToPage(0,"title.html"); } cyoa.goToPage1 = function() { ! cyoa.goToPage(1,"whatToDo.html"); } cyoa.goToPage2 = function() { ! cyoa.goToPage(2,"youHaveDied.html","explosion.jpg"); } cyoa.goToPage3 = function() { ! cyoa.goToPage(3,"youHaveDied.html","sisyphus.jpg"); } cyoa.goToPage4 = function() { ! cyoa.goToPage(4,"sellIt.html"); }Sunday, April 17, 2011
  47. 47. confine state info // r4: created array with page/state info cyoa.states = [ ! {page: "title.html"},! ! {page: "whatToDo.html"},! ! {page: "youHaveDied.html", image: "explosion.jpg"},! ! {page: "youHaveDied.html", image: "sisyphus.jpg"},! ! {page: "sellIt.html"} ]; // extra credit: routing infoSunday, April 17, 2011
  48. 48. now you have.. ☛ state differences encapsulated ☛ single place to switch state ☛ clear definitions ☛ add states cleanly ☛ add in routing with less riskSunday, April 17, 2011
  49. 49. release 5 ☛ pub/sub instead of event handlers ☛ reduce anonymous functions ☛ event handlers manage $(this) ☛ onreadystatechange publishesSunday, April 17, 2011
  50. 50. publish/subscribe ! ! $.get("pages/" + state.page,function(r) { ! ! ! $("div.page_text").html(r); ! ! ! ! ! ! img ? ! ! ! ! $p.html(<img src="img/ + img + " />) : ! ! ! ! $p.html(""); ! ! ! // r3: removed plugin setup code ! ! ! cyoa.setUpZoom($p.children()); ! ! ! ! ! ! $("div.continue a").click(function(e) { ! ! ! ! e.preventDefault(); ! ! ! ! cyoa.state.goToPage(cyoa.currentPage+1); ! ! ! }); ! ! ! ! ! ! ...! ! ! ! ! ! }, "html");Sunday, April 17, 2011
  51. 51. publish/subscribe ! ! $.get("pages/" + state.page,function(r) {! ! ! ! ! ! cyoa.event.publish("pageLoaded", [r]);! ! ! }, "html"); ... ! cyoa.event.subscribe("pageLoaded", function(r) {! ! ! ! ! $("div.page_text").html(r); ! ! ! ! $("div.continue a").click(function(e) { ! ! ! e.preventDefault(); ! ! ! cyoa.currentPage += 1; ! ! }); ! ! ! ! });Sunday, April 17, 2011
  52. 52. pub/sub and get/set cyoa = { ! ! _currentPage: 0, ! ! // r5: getter and setter for currentPage ! ! get currentPage() { return this._currentPage; }, ! ! set currentPage(n) { ! ! ! if (n < 0 || n >= cyoa.states.length) return; ! ! ! this._currentPage = n; ! ! ! cyoa.event.publish("pageChanged"); ! ! } } ... cyoa.event.subscribe("pageChanged", function(r) {!! ! cyoa.state.goToPage(); });Sunday, April 17, 2011
  53. 53. now you have.. ☛ application events vs. DOM events ☛ no manual callback chains ☛ easily add features that observe events ☛ control state through propertiesSunday, April 17, 2011
  54. 54. release 6 ☛ upgrade ☛ regression test ☛ swap out non-forward-compatible plugins ☛ regression test ☛ maybe roll back (sorries :( )Sunday, April 17, 2011
  55. 55. upgrade and test ! cyoa.event.subscribe("pageLoaded", function(r) {! ! ! ! ! $("div.page_text").html(r); ! ! ! ! $("div.continue a").click(function(e) { ! ! ! e.preventDefault(); ! ! ! cyoa.currentPage += 1; ! ! }); ! ! ! ! });Sunday, April 17, 2011
  56. 56. upgrade and test ! // r6: dont keep binding this every time ! $("div.page_text") ! ! .delegate("div.continue a","click",function(e) { ! ! e.preventDefault(); ! ! cyoa.currentPage += 1; ! });Sunday, April 17, 2011
  57. 57. when you can’t upgrade ☛ bugs should be easier to find ☛ fix them ☛ keep trying ☛ ala carte featuresSunday, April 17, 2011
  58. 58. but once you do.. !! ☛ dependency management ☛ event delegation ☛ deferreds ☛ unit tests ☛ documentation ☛ ..framework? maybe?Sunday, April 17, 2011
  59. 59. nobody saw a thing ☛ business people: “Oh I thought you finished that five releases ago?” ☛ users: less “It’s too slow,” more “Why can’t I make this have polka dots?”Sunday, April 17, 2011
  60. 60. you: ☛ “:D” ☛ can develop faster ☛ can fix easier ☛ can get hit by all the buses you wantSunday, April 17, 2011
  61. 61. hey, since you did such a super job on that refactor...Sunday, April 17, 2011
  62. 62. thanks! ☛ who’s got questions? ☛ shy questions: ☛ @garannm ☛ garann@gmail.comSunday, April 17, 2011
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×