JavaScript, Spaghetti, and Meatballs (or why modularity matters)

JavaScript, Spaghetti, and Meatballs (or why modularity matters)

My talk on JSconfBR 2013

Cb5d9e9095cd41b636764a85e57ade4b?s=128

Nando Vieira

June 22, 2013
Tweet

Transcript

  1. 2.
  2. 6.
  3. 8.
  4. 9.

    29 out of 50* most popular Github repositories are JavaScript-related.

    *bootstrap, node, jquery, html5-boilerplate, impress.js, d3, backbone, chosen, three.js, jQuery-File-Upload, brackets, express, angular.js, Modernizr, meteor, less.js, socket.io, jquery-mobile, underscore, reveal.js, co ee-script, jquery-ui, moment, ember.js, select2, todomvc, backbone-fundamentals, jquery-pjax, pdf.js.
  5. 13.

    "invite_friends" : function() { var resizeLoader = function() { $("#loader").css("width",

    $(".places").width()); $("#loader").css("height", $(".places").height()-18); } resizeLoader(); var resizeTimer; $(window).bind('resize', function() { clearTimeout(resizeTimer); resizeTimer = setTimeout(resizeLoader, 50); }); $("a[href=#automatic_invite]").click(function(e){ SomeApp.utils.stopPropagation(e); if(!$(this).parents(".tab_title:first").is(".active")) { $(".tab_title:first") .toggleClass("active"); $(".tab_title:last") .toggleClass("active"); $("#automatic") .toggleClass("hidden"); $("#manual") .toggleClass("hidden"); } }); var suffixes = { "gmail": "@gmail.com", "yahoo": "", "live": "@hotmail.com", "other": ""
  6. 31.

    var Todo = { tasks: [] , addTask: function(task) {}

    , removeTask : function() {} , count : function() {} };
  7. 33.

    var Todo = (function(){ var tasks = []; // private

    variable // expose the public API return { addTask: function(task) {} , removeTask: function(task) {} , count: function() {} }; })();
  8. 37.

    Module("MyApp.MyModule", function(MyModule){ MyModule.fn.initialize = function() { // this is the

    initializer }; MyModule.fn.someFunction = function() { // fn is just shortcut for // prototype alas jQuery }; });
  9. 38.
  10. 44.

    // boot.js $(function(){ var html = $("html") , controller =

    html.data("controller") , action = html.data("action") ; MyApp.Application(controller, action); });
  11. 48.

    // sample.js define(function(){ var tasks = []; // private variable

    // expose the public API return { addTask: function(task) {} , removeTask: function(task) {} , count: function() {} }; });
  12. 56.
  13. 58.

    var tasks = []; // private variable // expose the

    public API module.exports = { addTask: function(task) {} , removeTask: function(task) {} , count: function() {} };
  14. 63.

    module Todo { var tasks = []; // private variable

    // expose the public API export default { addTask: function(task) {} , removeTask: function(task) {} , count: function() {} }; }
  15. 66.

    // load from remote sources module $ from "http://example.org/jquery.js"; //

    Module loader API Loader.load("http://example.org/jquery.js", function($){ // do what you need });
  16. 71.
  17. 72.

    $(".postbox textarea") .on("focus", function(){ $(this).closest(".postbox") .addClass("did-focus") .removeClass("is-contracted") ; }) .on("keyup",

    function(){ var lines = this.value.split(/\r?\n/); var textarea = $(this); if (lines.length >= 5) { textarea.addClass("is-taller"); } else { textarea.removeClass("is-taller"); } }) .on("blur", function(){ if (!this.value) { $(this).closest(".postbox").addClass("is-contracted"); } }) ;
  18. 73.
  19. 74.

    Module("HOWTO.Postbox", function(Postbox){ Postbox.fn.initialize = function(container) { // the initialization code

    this.addEventListeners(); }; Postbox.fn.addEventListeners = function() { this.textarea .on("focus", this.onTextareaFocus.bind(this)) .on("keyup", this.onTextareaKeyUp.bind(this)) .on("blur", this.onTextareaBlur.bind(this)) ; }; });
  20. 75.

    Module("HOWTO.Postbox", function(Postbox){ Postbox.fn.initialize = function(container) {}; Postbox.fn.addEventListeners = function() {};

    Postbox.fn.onTextareaFocus = function(event) { this.container .addClass("did-focus") .removeClass("is-contracted") ; }; });
  21. 76.

    Module("HOWTO.Postbox", function(Postbox){ Postbox.fn.initialize = function(container) {}; Postbox.fn.addEventListeners = function() {};

    Postbox.fn.onTextareaFocus = function(event) {}; var LINES = 5; Postbox.fn.onTextareaKeyUp = function(event) { var lines = event.target.value.split(/\r?\n/); if (lines.length >= LINES) { this.textarea.addClass("is-taller"); } else { this.textarea.removeClass("is-taller"); } }; });
  22. 77.

    Module("HOWTO.Postbox", function(Postbox){ Postbox.fn.initialize = function(container) {}; Postbox.fn.addEventListeners = function() {};

    Postbox.fn.onTextareaFocus = function(event) {}; Postbox.fn.onTextareaKeyUp = function(event) {}; Postbox.fn.onTextareaBlur = function(event) { if (!event.target.value) { this.container.addClass("is-contract"); } }; });
  23. 78.

    describe("HOWTO.Postbox", function() { var container, postbox, textarea; beforeEach(function() { container

    = $("<div/>") .append("<textarea class='pb-input'/>") .append("<button class='pb-button' value='Reply'/>") .appendTo("#sample") ; textarea = container.find("textarea"); postbox = HOWTO.Postbox(container); }); it("sets class when focusing box", function() { textarea.trigger("focus"); expect(container.is(".did-focus")).toBeTruthy(); }); // other specs });
  24. 79.