SlideShare a Scribd company logo
1 of 55
Download to read offline
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

Viewers also liked (10)

Recognize Patterns of Organization
Recognize Patterns of Organization Recognize Patterns of Organization
Recognize Patterns of Organization
 
Patterns of organization-2
Patterns of organization-2Patterns of organization-2
Patterns of organization-2
 
Recognizing patterns of organization
Recognizing patterns of organizationRecognizing patterns of organization
Recognizing patterns of organization
 
pattern of organization
pattern of organizationpattern of organization
pattern of organization
 
5 Organizational Patterns In Paragraphs
5 Organizational Patterns In Paragraphs5 Organizational Patterns In Paragraphs
5 Organizational Patterns In Paragraphs
 
Pattern of Paragraph Development
Pattern of Paragraph DevelopmentPattern of Paragraph Development
Pattern of Paragraph Development
 
Pattern of organization
Pattern of organizationPattern of organization
Pattern of organization
 
4. patterns of organization
4. patterns of organization4. patterns of organization
4. patterns of organization
 
Methods of paragraph development
Methods of paragraph developmentMethods of paragraph development
Methods of paragraph development
 
Methods of Paragraph Development
Methods of Paragraph DevelopmentMethods of Paragraph Development
Methods of Paragraph Development
 

Similar to JavaScript Code Organizations, Patterns Slides - Zach Dennis

Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
Tools for Development and Debugging in Python
Tools for Development and Debugging in PythonTools for Development and Debugging in Python
Tools for Development and Debugging in Python
zeeg
 
Mike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to youMike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to you
StarTech Conference
 
jQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionjQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & Compression
Paul Irish
 
YUI3 Modules
YUI3 ModulesYUI3 Modules
YUI3 Modules
a_pipkin
 
Kick start with j query
Kick start with j queryKick start with j query
Kick start with j query
Md. Ziaul Haq
 

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

Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)
 
Creating an inclusive workplace with JS
Creating an inclusive workplace with JSCreating an inclusive workplace with JS
Creating an inclusive workplace with JS
 
Tools for Development and Debugging in Python
Tools for Development and Debugging in PythonTools for Development and Debugging in Python
Tools for Development and Debugging in Python
 
Mike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to youMike hostetler - jQuery knowledge append to you
Mike hostetler - jQuery knowledge append to you
 
A Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NETA Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NET
 
A Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETA 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
How to increase Performance of Web Application using JQueryHow to increase Performance of Web Application using JQuery
How to increase Performance of Web Application using JQuery
 
Gearman, from the worker's perspective
Gearman, from the worker's perspectiveGearman, from the worker's perspective
Gearman, from the worker's perspective
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
J query training
J query trainingJ query training
J query training
 
Building mobile web apps with Mobello
Building mobile web apps with MobelloBuilding mobile web apps with Mobello
Building mobile web apps with Mobello
 
jQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionjQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & Compression
 
JavaFX Pitfalls
JavaFX PitfallsJavaFX Pitfalls
JavaFX Pitfalls
 
YUI3 Modules
YUI3 ModulesYUI3 Modules
YUI3 Modules
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Jquery examples
Jquery examplesJquery examples
Jquery examples
 
How te bring common UI patterns to ADF
How te bring common UI patterns to ADFHow te bring common UI patterns to ADF
How te bring common UI patterns to ADF
 
Kick start with j query
Kick start with j queryKick start with j query
Kick start with j query
 
jQuery Rescue Adventure
jQuery Rescue AdventurejQuery Rescue Adventure
jQuery Rescue Adventure
 

More from Zach Dennis

More from Zach Dennis (6)

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

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Recently uploaded (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 

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