SlideShare a Scribd company logo
JAVASCRIPT CODE
              ORGANIZATION, PATTERNS
                               ZACH DENNIS
                         MUTUALLY HUMAN SOFTWARE




Monday, March 28, 2011                             1
<div class="presentation">
                           <a onclick="playPresentation()">
                             Play Presentation
                           </a>
                         </div>




                             INLINE JAVASCRIPT
                                  IS NOT SUSTAINABLE


Monday, March 28, 2011                                        2
POOR MODULARITY / REUSE


                    CODE MAINTENANCE PROBLEMS


                    LACK OF CACHING


                    DIFFICULTY SCALING TO LARGER APPS




Monday, March 28, 2011                                  3
UNOBTRUSIVE JAVASCRIPT
                            PATHWAY TO THE GREAT VALLEY


Monday, March 28, 2011                                    4
2 TECHNIQUES
                              SEPARATE CONTENT FROM BEHAVIOR,
                         REGISTER EVENT HANDLERS PROGRAMMATICALLY




Monday, March 28, 2011                                              5
SEPARATE BEHAVIOR FROM
                                CONTENT

                              <div class="presentation">
                                <a class="play">
                                  Play Presentation
                                </a>
                              </div>

                                                           HTML


                          $(“.presentation .play”).click(function(){
                            // ...
                          });

                                                                       JS


Monday, March 28, 2011                                                      6
REGISTER HANDLERS
                                PROGRAMMATICALLY
                              $(“.presentation .play”).click(function(){
                                // ...
                              });                                    JQUERY


                         $(“.presentation .play”).addEvent(“click”, function(){
                           // ...
                         });
                                                                      MOOTOOLS


                               var el = dojo.query(“.presentation .play”);
                               el.connect(“click”, function(){
                                 // ...
                               });
                                                                       DOJO


Monday, March 28, 2011                                                            7
THE GREAT VALLEY EFFECT




Monday, March 28, 2011                             8
A BETTER VANTAGE POINT



                                     SEE PATTERNS

                                     CODE DECOMPOSITION

                                     CODE ORGANIZATION

                                     APPLY PATTERNS




Monday, March 28, 2011                                    9
DRIVES SEMANTIC
                    SELECTOR DRIVEN CODE



Monday, March 28, 2011                     10
REINFORCE SEMANTIC MARKUP

                              <div class="presentation">
                                <a class="play">
                                  Play Presentation
                                </a>
                              </div>                       HTML

                         $(“.presentation .play”).click(function(){
                           // ...
                         });
                                                                      JS

                         .presentation .play {
                           background-image: url(...);
                           font-size: 1.em;
                         }                                        CSS

Monday, March 28, 2011                                                     11
SELECTOR DRIVEN CODE


                     IT CAN BE SCANNED AND
                        RE-ORGANIZED MORE
                    EFFECTIVELY. IT’S EASIER TO
                   VISUALIZE AND MANIPULATE.




Monday, March 28, 2011                            12
BUT THEN




Monday, March 28, 2011              13
$(".presentation .play").click(function(){
                           var presentation = $(this).parents('.presentation:first');
                           presentation.addClass('playing');
                           selectSlide(presentation.find(".slides:first"));
                         });

                         $(".presentation .stop").click(function(){
                           $(this).parents('.deck:first').addClass('stopping');
                         });

                         $('.presentation a.destroy').live('ajax:success', function(data){
                           var deck = $(this).parents('.deck:first');
                           deck.fadeOut('fast', deck.remove);
                         });

                         $('#grid .slide a:last').click(function(){
                           selectSlide($(this).parents(".slide:first"));
                           return false;
                         });

                         $('img.slide').live("slide:loaded", function(){
                             resizeSlide($(this));
                         });

                         // any time the window resizes, resize the main slide
                         $(window).resize(function(){
                           resizeSlide($(".slide_viewer img.slide"));
                         });

                         function resizeSlide(img) {
                           var viewer_width = $('.slide_viewer').width();
                           var viewer_height = $('.slide_viewer').height();

                             // Use original width and height since the image may be scaled
                             // down to a smaller size, and we want to use the original size to scale
                             // the image rather than the size it is currently scaled to
                             var slide_width = img.data('original_width');
                             var slide_height = img.data('original_height');

                             if(slide_width > viewer_width){
                               ratio = viewer_width / slide_width;
                               $('.slide_viewer img.slide').css({width: viewer_width, height: slide_height * ratio});
                             }
                         }


                                                                page 1 of 22



Monday, March 28, 2011                                                                                                  14
MONOLITHIC JAVASCRIPT
                           FORMED OF A SINGLE LARGE FILE.


Monday, March 28, 2011                                      15
CODE MONOLITHS

                    GREAT FOR DEPLOYMENT

                    BAD FOR DEVELOPMENT

                         LOSES CONTEXT, HIERARCHY, SCOPE

                         VISUALLY HARD TO SCAN

                         CODE WITH DIFFERENT BEHAVIORS OR REASONS TO
                         EXIST, CO-EXIST

                    EXCEPT VERY SMALL SITES / APPS




Monday, March 28, 2011                                                 16
PATTERNS FOR AVOIDING
                              MONOLITHS



                    TRADITIONAL CLASS-BASED OO

                    FUNCTIONS, CLOSURES

                    EVENT-DRIVEN JAVASCRIPT




Monday, March 28, 2011                           17
TRADITIONAL CLASS-BASED OO
              APPLYING TRIED AND TRUE TECHNIQUES WITH JAVASCRIPT


Monday, March 28, 2011                                             18
function Presentation(element) {
                 this._element = element;
                 this.play = element.find(“.play”);
                 this.stop = element.find(“.stop”);
                 this.play.bind(“click”, $.proxy(this.play, this));
                 this.stop.bind(“click”, $.proxy(this.stop, this));
              };

              Presentation.prototype.play = function() {
                 this._element.addClass(“playing”);
                 // ...
              };

              Presentation.prototype.stop = function(hours) {
                 // ...
              };
                                                                      JS



Monday, March 28, 2011                                                     19
var Presentation = $.Class.create({

                  initialize: function(element) {
                     this._element = element;
                     this.play = element.find(“.play”);
                     this.stop = element.find(“.stop”);
                     this.play.bind(“click”, $.proxy(this.play, this));
                     this.stop.bind(“click”, $.proxy(this.stop, this));
                  },

                  play: function(){
                     this._element.addClass(“playing”);
                     // ...
                  },

                  stop: function(){
                     // ...
                  },

              });
                                                                          JQUERY

Monday, March 28, 2011                                                             20
USING THE CLASS

                         var el = $(“.presentation:first”);

                         var prez = new Presentation(prez);

                         prez.play();

                         prez.stop();

                                                              JQUERY




Monday, March 28, 2011                                                 21
BENEFITS



                    DATA/BEHAVIOR ENCAPSULATION

                    CLEAR BOUNDARIES OF RESPONSIBILITIES

                    API DEFINITION

                    MODULAR / REUSABLE CODE




Monday, March 28, 2011                                     22
ASSIGN PSEUDO-PRIVATE VARIABLE
            var Presentation = $.Class.create({

                 initialize: function(element) {
                    this._element = element;
                    this.play = element.find(“.play”);
                    this.stop = element.find(“.stop”);
                    this.play.bind(“click”, $.proxy(this.play, this));
                    this.stop.bind(“click”, $.proxy(this.stop, this));
                 },

                 play: function(){
                    this._element.addClass(“playing”);
                    // ...
                 },

              stop: function(){
                 // ...
              },
            });                                                          JQUERY

Monday, March 28, 2011                                                            23
FIND AND ASSIGN ELEMENTS WE NEED ACCESS TO
            var Presentation = $.Class.create({

                 initialize: function(element) {
                    this._element = element;
                    this.play = element.find(“.play”);
                    this.stop = element.find(“.stop”);
                    this.play.bind(“click”, $.proxy(this.play, this));
                    this.stop.bind(“click”, $.proxy(this.stop, this));
                 },

                 play: function(){
                    this._element.addClass(“playing”);
                    // ...
                 },

              stop: function(){
                 // ...
              },
            });                                                          JQUERY

Monday, March 28, 2011                                                            24
REGISTER EVENT HANDLERS
            var Presentation = $.Class.create({

                 initialize: function(element) {
                   this._element = element;
                   this.play = element.find(“.play”);
                   this.stop = element.find(“.stop”);
                   this.play.bind(“click”, $.proxy(this.play, this));
                   this.stop.bind(“click”, $.proxy(this.stop, this));
                 },

                play: function(){
                   this._element.addClass(“playing”);
                   // ...
                },

                 stop: function(){
                   // ...

                                                                        JQUERY

Monday, March 28, 2011                                                           25
KEEP REFERENCE TO THIS
            var Presentation = $.Class.create({

                 initialize: function(element) {
                   this._element = element;
                   this.play = element.find(“.play”);
                   this.stop = element.find(“.stop”);
                   this.play.bind(“click”, $.proxy(this.play, this); );
                   this.stop.bind(“click”, $.proxy(this.stop, this) );
                 },

                play: function(){
                  this ._element.addClass(“playing”);
                   // ...
                },

                 stop: function(){
                   // ...

                                                                      JQUERY

Monday, March 28, 2011                                                         26
FEELS A LITTLE HEAVY
              FEELS A LITTLE AWKWARD




Monday, March 28, 2011                 27
SAME EXAMPLE,
                         DIFFERENT PATTERN




Monday, March 28, 2011                       28
FUNCTIONS, CLOSURES
                          TAKING ADVANTAGE OF JAVASCRIPT


Monday, March 28, 2011                                     29
FUNCTIONS, SCOPE, CLOSURES
                         var Presentation = function(element){
                           var presentation = element;
                           presentation.delegate(".play", "click", play);
                           presentation.delegate(".stop", "click", stop);

                              function play(){
                                presentation.addClass(“playing”);
                                // ...
                              }

                              function stop(){
                                // ...
                              }

                              return {
                                play: play,
                                stop: stop
                              }
                         };
                                                                        JQUERY

Monday, March 28, 2011                                                           30
ONLY DIFFERENCE, NO “NEW”

                         var el = $(“.presentation:first”);

                         var prez = Presentation(prez);

                         prez.play();

                         prez.stop();

                                                          JQUERY




Monday, March 28, 2011                                             31
ACCESSIBLE PRIVATE VARIABLES
                         var Presentation = function(element){
                           var presentation = element;
                           presentation.delegate(".play", "click", play);
                           presentation.delegate(".stop", "click", stop);

                              function play(){
                                presentation.addClass(“playing”);
                                // ...
                              }

                              function stop(){
                                // ...
                              }

                              return {
                                play: play,
                                stop: stop
                              }
                         };                                             JQUERY

Monday, March 28, 2011                                                           32
STRAIGHT FORWARD EVENT DELEGATION
                         var Presentation = function(element){
                           var presentation = element;
                           presentation.delegate(".play", "click", play);
                           presentation.delegate(".stop", "click", stop);

                              function play(){
                                presentation.addClass(“playing”);
                                // ...
                              }

                              function stop(){
                                // ...
                              }

                              return {
                                play: play,
                                stop: stop
                              }
                         };                                             JQUERY

Monday, March 28, 2011                                                           33
API DEFINITION
                         var Presentation = function(element){
                           var presentation = element;
                           presentation.delegate(".play", "click", play);
                           presentation.delegate(".stop", "click", stop);

                              function play(){
                                 presentation.addClass(“playing”);
                                 // ...
                              };

                              function stop(){
                                 // ...
                              };

                              return {
                                play: play,
                                stop: stop
                              };
                         };                                             JQUERY

Monday, March 28, 2011                                                           34
FEELS MORE LIKE HOME




Monday, March 28, 2011                          35
WHAT IF WE DIDN’T
                     CARE ABOUT A
                      PUBLIC API?



Monday, March 28, 2011                  36
SHORTER. SIMPLER. SWEETER.

       (function(){
         $(".presentation").delegate(".play", "click", play);
         $(".presentation").delegate(".stop", "click", stop);

            function play(){
              $(this).parents(“.presentation:first”).addClass(“playing”);
              // ...
            }

         function stop(){
           // ...
         }
       })();
                                                                   JQUERY




Monday, March 28, 2011                                                      37
WHAT JUST HAPPENED?



                    CREATED A FUNCTION, EXECUTED IT

                    REMOVE UNNECESSARY VARS

                    RELY ON SELECTOR-DRIVEN EVENT HANDLERS

                    NO NEED TO MANUALLY BIND TO ELEMENTS




Monday, March 28, 2011                                       38
CLASS-BASED                                        FUNCTION, CLOSURES                                              EVENT-DRIVEN

var Presentation = $.Class.create({                       var Presentation = (function(element){             function(){
                                                            var presentation = element;                        $(".presentation").delegate(".play", "click", play);
  initialize: function(element) {                           presentation.delegate(".play", "click", play);     $(".presentation").delegate(".stop", "click", stop);
     this._element = element;                               presentation.delegate(".stop", "click", stop);
     this.play = element.find(“.play”);                                                                        function play(){
     this.stop = element.find(“.stop”);                     function play(){                                     $(this).parents(“.presentation:first”).addClass(“playing”);
     this.play.bind(“click”, $.proxy(this.play, this));       presentation.addClass(“playing”);                  // ...
     this.stop.bind(“click”, $.proxy(this.stop, this));       // ...                                           }
  },                                                        }
                                                                                                               function stop(){
  play: function(){                                         function stop(){                                      // ...
     this._element.addClass(“playing”);                       // ...                                           }
     // ...                                                 }                                                }();
  },
                                                            return {
  stop: function(){                                           play: playPresentation,
    // ...                                                    stop: stopPresentation
  }                                                         }
});                                                       });




Monday, March 28, 2011                                                                                                                                                         39
FUNCTIONS, CLOSURES RECAP



                    USE FUNCTIONS AND CLOSURES TO CREATE SCOPE

                    PRESERVE PRIVATE METHODS AND PROPERTIES WITH
                    VAR STATEMENTS

                    RETURN PUBLIC METHODS, PROPERTIES (OPTIONAL)

                    AND WE DON’T POLLUTE GLOBAL NAMESPACE




Monday, March 28, 2011                                             40
ONE STEP FURTHER




Monday, March 28, 2011                      41
EVENT-DRIVEN JAVASCRIPT
                         DECLARATIVELY READABLE SELECTOR DRIVEN CODE


Monday, March 28, 2011                                                 42
6 GUIDELINES




Monday, March 28, 2011                  43
MEANINGFUL FILE NAMES TO
                           ORGANIZE BEHAVIOR
               PRESENTER.JS
               PRESENTER/
                  GRID.JS
                  REMOTE-CONTROLS.JS

                VIEWER.JS
                VIEWER/
                   REMOTE-CONTROLS.JS

                  SLIDES/
                      RESIZING.JS
                                 *USE COMBINATOR, COMPRESSOR, MINIFIER FOR DEPLOYMENT


Monday, March 28, 2011                                                                  44
STRUCTURE RELIES ON
                              FUNCTION SCOPE
                                       EXECUTES IMMEDIATELY
                    (function(){

                    })();
                                                    JS MODULE



                                   EXECUTES AFTER DOM READY
                   $(function(){

                   });
                                                JQUERY MODULE




Monday, March 28, 2011                                          45
DECLARE PAGE CHECKS FIRST



                    $(function(){
                      if(!$("html.presenter").length) return;
                                                                PRESENTER.JS
                    });
                                                                 JQUERY




Monday, March 28, 2011                                                         46
DECLARE HANDLERS AND VARS
                           SECOND
          $(function(){
            if(!$("html.presenter").length) return;

               var presentation = $(“.presentation”),
                   attendee_count = 0;

               presentation.delegate(“.play”, “click”, play);
               presentation.delegate(“.stop”, “click”, stop);
               presentation.delegate(“.slide .next”, “click”, nextSlide);
               presentation.delegate(“.slide .prev”, “click”, prevSlide);
          });                                                     PRESENTER.JS

                                                                    JQUERY




Monday, March 28, 2011                                                           47
DECLARE FUNCTIONS LAST
          $(function(){
            if(!$("html.presenter").length) return;

              var presentation = $(“.presentation”),
                  attendee_count = 0;

              presentation.delegate(“.play”, “click”, play);
              presentation.delegate(“.stop”, “click”, stop);
              presentation.delegate(“.slide .next”, “click”, nextSlide);
              presentation.delegate(“.slide .prev”, “click”, prevSlide);

               function play(){
                  // ...
               };

               function stop(){
                                                                  PRESENTER.JS
                // ...
                                                                   JQUERY

Monday, March 28, 2011                                                           48
QUICKER TO SCAN. KEEPING
                 DECLARATIONS ABOVE
                FUNCTION DEFINITIONS
                     CREATES MORE
                    READABLE CODE.



Monday, March 28, 2011                     49
EVENTS DRIVE CROSS-CLOSURE
                       COMMUNICATION
           PRESENTER.JS


         function nextSlide(){
           var prez = $(this).parents('.presentation:first');                    _
           // ...                                                                    _
                                                                                         _
              current_slide.removeClass('current');
              next_slide.addClass('current');

             prez.trigger('slide:changed', { slide: next_slide });
         };



            THUMBNAIL-CONTROLS.JS


          $("body").delegate(".presentation", "slide:changed", transitionToSlide);


         REMOTE-VIEWER-CONTROLS.JS

          $("body").delegate(".presentation", "slide:changed", changeSlideOnRemoteViewers);



Monday, March 28, 2011                                                                        50
BENEFITS

                    FUNCTIONS AND CLOSURES ALLOW GROUPING OF
                    COMMON BEHAVIOR AND DATA

                    CUSTOM EVENTS ARE AWESOME

                         NO NEED TO HAVE REFERENCES TO EXTERNAL
                         OBJECTS THROUGHOUT OUR APP

                         LOOSER COUPLING

                         EASIER TO HOOK IN NEW PARTS OF OUR APP WITH
                         MINIMAL IMPACT TO EXISTING CODE




Monday, March 28, 2011                                                 51
Monday, March 28, 2011   52
EVENT-DRIVEN HOW WE GOT THERE

                    MEANINGFUL DIRECTORY AND FILE NAMES

                    FOLLOW MODULE OR SIMILAR CLOSURE-PATTERN

                    GENERAL GUIDELINES FOR READABILITY:

                         DECLARE PAGE CHECKS FIRST

                         DECLARE HANDLERS AND VARS SECOND

                         DECLARE FUNCTIONS LAST

                    USE EVENTS TO DRIVE CROSS-CLOSURE
                    COMMUNICATION


Monday, March 28, 2011                                         53
Monday, March 28, 2011   54
IN SUMMARY
                    INLINE JAVASCRIPT IS NOT A SUSTAINABLE APPROACH.


                    UNOBTRUSIVE JAVASCRIPT IS A PATH TO “THE GREAT VALLEY”


                    MONOLITHIC UJS WORKS FINE FOR SMALL APPS, BUT DOESN’T SCALE WELL.
                    FORTUNATELY SELECTOR-DRIVEN JS IS EASIER TO MANIPULATE AND
                    REORGANIZE.


                    TRADITIONAL CLASS-BASED OO + UJS WORKS WELL, BUT CAN AT TIMES BE A
                    BIT HEAVY


                    FUNCTION/CLOSURES ARE A LIGHTER WEIGHT APPROACH THAN TRADITIONAL
                    OO. FEELS MORE JAVASCRIPTY.


                    EVENT-DRIVEN APPROACH WITH EMPHASIS ON FUNCTION/CLOSURES FOR SCOPE
                    AND DECLARATIVE SELECTOR-DRIVEN CODE IS LEANER, SCALABLE AND
                    PROMOTES LOOSE COOUPLING



Monday, March 28, 2011                                                                   55

More Related Content

PDF
Action bar
ODP
Android App Development - 05 Action bar
PPTX
Android 3
PDF
Using and reusing CakePHP plugins
PPTX
Silverlight as a Gaming Platform
PDF
WordPress Ajax Recipes
PDF
Building Scalable Web Apps
PDF
Developing Mobile Apps, Lecture 5
Action bar
Android App Development - 05 Action bar
Android 3
Using and reusing CakePHP plugins
Silverlight as a Gaming Platform
WordPress Ajax Recipes
Building Scalable Web Apps
Developing Mobile Apps, Lecture 5

Viewers also liked (10)

PPTX
Recognize Patterns of Organization
PDF
Patterns of organization-2
PPT
Recognizing patterns of organization
PPT
pattern of organization
ODP
5 Organizational Patterns In Paragraphs
PPTX
Pattern of Paragraph Development
PPTX
Pattern of organization
PDF
4. patterns of organization
PPTX
Methods of paragraph development
PPTX
Methods of Paragraph Development
Recognize Patterns of Organization
Patterns of organization-2
Recognizing patterns of organization
pattern of organization
5 Organizational Patterns In Paragraphs
Pattern of Paragraph Development
Pattern of organization
4. patterns of organization
Methods of paragraph development
Methods of Paragraph Development
Ad

Similar to JavaScript Code Organizations, Patterns Slides - Zach Dennis (20)

PDF
Cleaner, Leaner, Meaner: Refactoring your jQuery
PDF
Single Page Applications in Angular (italiano)
PDF
Creating an inclusive workplace with JS
PDF
Tools for Development and Debugging in Python
PDF
Mike hostetler - jQuery knowledge append to you
PPTX
A Rich Web Experience with jQuery, Ajax and .NET
PPTX
A Rich Web experience with jQuery, Ajax and .NET
PPTX
How to increase Performance of Web Application using JQuery
PDF
Gearman, from the worker's perspective
PDF
The jQuery Divide
PDF
Building mobile web apps with Mobello
KEY
jQuery Anti-Patterns for Performance & Compression
PDF
JavaFX Pitfalls
PDF
YUI3 Modules
PDF
jQuery secrets
DOC
Jquery examples
PDF
How te bring common UI patterns to ADF
PPT
Kick start with j query
PDF
jQuery Rescue Adventure
Cleaner, Leaner, Meaner: Refactoring your jQuery
Single Page Applications in Angular (italiano)
Creating an inclusive workplace with JS
Tools for Development and Debugging in Python
Mike hostetler - jQuery knowledge append to you
A Rich Web Experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NET
How to increase Performance of Web Application using JQuery
Gearman, from the worker's perspective
The jQuery Divide
Building mobile web apps with Mobello
jQuery Anti-Patterns for Performance & Compression
JavaFX Pitfalls
YUI3 Modules
jQuery secrets
Jquery examples
How te bring common UI patterns to ADF
Kick start with j query
jQuery Rescue Adventure
Ad

More from Zach Dennis (6)

PDF
A Brief, Very Very Brief Intro to Systems Thinking
PDF
BTLE (Bluetooth Low Energy) and CoreBluetooth
PDF
Sand Piles and Software - Madison Ruby Conference
PDF
Discovering patterns
PDF
PDF
Balancing the Pendulum: Reflecting on BDD in Practice
A Brief, Very Very Brief Intro to Systems Thinking
BTLE (Bluetooth Low Energy) and CoreBluetooth
Sand Piles and Software - Madison Ruby Conference
Discovering patterns
Balancing the Pendulum: Reflecting on BDD in Practice

Recently uploaded (20)

PDF
Approach and Philosophy of On baking technology
PPTX
Tartificialntelligence_presentation.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
cuic standard and advanced reporting.pdf
PDF
Encapsulation theory and applications.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
Machine Learning_overview_presentation.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
A Presentation on Artificial Intelligence
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
Approach and Philosophy of On baking technology
Tartificialntelligence_presentation.pptx
Spectral efficient network and resource selection model in 5G networks
cuic standard and advanced reporting.pdf
Encapsulation theory and applications.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Machine Learning_overview_presentation.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
20250228 LYD VKU AI Blended-Learning.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
MIND Revenue Release Quarter 2 2025 Press Release
“AI and Expert System Decision Support & Business Intelligence Systems”
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Programs and apps: productivity, graphics, security and other tools
Encapsulation_ Review paper, used for researhc scholars
A Presentation on Artificial Intelligence
SOPHOS-XG Firewall Administrator PPT.pptx
The Rise and Fall of 3GPP – Time for a Sabbatical?

JavaScript Code Organizations, Patterns Slides - Zach Dennis

  • 1. JAVASCRIPT CODE ORGANIZATION, PATTERNS ZACH DENNIS MUTUALLY HUMAN SOFTWARE Monday, March 28, 2011 1
  • 2. <div class="presentation"> <a onclick="playPresentation()"> Play Presentation </a> </div> INLINE JAVASCRIPT IS NOT SUSTAINABLE Monday, March 28, 2011 2
  • 3. POOR MODULARITY / REUSE CODE MAINTENANCE PROBLEMS LACK OF CACHING DIFFICULTY SCALING TO LARGER APPS Monday, March 28, 2011 3
  • 4. UNOBTRUSIVE JAVASCRIPT PATHWAY TO THE GREAT VALLEY Monday, March 28, 2011 4
  • 5. 2 TECHNIQUES SEPARATE CONTENT FROM BEHAVIOR, REGISTER EVENT HANDLERS PROGRAMMATICALLY Monday, March 28, 2011 5
  • 6. SEPARATE BEHAVIOR FROM CONTENT <div class="presentation"> <a class="play"> Play Presentation </a> </div> HTML $(“.presentation .play”).click(function(){ // ... }); JS Monday, March 28, 2011 6
  • 7. REGISTER HANDLERS PROGRAMMATICALLY $(“.presentation .play”).click(function(){ // ... }); JQUERY $(“.presentation .play”).addEvent(“click”, function(){ // ... }); MOOTOOLS var el = dojo.query(“.presentation .play”); el.connect(“click”, function(){ // ... }); DOJO Monday, March 28, 2011 7
  • 8. THE GREAT VALLEY EFFECT Monday, March 28, 2011 8
  • 9. A BETTER VANTAGE POINT SEE PATTERNS CODE DECOMPOSITION CODE ORGANIZATION APPLY PATTERNS Monday, March 28, 2011 9
  • 10. DRIVES SEMANTIC SELECTOR DRIVEN CODE Monday, March 28, 2011 10
  • 11. REINFORCE SEMANTIC MARKUP <div class="presentation"> <a class="play"> Play Presentation </a> </div> HTML $(“.presentation .play”).click(function(){ // ... }); JS .presentation .play { background-image: url(...); font-size: 1.em; } CSS Monday, March 28, 2011 11
  • 12. SELECTOR DRIVEN CODE IT CAN BE SCANNED AND RE-ORGANIZED MORE EFFECTIVELY. IT’S EASIER TO VISUALIZE AND MANIPULATE. Monday, March 28, 2011 12
  • 13. BUT THEN Monday, March 28, 2011 13
  • 14. $(".presentation .play").click(function(){ var presentation = $(this).parents('.presentation:first'); presentation.addClass('playing'); selectSlide(presentation.find(".slides:first")); }); $(".presentation .stop").click(function(){ $(this).parents('.deck:first').addClass('stopping'); }); $('.presentation a.destroy').live('ajax:success', function(data){ var deck = $(this).parents('.deck:first'); deck.fadeOut('fast', deck.remove); }); $('#grid .slide a:last').click(function(){ selectSlide($(this).parents(".slide:first")); return false; }); $('img.slide').live("slide:loaded", function(){ resizeSlide($(this)); }); // any time the window resizes, resize the main slide $(window).resize(function(){ resizeSlide($(".slide_viewer img.slide")); }); function resizeSlide(img) { var viewer_width = $('.slide_viewer').width(); var viewer_height = $('.slide_viewer').height(); // Use original width and height since the image may be scaled // down to a smaller size, and we want to use the original size to scale // the image rather than the size it is currently scaled to var slide_width = img.data('original_width'); var slide_height = img.data('original_height'); if(slide_width > viewer_width){ ratio = viewer_width / slide_width; $('.slide_viewer img.slide').css({width: viewer_width, height: slide_height * ratio}); } } page 1 of 22 Monday, March 28, 2011 14
  • 15. MONOLITHIC JAVASCRIPT FORMED OF A SINGLE LARGE FILE. Monday, March 28, 2011 15
  • 16. CODE MONOLITHS GREAT FOR DEPLOYMENT BAD FOR DEVELOPMENT LOSES CONTEXT, HIERARCHY, SCOPE VISUALLY HARD TO SCAN CODE WITH DIFFERENT BEHAVIORS OR REASONS TO EXIST, CO-EXIST EXCEPT VERY SMALL SITES / APPS Monday, March 28, 2011 16
  • 17. PATTERNS FOR AVOIDING MONOLITHS TRADITIONAL CLASS-BASED OO FUNCTIONS, CLOSURES EVENT-DRIVEN JAVASCRIPT Monday, March 28, 2011 17
  • 18. TRADITIONAL CLASS-BASED OO APPLYING TRIED AND TRUE TECHNIQUES WITH JAVASCRIPT Monday, March 28, 2011 18
  • 19. function Presentation(element) { this._element = element; this.play = element.find(“.play”); this.stop = element.find(“.stop”); this.play.bind(“click”, $.proxy(this.play, this)); this.stop.bind(“click”, $.proxy(this.stop, this)); }; Presentation.prototype.play = function() { this._element.addClass(“playing”); // ... }; Presentation.prototype.stop = function(hours) { // ... }; JS Monday, March 28, 2011 19
  • 20. var Presentation = $.Class.create({ initialize: function(element) { this._element = element; this.play = element.find(“.play”); this.stop = element.find(“.stop”); this.play.bind(“click”, $.proxy(this.play, this)); this.stop.bind(“click”, $.proxy(this.stop, this)); }, play: function(){ this._element.addClass(“playing”); // ... }, stop: function(){ // ... }, }); JQUERY Monday, March 28, 2011 20
  • 21. USING THE CLASS var el = $(“.presentation:first”); var prez = new Presentation(prez); prez.play(); prez.stop(); JQUERY Monday, March 28, 2011 21
  • 22. BENEFITS DATA/BEHAVIOR ENCAPSULATION CLEAR BOUNDARIES OF RESPONSIBILITIES API DEFINITION MODULAR / REUSABLE CODE Monday, March 28, 2011 22
  • 23. ASSIGN PSEUDO-PRIVATE VARIABLE var Presentation = $.Class.create({ initialize: function(element) { this._element = element; this.play = element.find(“.play”); this.stop = element.find(“.stop”); this.play.bind(“click”, $.proxy(this.play, this)); this.stop.bind(“click”, $.proxy(this.stop, this)); }, play: function(){ this._element.addClass(“playing”); // ... }, stop: function(){ // ... }, }); JQUERY Monday, March 28, 2011 23
  • 24. FIND AND ASSIGN ELEMENTS WE NEED ACCESS TO var Presentation = $.Class.create({ initialize: function(element) { this._element = element; this.play = element.find(“.play”); this.stop = element.find(“.stop”); this.play.bind(“click”, $.proxy(this.play, this)); this.stop.bind(“click”, $.proxy(this.stop, this)); }, play: function(){ this._element.addClass(“playing”); // ... }, stop: function(){ // ... }, }); JQUERY Monday, March 28, 2011 24
  • 25. REGISTER EVENT HANDLERS var Presentation = $.Class.create({ initialize: function(element) { this._element = element; this.play = element.find(“.play”); this.stop = element.find(“.stop”); this.play.bind(“click”, $.proxy(this.play, this)); this.stop.bind(“click”, $.proxy(this.stop, this)); }, play: function(){ this._element.addClass(“playing”); // ... }, stop: function(){ // ... JQUERY Monday, March 28, 2011 25
  • 26. KEEP REFERENCE TO THIS var Presentation = $.Class.create({ initialize: function(element) { this._element = element; this.play = element.find(“.play”); this.stop = element.find(“.stop”); this.play.bind(“click”, $.proxy(this.play, this); ); this.stop.bind(“click”, $.proxy(this.stop, this) ); }, play: function(){ this ._element.addClass(“playing”); // ... }, stop: function(){ // ... JQUERY Monday, March 28, 2011 26
  • 27. FEELS A LITTLE HEAVY FEELS A LITTLE AWKWARD Monday, March 28, 2011 27
  • 28. SAME EXAMPLE, DIFFERENT PATTERN Monday, March 28, 2011 28
  • 29. FUNCTIONS, CLOSURES TAKING ADVANTAGE OF JAVASCRIPT Monday, March 28, 2011 29
  • 30. FUNCTIONS, SCOPE, CLOSURES var Presentation = function(element){ var presentation = element; presentation.delegate(".play", "click", play); presentation.delegate(".stop", "click", stop); function play(){ presentation.addClass(“playing”); // ... } function stop(){ // ... } return { play: play, stop: stop } }; JQUERY Monday, March 28, 2011 30
  • 31. ONLY DIFFERENCE, NO “NEW” var el = $(“.presentation:first”); var prez = Presentation(prez); prez.play(); prez.stop(); JQUERY Monday, March 28, 2011 31
  • 32. ACCESSIBLE PRIVATE VARIABLES var Presentation = function(element){ var presentation = element; presentation.delegate(".play", "click", play); presentation.delegate(".stop", "click", stop); function play(){ presentation.addClass(“playing”); // ... } function stop(){ // ... } return { play: play, stop: stop } }; JQUERY Monday, March 28, 2011 32
  • 33. STRAIGHT FORWARD EVENT DELEGATION var Presentation = function(element){ var presentation = element; presentation.delegate(".play", "click", play); presentation.delegate(".stop", "click", stop); function play(){ presentation.addClass(“playing”); // ... } function stop(){ // ... } return { play: play, stop: stop } }; JQUERY Monday, March 28, 2011 33
  • 34. API DEFINITION var Presentation = function(element){ var presentation = element; presentation.delegate(".play", "click", play); presentation.delegate(".stop", "click", stop); function play(){ presentation.addClass(“playing”); // ... }; function stop(){ // ... }; return { play: play, stop: stop }; }; JQUERY Monday, March 28, 2011 34
  • 35. FEELS MORE LIKE HOME Monday, March 28, 2011 35
  • 36. WHAT IF WE DIDN’T CARE ABOUT A PUBLIC API? Monday, March 28, 2011 36
  • 37. SHORTER. SIMPLER. SWEETER. (function(){ $(".presentation").delegate(".play", "click", play); $(".presentation").delegate(".stop", "click", stop); function play(){ $(this).parents(“.presentation:first”).addClass(“playing”); // ... } function stop(){ // ... } })(); JQUERY Monday, March 28, 2011 37
  • 38. WHAT JUST HAPPENED? CREATED A FUNCTION, EXECUTED IT REMOVE UNNECESSARY VARS RELY ON SELECTOR-DRIVEN EVENT HANDLERS NO NEED TO MANUALLY BIND TO ELEMENTS Monday, March 28, 2011 38
  • 39. CLASS-BASED FUNCTION, CLOSURES EVENT-DRIVEN var Presentation = $.Class.create({ var Presentation = (function(element){ function(){ var presentation = element; $(".presentation").delegate(".play", "click", play); initialize: function(element) { presentation.delegate(".play", "click", play); $(".presentation").delegate(".stop", "click", stop); this._element = element; presentation.delegate(".stop", "click", stop); this.play = element.find(“.play”); function play(){ this.stop = element.find(“.stop”); function play(){ $(this).parents(“.presentation:first”).addClass(“playing”); this.play.bind(“click”, $.proxy(this.play, this)); presentation.addClass(“playing”); // ... this.stop.bind(“click”, $.proxy(this.stop, this)); // ... } }, } function stop(){ play: function(){ function stop(){ // ... this._element.addClass(“playing”); // ... } // ... } }(); }, return { stop: function(){ play: playPresentation, // ... stop: stopPresentation } } }); }); Monday, March 28, 2011 39
  • 40. FUNCTIONS, CLOSURES RECAP USE FUNCTIONS AND CLOSURES TO CREATE SCOPE PRESERVE PRIVATE METHODS AND PROPERTIES WITH VAR STATEMENTS RETURN PUBLIC METHODS, PROPERTIES (OPTIONAL) AND WE DON’T POLLUTE GLOBAL NAMESPACE Monday, March 28, 2011 40
  • 41. ONE STEP FURTHER Monday, March 28, 2011 41
  • 42. EVENT-DRIVEN JAVASCRIPT DECLARATIVELY READABLE SELECTOR DRIVEN CODE Monday, March 28, 2011 42
  • 44. MEANINGFUL FILE NAMES TO ORGANIZE BEHAVIOR PRESENTER.JS PRESENTER/ GRID.JS REMOTE-CONTROLS.JS VIEWER.JS VIEWER/ REMOTE-CONTROLS.JS SLIDES/ RESIZING.JS *USE COMBINATOR, COMPRESSOR, MINIFIER FOR DEPLOYMENT Monday, March 28, 2011 44
  • 45. STRUCTURE RELIES ON FUNCTION SCOPE EXECUTES IMMEDIATELY (function(){ })(); JS MODULE EXECUTES AFTER DOM READY $(function(){ }); JQUERY MODULE Monday, March 28, 2011 45
  • 46. DECLARE PAGE CHECKS FIRST $(function(){ if(!$("html.presenter").length) return; PRESENTER.JS }); JQUERY Monday, March 28, 2011 46
  • 47. DECLARE HANDLERS AND VARS SECOND $(function(){ if(!$("html.presenter").length) return; var presentation = $(“.presentation”), attendee_count = 0; presentation.delegate(“.play”, “click”, play); presentation.delegate(“.stop”, “click”, stop); presentation.delegate(“.slide .next”, “click”, nextSlide); presentation.delegate(“.slide .prev”, “click”, prevSlide); }); PRESENTER.JS JQUERY Monday, March 28, 2011 47
  • 48. DECLARE FUNCTIONS LAST $(function(){ if(!$("html.presenter").length) return; var presentation = $(“.presentation”), attendee_count = 0; presentation.delegate(“.play”, “click”, play); presentation.delegate(“.stop”, “click”, stop); presentation.delegate(“.slide .next”, “click”, nextSlide); presentation.delegate(“.slide .prev”, “click”, prevSlide); function play(){ // ... }; function stop(){ PRESENTER.JS // ... JQUERY Monday, March 28, 2011 48
  • 49. QUICKER TO SCAN. KEEPING DECLARATIONS ABOVE FUNCTION DEFINITIONS CREATES MORE READABLE CODE. Monday, March 28, 2011 49
  • 50. EVENTS DRIVE CROSS-CLOSURE COMMUNICATION PRESENTER.JS function nextSlide(){ var prez = $(this).parents('.presentation:first'); _ // ... _ _ current_slide.removeClass('current'); next_slide.addClass('current'); prez.trigger('slide:changed', { slide: next_slide }); }; THUMBNAIL-CONTROLS.JS $("body").delegate(".presentation", "slide:changed", transitionToSlide); REMOTE-VIEWER-CONTROLS.JS $("body").delegate(".presentation", "slide:changed", changeSlideOnRemoteViewers); Monday, March 28, 2011 50
  • 51. BENEFITS FUNCTIONS AND CLOSURES ALLOW GROUPING OF COMMON BEHAVIOR AND DATA CUSTOM EVENTS ARE AWESOME NO NEED TO HAVE REFERENCES TO EXTERNAL OBJECTS THROUGHOUT OUR APP LOOSER COUPLING EASIER TO HOOK IN NEW PARTS OF OUR APP WITH MINIMAL IMPACT TO EXISTING CODE Monday, March 28, 2011 51
  • 52. Monday, March 28, 2011 52
  • 53. EVENT-DRIVEN HOW WE GOT THERE MEANINGFUL DIRECTORY AND FILE NAMES FOLLOW MODULE OR SIMILAR CLOSURE-PATTERN GENERAL GUIDELINES FOR READABILITY: DECLARE PAGE CHECKS FIRST DECLARE HANDLERS AND VARS SECOND DECLARE FUNCTIONS LAST USE EVENTS TO DRIVE CROSS-CLOSURE COMMUNICATION Monday, March 28, 2011 53
  • 54. Monday, March 28, 2011 54
  • 55. IN SUMMARY INLINE JAVASCRIPT IS NOT A SUSTAINABLE APPROACH. UNOBTRUSIVE JAVASCRIPT IS A PATH TO “THE GREAT VALLEY” MONOLITHIC UJS WORKS FINE FOR SMALL APPS, BUT DOESN’T SCALE WELL. FORTUNATELY SELECTOR-DRIVEN JS IS EASIER TO MANIPULATE AND REORGANIZE. TRADITIONAL CLASS-BASED OO + UJS WORKS WELL, BUT CAN AT TIMES BE A BIT HEAVY FUNCTION/CLOSURES ARE A LIGHTER WEIGHT APPROACH THAN TRADITIONAL OO. FEELS MORE JAVASCRIPTY. EVENT-DRIVEN APPROACH WITH EMPHASIS ON FUNCTION/CLOSURES FOR SCOPE AND DECLARATIVE SELECTOR-DRIVEN CODE IS LEANER, SCALABLE AND PROMOTES LOOSE COOUPLING Monday, March 28, 2011 55