Upgrade to Pro — share decks privately, control downloads, hide ads and more …

It's not you, it's me - FFWD.PRO

It's not you, it's me - FFWD.PRO

General purpose Javascript frameworks are the ones that made the language popular in the past, but right now it is a risk to think about our application development and architecture just in relation to our favorite framework.

This talk highlights risks and suggest some techniques (from design patterns to snippets of code) to avoid being coupled to a specific framework.

3ca63d4e2f2be0ef47b841e63b564d18?s=128

Marco Cedaro

June 11, 2012
Tweet

Transcript

  1. “It’s not you, It’s me”

  2. How to avoid being coupled with a Javascript framework.

  3. Even if you loved it. Even if it was the

    right one.
  4. Hello, who’s speaking? Marco Cedaro @cedmax

  5. About me... Frontend Cowboy Nicola Vitto Jr. Hello, who’s speaking?

    Marco Cedaro @cedmax
  6. About me... Frontend Cowboy Nicola Vitto Jr. Javascript Pervert Roberto

    Felter Hello, who’s speaking? Marco Cedaro @cedmax
  7. About me... Frontend Cowboy Nicola Vitto Jr. Javascript Pervert Roberto

    Felter Marco.. who? basically anyone else Hello, who’s speaking? Marco Cedaro @cedmax
  8. Actually I am: a Frontend Developer at Spreaker.com Hello, who’s

    speaking? Marco Cedaro @cedmax
  9. Actually I am: a Frontend Developer at Spreaker.com Conference organizer

    with From The Front Hello, who’s speaking? Marco Cedaro @cedmax
  10. Actually I am: a Frontend Developer at Spreaker.com Conference organizer

    with From The Front and a javascript pervert Hello, who’s speaking? Marco Cedaro @cedmax
  11. http://welovestyles.com/love-pictures/

  12. http://welovestyles.com/love-pictures/ http://everyoneneedsanalgonquin.com/2012/03/25/fruit-season/

  13. General Purpose Frameworks http://geekadelphia.com/2008/05/01/sick-ink-brah-alex-hillmans-geeky-love-hate-tattoos/

  14. LOVE FACT #1 Love is a given, hatred is acquired.

    Doug Horton
  15. Definition frame·work n. A structure for supporting or enclosing something

    else, especially a skeletal support used as the basis for something being constructed. gen·er·al-pur·pose adj. Designed for or suitable to more than one use; broadly useful.
  16. A little history http://mattstone.blogs.com/photos/christian_art_genesis/adam-eve-and-the-tree.html

  17. Once upon a time code snippet “dhtml” if (document.all) http://creativecriminals.com/print/scotch-tape-beyond-strong/

  18. Then

  19. Then

  20. Then

  21. Then

  22. Then

  23. Now

  24. Why did they get so popular? DOM access Cross browser

    implementation Shorthands Community support
  25. Drawbacks

  26. 1. Community Support

  27. Let’s Fight http://www.rustybrick.com/prototype-js-vs-jquery-comparison.html -http://www.fotolog.com/alinolandia/36818888/

  28. http://www.rustybrick.com/prototype-js-vs-jquery-comparison.html -http://www.fotolog.com/alinolandia/36818888/ Where’s your community now?

  29. 2. Updating is a mess

  30. Long life cycle websites General purpose framework may seem the

    right solution to handle complexity http://sproutsocial.com/insights/2011/11/how-to-iphone-ipad-friendly/ - http://pressganger.blogspot.it/2012/03/blog-progress-update.html - http://news.brothersoft.com/internet-explorer-10-focuses-html5-improves-performance-16036.html
  31. Long life cycle websites General purpose framework may seem the

    right solution to handle complexity New browser, new framework version http://sproutsocial.com/insights/2011/11/how-to-iphone-ipad-friendly/ - http://pressganger.blogspot.it/2012/03/blog-progress-update.html - http://news.brothersoft.com/internet-explorer-10-focuses-html5-improves-performance-16036.html
  32. Long life cycle websites General purpose framework may seem the

    right solution to handle complexity New browser, new framework version How many patches did you make in your framework over years? http://sproutsocial.com/insights/2011/11/how-to-iphone-ipad-friendly/ - http://pressganger.blogspot.it/2012/03/blog-progress-update.html - http://news.brothersoft.com/internet-explorer-10-focuses-html5-improves-performance-16036.html
  33. Short life cycle websites Counterintuitively situation is even worse http://www.cnbc.com/id/46994692/The_Worst_Jobs_for_2012

    - http://indiatransportportal.com/india-transport-studies/
  34. Short life cycle websites Counterintuitively situation is even worse Less

    analysis and foresight http://www.cnbc.com/id/46994692/The_Worst_Jobs_for_2012 - http://indiatransportportal.com/india-transport-studies/
  35. Short life cycle websites Counterintuitively situation is even worse Less

    analysis and foresight Did you make any patch in your framework over years? http://www.cnbc.com/id/46994692/The_Worst_Jobs_for_2012 - http://indiatransportportal.com/india-transport-studies/
  36. Our job is evolving

  37. It's the browser, baby

  38. It's the browser, baby

  39. Some frameworks are just not built for maintainability

  40. Some frameworks are just not built for simplicity

  41. Some frameworks are just not built for love

  42. 3. Code Portability

  43. case study Own scripts built on a known framework http://www.naba.it/newsletter_09_10/naba_n184.html

    - http://sevenspark.com/product/agility-responsive-minimal-html5-template/ - http://middleclasshell.com/republicans-ignore-catholics-when-it-comes-to-unemployment-benefits
  44. case study Own scripts built on a known framework Brand

    new website with responsive design http://www.naba.it/newsletter_09_10/naba_n184.html - http://sevenspark.com/product/agility-responsive-minimal-html5-template/ - http://middleclasshell.com/republicans-ignore-catholics-when-it-comes-to-unemployment-benefits
  45. case study Own scripts built on a known framework Brand

    new website with responsive design same old bloat code over 3g? http://www.naba.it/newsletter_09_10/naba_n184.html - http://sevenspark.com/product/agility-responsive-minimal-html5-template/ - http://middleclasshell.com/republicans-ignore-catholics-when-it-comes-to-unemployment-benefits
  46. $LAB .script("jquery.js").wait() .script("scripts.js"); $LAB .script("xui.js").wait() .script("scripts.js"); Desktop Mobile

  47. $LAB .script("jquery.js").wait() .script("scripts.js"); $LAB .script("xui.js").wait() .script("scripts.js"); Desktop Mobile

  48. It's the browser, baby

  49. and the devices http://www.newfangled.com/mobile_technology_and_web_enhanced_devices

  50. and the devices http://www.newfangled.com/mobile_technology_and_web_enhanced_devices

  51. We need our code to be PORTABLE

  52. We need our code to be PORTABLE but how?

  53. DISCLAIMER http://www.destructoid.com/disappointment-a-postmortem-of-l-a-noire-224486.phtml

  54. Go Vanilla http://s394.photobucket.com/albums/pp28/cojohn55/?action=view&current=tasty-thursday-187-lets-get-naked.gif&mediafilter=images

  55. LOVE FACT #2 What is known as a French Kiss

    in the English speaking world is called an English Kiss in France.
  56. Loops

  57. _.each(items, function(item, i) { [...] }); Ext.each(items, function(item, i) {

    [...] }); $.each(items, function(i, item) { [...] }); items.each(function(item, i) { [...] });
  58. _.each(items, function(item, i) { [...] }); Ext.each(items, function(item, i) {

    [...] }); $.each(items, function(i, item) { [...] }); items.each(function(item, i) { [...] });
  59. _.each(items, function(item, i) { [...] }); Ext.each(items, function(item, i) {

    [...] }); $.each(items, function(i, item) { [...] }); items.each(function(item, i) { [...] });
  60. _.each(items, function(item, i) { [...] }); Ext.each(items, function(item, i) {

    [...] }); $.each(items, function(i, item) { [...] }); items.each(function(item, i) { [...] });
  61. $.each(items, function(i, item) { [...] });

  62. for (var i = 0; i < items.length; i++) {

    [...] }; $.each(items, function(i, item) { [...] });
  63. for (var i = 0; i < items.length; i++) {

    [...] }; $.each(items, function(i, item) { [...] });
  64. operations per second (higher is better)

  65. yes, but... http://www.funnyjunk.com/funny_pictures/3454040/Guess+what/

  66. you should http://www.behaviorgap.com/sketch/things-you-can-control/

  67. operations per second (higher is better)

  68. operations per second (higher is better)

  69. for (var i = 0; i < items.length; i++) {

    [...] };
  70. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] };
  71. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] };
  72. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] };
  73. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] }; for (var i = -1, item;item = items[++i];) { [...] };
  74. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] }; for (var i = -1, item;item = items[++i];) { [...] };
  75. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] }; for (var i = -1, item;item = items[++i];) { [...] };
  76. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] }; for (var i = -1, item;item = items[++i];) { [...] }; var i = 0; while (i < items.length) { [...] i++; };
  77. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] }; for (var i = -1, item;item = items[++i];) { [...] }; var i = 0; while (i < items.length) { [...] i++; };
  78. for (var i = -1; ++i < items.length;) { [...]

    }; for (var i = 0; i < items.length; i++) { [...] }; for (var i = -1, item;item = items[++i];) { [...] }; var i = 0; while (i < items.length) { [...] i++; }; //and counting -> http://jsperf.com/loops/33
  79. items.forEach(function(item, i) { [...] });

  80. items.forEach(function(item, i) { [...] });

  81. Vanilla loop PROS Lots of flavors Performance benefits CONS mmm...

  82. wait, what? too many characters?? http://screenrant.com/game-thrones-episode-7-recap-spoilers-benm-117660/

  83. Zip It! http://screenrant.com/austin-powers-4-2-ross-50006/

  84. ...and minify http://www.destentor.nl/algemeen/show/3347136/Minime-sleept-site-voor-rechter-om-sexvideo.ece

  85. Yeah, baby, yeah http://www.destentor.nl/algemeen/show/3347136/Minime-sleept-site-voor-rechter-om-sexvideo.ece

  86. Context Binding

  87. var conf = { name: "jsDay", clicked: function(event) { alert(this.name);

    } } myElm.onclick = conf.clicked;
  88. var conf = { name: "jsDay", clicked: function(event) { alert(this.name);

    } } myElm.onclick = conf.clicked;
  89. var conf = { name: "jsDay", clicked: function(event) { alert(this.name);

    } } myElm.onclick = conf.clicked;
  90. var conf = { name: "jsDay", clicked: function(event) { alert(this.name);

    } } myElm.onclick = conf.clicked;
  91. var conf = { name: "jsDay", clicked: function(event) { alert(this.name);

    } } myElm.onclick = conf.clicked;
  92. conf.clicked.bind(conf) conf.clicked.createDelegate(conf); $.proxy(conf.clicked, conf); conf.clicked.bind(conf)

  93. conf.clicked.bind(conf) conf.clicked.createDelegate(conf); $.proxy(conf.clicked, conf); conf.clicked.bind(conf)

  94. conf.clicked.bind(conf) conf.clicked.createDelegate(conf); $.proxy(conf.clicked, conf); conf.clicked.bind(conf)

  95. myElm.onclick = (function(context){ return function(){ conf.clicked.apply(context, arguments); } })(conf);

  96. myElm.onclick = (function(context){ return function(){ conf.clicked.apply(context, arguments); } })(conf);

  97. myElm.onclick = (function(context){ return function(){ conf.clicked.apply(context, arguments); } })(conf);

  98. myElm.onclick = (function(context){ return function(){ conf.clicked.apply(context, arguments); } })(conf);

  99. myElm.onclick = (function(context){ return function(){ conf.clicked.apply(context, arguments); } })(conf);

  100. myElm.onclick = (function(context){ return function(){ conf.clicked.apply(context, arguments); } })(conf);

  101. argh, my eyes are bleeding.. http://www.accessexcellence.org/AE/mspot/tbs/episode3a/ep3a06.php

  102. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; }
  103. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; }
  104. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; }
  105. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; }
  106. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; }
  107. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; } myElm.onclick = MyNS.bind(conf.clicked, conf);
  108. MyNS.bind = function(func, context) { return function() { func.apply(context, arguments);

    }; } myElm.onclick = $.proxy(conf.clicked, conf); myElm.onclick = MyNS.bind(conf.clicked, conf);
  109. AAAARGGGHHH http://digitivity.org/1044/rss-kill-your-productivity-make-you-insane-waste-time

  110. MyNS.bind = function(func, context) { } myElm.onclick = MyNS.bind(conf.clicked, conf);

    return function() { return func.apply(context, arguments); };
  111. MyNS.bind = function(func, context) { } myElm.onclick = MyNS.bind(conf.clicked, conf);

    $.proxy(func, context);
  112. Design Patterns http://failblog.org/vote

  113. Wrapper Pattern

  114. MyNS.bind = function(func, context) { } myElm.onclick = MyNS.bind(conf.clicked, conf);

    $.proxy(func, context);
  115. MyNS.bind = function(func, context) { } myElm.onclick = MyNS.bind(conf.clicked, conf);

    $.proxy(func, context);
  116. MyNS.bind = function(func, context) { } myElm.onclick = MyNS.bind(conf.clicked, conf);

    $.proxy(func, context);
  117. http://www.pinkblog.it/post/8396/comprare-i-preservativi-vi-imbarazza Wrapper Pattern

  118. http://clericalwhispers.blogspot.it/2010/09/popes-anti-condom-message-is-sabotage.html sorry I should have said “NSFW” and, moreover...

  119. http://clericalwhispers.blogspot.it/2010/09/popes-anti-condom-message-is-sabotage.html sorry I should have said “NSFW” and, moreover...

  120. var AwesomeEffect = function(id, config){ var default = { delay:

    0, duration: 500, transition: "easeOut", }; [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); //{delay: 1000, duration:100, transition: "easeOut"};
  121. var AwesomeEffect = function(id, config){ var default = { delay:

    0, duration: 500, transition: "easeOut", }; [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); //{delay: 1000, duration:100, transition: "easeOut"};
  122. var AwesomeEffect = function(id, config){ var default = { delay:

    0, duration: 500, transition: "easeOut", }; [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); //{delay: 1000, duration:100, transition: "easeOut"};
  123. var AwesomeEffect = function(id, config){ var default = { delay:

    0, duration: 500, transition: "easeOut", }; [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); //{delay: 1000, duration:100, transition: "easeOut"};
  124. var AwesomeEffect = function(id, config){ var default = { delay:

    0, duration: 500, transition: "easeOut", }; [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); //{delay: 1000, duration:100, transition: "easeOut"};
  125. var AwesomeEffect = function(id, config){ var default = { delay:

    0, duration: 500, transition: "easeOut", }; [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); //{delay: 1000, duration:100, transition: "easeOut"};
  126. _.extend(default, config); Ext.apply(default, config); $.extend(default, config); Object.extend(default, config);

  127. _.extend(default, config); Ext.apply(default, config); $.extend(default, config); Object.extend(default, config);

  128. _.extend(default, config); Ext.apply(default, config); $.extend(default, config); Object.extend(default, config);

  129. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } $.extend(default, config);
  130. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } $.extend(default, config);
  131. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } Ext.apply(default, config);
  132. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } _.extend(default, config);
  133. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } Object.extend(default, config);
  134. Wasn’t it bad to delegate? http://clericalwhispers.blogspot.it/2010/09/popes-anti-condom-message-is-sabotage.html

  135. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); $.extend(default, config);
  136. MyNS.extend = function(destination, source) { return } var AwesomeEffect =

    function(id, config){ var default = { delay: 0, duration: 500, transition: "easeOut", }; var options = MyNS.extend(default, config); [...] } var myEff = new AwesomeEffect("myId", { duration: 100, delay: 1000 }); $.extend(default, config);
  137. Deeply into it

  138. MyNS.Layer = function(content, config){ config = MyNS.extend({ overlayOpacity:0.6, imageLoading: "/img/warn.gif",

    }, config); new LightBox(content, config); } MyNS.Layer("Sorry, an error occured");
  139. MyNS.Layer = function(content, config){ config = MyNS.extend({ overlayOpacity:0.6, imageLoading: "/img/warn.gif",

    }, config); new LightBox(content, config); } MyNS.Layer("Sorry, an error occured");
  140. MyNS.Layer = function(content, config){ config = MyNS.extend({ overlayOpacity:0.6, imageLoading: "/img/warn.gif",

    }, config); new LightBox(content, config); } MyNS.Layer("Sorry, an error occured");
  141. MyNS.Layer = function(content, config){ config = MyNS.extend({ overlayOpacity:0.6, imageLoading: "/img/warn.gif",

    }, config); new LightBox(content, config); } MyNS.Layer("Sorry, an error occured");
  142. MyNS.Layer = function(content, config){ config = MyNS.extend({ overlayOpacity:0.6, imageLoading: "/img/warn.gif",

    }, config); new LightBox(content, config); } MyNS.Layer("Sorry, an error occured");
  143. MyNS.Layer = function(content, config){ config = MyNS.extend({ opacity: true, modal:

    true, }, config); new FancyBox(content, config); } MyNS.Layer("Sorry, an error occured");
  144. MyNS.Layer = function(content, config){ config = MyNS.extend({ opacity: true, modal:

    true, }, config); new FancyBox(content, config); } MyNS.Layer("Sorry, an error occured");
  145. MyNS.Layer = function(content, config){ config = MyNS.extend({ opacity: true, modal:

    true, }, config); new FancyBox(content, config); } MyNS.Layer("Sorry, an error occured");
  146. MyNS.Layer = function(content, config){ config = MyNS.extend({ opacity: true, modal:

    true, }, config); new FancyBox(content, config); } MyNS.Layer("Sorry, an error occured");
  147. MyNS.Layer = function(content, config){ config = MyNS.extend({ opacity: true, modal:

    true, }, config); new FancyBox(content, config); } MyNS.Layer("Sorry, an error occured");
  148. Event Driven Design

  149. MyNS.Layer = function(content, config){ [...] } MyNS.Layer("Sorry, an error occured");

  150. MyNS.Layer("Sorry, an error occured");

  151. MyNS.notify("error", { msg: "Sorry, an error occured" });

  152. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  153. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  154. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  155. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  156. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  157. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  158. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  159. MyNS.notify("error", { msg: "Sorry, an error occured" }); MyNS.listen("error", function(payload){

    MyNS.Layer(payload.msg); });
  160. MyNS.listen("error", function(payload){ MyNS.Layer(payload.msg); }); Advantages

  161. MyNS.listen("error", function(payload){ MyNS.Layer(payload.msg); }); Advantages Semantic

  162. MyNS.listen("error", function(payload){ MyNS.Layer(payload.msg); }); Advantages Semantic More Flexible

  163. Advantages Unpluggable

  164. almost decoupled http://thewellversed.com/2010/12/09/love-warranties-they-dont-make-them-like-they-used-to/broken-heart/

  165. What about ... ?

  166. a real world example

  167. DISCLAIMER #2 http://www.noncipossocredere.com/2012/04/26/lo-spam-arriva-soprattutto-dallindia/

  168. From The Front

  169. Not only the conference

  170. basically a lot of stuff

  171. basically a lot of stuff @sid05 @verlok @aureliari @lucasalvini

  172. cross site menu

  173. Goals modify a single file to update menu do not

    depend on website implementation do not interfere with website implementation
  174. AJAX: MicroAjax 0.4kB

  175. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB

  176. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB

  177. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  178. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  179. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  180. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  181. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  182. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  183. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  184. AJAX: MicroAjax 0.4kB DOM: TinyDOM 0.4kB DOMEvents: Vine 0.8kB OUR

    CODE: microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); }); SIZE: 1.8kB
  185. microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s

    = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  186. microAjax("static/nav.html", function (res) { $.prependBody(res); vine.bind("ftf_xsite_sel", "change", function(e){ var s

    = $.id("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  187. FTF.ajax("static/nav.html", { success: function (res) { FTF.dom.prependBody(res); FTF.evt.bind("ftf_xsite", "change", function(e){

    var s = FTF("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  188. FTF.ajax("static/nav.html", { success: function (res) { FTF.dom.prependBody(res); FTF.evt.bind("ftf_xsite", "change", function(e){

    var s = FTF("ftf_xsite"); var href = s.options[s.selectedIndex].value; if (href) { document.location.href = href; } }); });
  189. Actually decoupled http://thewellversed.com/2010/12/09/love-warranties-they-dont-make-them-like-they-used-to/broken-heart/

  190. Ain’t that bad http://locomente.blogspot.it/2012/02/single-unemployed.html

  191. LOVE FACT #3 2 out of 5 people marry their

    first love.
  192. You may want a silver bullet http://www.splattlog.com/2009/02/28/the-wolf-man-ecco-la-trasformazione-di-benicio-del-toro/

  193. Do you really need it?

  194. Work to decouple your FOUNDATION CODE

  195. Work to decouple your FOUNDATION CODE AND TEST IT!

  196. Let your UI rely on a framework http://loveallit.tumblr.com/post/1044567068/jegushi-please-dont-leave-me

  197. Advantages of this approach

  198. Portability & Maintainability http://news.tecnozoom.it/tv-lcd/piu-persone-usano-tv-ed-internet-contemporaneamente-post-16157.html - http://marine.rina.org/CATEGORIE_SERVIZI/Gestione_rischio/servizi/maintenance.aspx

  199. Build own architecture http://www.alegriphotos.com/Cards_castle-lphoto-ce5fe99d397c7bf789b6b43d64bf5683.html

  200. Improve javascript skills http://edtechdigest.wordpress.com/2010/09/06/6-reasons-why-students-need-21st-century-skills/

  201. Mobile $LAB .script("xui.js").wait() .script("layer.mobile.js") .script("scripts.js") $LAB .script("jquery.js").wait() .script("lightbox.jquery.js") .script("layer.desktop.js") .script("scripts.js");

    Desktop
  202. the whole point is

  203. BE A JAVASCRIPT PERVERT

  204. BE A JAVASCRIPT PERVERT

  205. play with javascript BE A JAVASCRIPT PERVERT

  206. play with javascript discover your own project needs BE A

    JAVASCRIPT PERVERT
  207. play with javascript discover your own project needs BE A

    JAVASCRIPT PERVERT
  208. play with javascript discover your own project needs BE A

    JAVASCRIPT PERVERT let github be your playground
  209. play with javascript discover your own project needs BE A

    JAVASCRIPT PERVERT let github be your playground javascript is fun
  210. play with javascript discover your own project needs BE A

    JAVASCRIPT PERVERT let github be your playground javascript is fun javascript is lovable
  211. play with javascript discover your own project needs BE A

    JAVASCRIPT PERVERT let github be your playground javascript is fun javascript is lovable but you also need to...
  212. know when to stop

  213. marco@fromthefront.it http://cedmax.com @cedmax http://bit.ly/jsbanana your framework —