SlideShare ist ein Scribd-Unternehmen logo
1 von 51
Downloaden Sie, um offline zu lesen
Refactoring to
 Unobtrusive
  Javascript
         Federico Galassi
   federico.galassi@gmail.com
    http://federico.galassi.net/
Separation of Concerns



 Keeping different
    aspects of an
application separate
Separation of Concerns


So that everyone can
focus on one thing
      at a time
Unobtrusive Javascript

   Techniques to
enforce separation
 of javascript from
    other web
   technologies
Web Technologies


   Html                 Content

   Css                Presentation

Javascript         Presentation Logic

Server side          Business Logic
Rules of the Game


1 Javascript stays in its own files
2 Files are affected only by
changes directly related to
presentation logic
Game Strategy


How do we play?
Code refactoring
is improving quality of
existing code without
changing its functional
       behavior
Game Strategy



No refactoring
without testing

• unit testing with jsTestDriver & friends
• minimal functional testing with selenium & friends
• mock the server by wrapping XMLHttpRequest
1 Round

                        Html
                                   You see an
<script>
        doSomething();
        // ... more code ...
                                 inline script
</script>
1 Bad Smell

                        Html




<script>
        doSomething();



                                         Hey, it’s
        // ... more code ...
</script>




                                    javascript in
                                        html
1 Refactoring:
Externalize Inline Script
 Html                                       Js




             <script>
                     doSomething();
                     // ... more code ...
             </script>
1 Refactoring:
                     Externalize Inline Script
                        Html                                  Js




<script src="myjavascript.js">
                                       doSomething();
</script>
                                       // ... more code ...
2 Round

                      Html
                                  You see an
<button
 onclick="refreshView();"/>
                               event handler
                                registration
    Refresh
</button>




                                  by element
                                   attribute
2 Bad Smell

                      Html




<button
 onclick="refreshView();"/>



                                        Hey, it’s
    Refresh
</button>




                                   javascript in
                                       html
2 Refactoring:
              Attribute Event to Dom Event
                  Html                                     Js




<button
                              onclick="refreshView();"/>

    Refresh
</button>
2 Refactoring:
                  Attribute Event to Dom Event
                           Html                                 Js



   <!-- add id to locate it -->      var btnrefresh =
   <button id="btnRefresh">          document.getElementById(
       Refresh                           "btnRefresh"
   </button>                         );

                                     btnrefresh.addEventListener(
                                         "click",
                                         refreshView,
                                         false
                                     );


<!-- loaded after DOM is built -->
    <script src="myjavascript.js">
    </script>
</body>
</html>
3 Round

                         Html

                                         You see a
                                     javascript link
<a

href="javascript:showCredits();">

Show Credits</a>
3 Bad Smell

                         Html



<a

href="javascript:showCredits();">




                                              Hey, it’s
Show Credits</a>




                                         javascript in
                                             html
3 Refactoring:
                   Javascript Link to Click Event
                       Html                                     Js



<a

href="">                            javascript:showCredits();

Show Credits</a>
3 Refactoring:
                    Javascript Link to Click Event
                           Html                                 Js

                                     var showcredits =
 <!-- add id to locate it -->
                                     document.getElementById(
 <a id="linkShowCredits"
                                         "linkShowCredits"
 href="#">                           );

 Show Credits</a>
                                     // in refreshView you should
                                     // event.preventDefault
                                     showcredits.addEventListener(
                                         "click",
                                         refreshView,
                                         false
                                     );


<!-- loaded after DOM is built -->
    <script src="myjavascript.js">
    </script>
</body>
</html>
Game Break



Now HTML should
be Javascript free
4 Round

                               Js
                                          You see
div.onclick = function(e) {

    // div has been selected
                                     presentation
                                              set by
    var clicked = this;
    clicked.style.border =
        "1px solid blue";




                                     element.style
}




                                      properties
4 Bad Smell

                               Js



div.onclick = function(e) {

    // div has been selected



                                              Hey, it’s
    var clicked = this;
    clicked.style.border =
        "1px solid blue";




                                              css in
}




                                           javascript
4 Refactoring:
                  Dynamic Style to Css Class
                               Js                            Css



div.onclick = function(e) {

    // div has been selected
    var clicked = this;
                                    clicked.style.border =
                                        "1px solid blue";

}
4 Refactoring:
                  Dynamic Style to Css Class
                               Js                          Css



div.onclick = function(e) {

    // div has been selected
    var clicked = this;
                                    .selected: {
    // should be addClass
                                        border: 1px solid blue;
    clicked.setAttribute(
                                    }
        "class",
        "selected"
    );
}
5 Round

                              Js         You test a
var account = JSON.parse(
                                          complex
                                          boolean
    response
);
if (account.balance < 0) {




                                         expression
    show("can’t transfer money!");

}




                                        which is not
                                        presentation
5 Bad Smell

                                 Js



var account = JSON.parse(
    response
);




                                                 Hey, it’s
    if (account.balance < 0) {

      show("can’t transfer money!");

}



                                          business logic
                                           in javascript
5 Refactoring:
                     Business Logic Simple Test
                              Js                           Server



var account = JSON.parse(
    response
);
 if () {                             account.balance < 0

    show("can’t transfer money!");

}
5 Refactoring:
                     Business Logic Simple Test
                              Js                              Server



var account = JSON.parse(
    response
                                     <?php
);
                                        // use business logic to decide
 if (account.canTransfer) {             $account["canTransfer"] = false;
                                        echo json_encode($account);
    show("can’t transfer money!");   ?>

}
6 Round

                                     Js


// add book to the list
var book = doc.createElement("li");
                                              You see
                                             complex
var title = doc.createElement("strong");
titletext = doc.createTextNode(name);
title.appendChild(titletext);
var cover = doc.createElement("img");



                                           dom code to
cover.src = url;
book.appendChild(cover);
book.appendChild(title);
bookList.appendChild(book);



                                           generate html
6 Bad Smell

                                     Js


// add book to the list

var book = doc.createElement("li");
var title = doc.createElement("strong");
titletext = doc.createTextNode(name);



                                              Hey, it’s
title.appendChild(titletext);
var cover = doc.createElement("img");
cover.src = coverurl;
book.appendChild(cover);




                                              html in
book.appendChild(title);
bookList.appendChild(book);




                                           javascript
6 Refactoring:
                Dom Creation to Html Template
                          Js                                      Html


// add book to the list

                                 var book = doc.createElement("li");
                                 var title = doc.createElement("strong");
                                 titletext = doc.createTextNode(name);
                                 title.appendChild(titletext);
                                 var cover = doc.createElement("img");
                                 cover.src = coverurl;
                                 book.appendChild(cover);
                                 book.appendChild(title);
                                 bookList.appendChild(book);
6 Refactoring:
                 Dom Creation to Html Template
                                  Js                                Html


// add book to the list

var tplBook = loadTemplate(
    "book_tpl.html"
                                       <li>
);
                                           <strong>Title</strong>
var book = tplBook.substitute({
                                           <img src="Cover" />
    Title: name,
                                       </li>
    Cover: coverurl
});
bookList.appendChild(book);
Game Extra Time



Make javascript
 play well with
other javascript
7 Round

                       Js
var counter = 0;
// ... more code ...




                              You see code
                             placed outside
                               a function
7 Bad Smell

                         Js
var counter = 0;
// ... more code ...



// ... later ...
// counter is 1




                                     Hey, it’s a
                   Other Js
// redeclares previous
// counter !!



                                  global variable
var counter = 1;
7 Refactoring:
                         Global Abatement
                         Js
var counter = 0;
// ... more code ...



// ... later ...
// counter is 1
                                Using the
                              Module pattern
                   Other Js
// redeclares previous
                              we can make it
                                 private
// counter !!
var counter = 1;
7 Refactoring:
                            Global Abatement


                                  Wrap code in
(function() {
                            Js
    var counter = 0;
    // ... more code ...



    // ... later ...
    // counter is still 0
 })();
                                 an anonymous
                     Other Js    function which
                                  is immediately
    // don’t see previous
    // counter
    var counter = 1;




                                       invoked
8 Round
                        Login Js
btnLogin.onclick = function(e){
    login();
    toolbar.update();
    logger.log("login!");
                                      You see an
                                   event handler
}




function update() {
    // ...
                      Toolbar Js
                                     which calls
                                   many unrelated
}




                       Logger Js
function log(msg) {

}
    // ...
                                       modules
8 Bad Smell
                        Login Js
btnLogin.onclick = function(e){
    login();
    toolbar.update();
    logger.log("login!");
}




                      Toolbar Js
function update() {



                                         Hey, it’s
    // ...
}




function log(msg) {
                       Logger Js
                                      other modules
                                        javascript
    // ...
}
8 Impact
                        Login Js
btnLogin.onclick = function(e){
    login();
    toolbar.update();
    logger.log("login!");
}


     FAIL
                      Toolbar Js
function update() {



                                    Time coupling
    // ...
}




function log(msg) {
                       Logger Js
                                              issues
  t initialized
    // ...


No
}
8 Impact
                        Login Js
btnLogin.onclick = function(e){
    login();
    toolbar.update();
    logger.log("login!");



       hange
    friends.notify("login");



  eds C
}


Ne
                      Toolbar Js
function update() {
    // ...                        Friends   Js


                                                 Divergent
}
             function notify(event) {
                 // ...


                            dded
             }

                           A
                       Logger Js
function log(msg) {

}
    // ...
                                                  change
8 Refactoring:
                                       Custom Events
                            Login Js


                                          Custom events
btnLogin.onclick = function(e){
    login();




                                              invert
}




function update() {
    toolbar.update();
                        Toolbar Js
                                           dependency
                                            and make
}




                                          code readable
                         Logger Js
function log(msg) {
    logger.log("login!");
}
8 Refactoring:
                                      Custom Events
                           Login Js
 btnLogin.onclick = function(e){
     login();
     event.fire("login");                   Fire an high
                                         level custom
 }




                     Toolbar Js
function update() {...}
event.listen("login", function(e) {
    update();
                                        event and make
                                        other modules
});



                          Logger Js


                                           listen to it
function log(msg) {...}
event.listen("login", function(e) {
    log("login attempt");
});
9 Round

                               Js


// home getElementById "tabHome"
// news getElementById "tabNews"
// about getElementById "tabAbout"
                                       You see many
home.onclick = function() {

}
    showPage("pageHome");

news.onclick = function() {
                                      similar event
                                        handlers
    showPage("pageNews");
}
about.onclick = function() {
    showPage("pageAbout");
}
9 Bad Smell

                               Js


// home getElementById "tabHome"
// news getElementById "tabNews"
// about getElementById "tabAbout"

home.onclick = function() {
    showPage("pageHome");
}



                                               Hey, it’s
news.onclick = function() {
    showPage("pageNews");
}
about.onclick = function() {




                                            duplicated
    showPage("pageAbout");
}




                                            javascript
9 Impact

                                  Js


 // home getElementById "tabHome"
 // news getElementById "tabNews"
 // about getElementById "tabAbout"

 home.onclick = function() {

 }
     showPage("pageHome");                More tabs
                                          more code
 news.onclick = function() {
     showPage("pageNews");
 }
 about.onclick = function() {




                                         more handlers
     showPage("pageAbout");
 }
 contact.onclick = function() {
     showPage("pageContact");
 }



Needs Change                             more memory
                                            usage
9 Impact

                               Js


// home getElementById "tabHome"




                                       Need to track
// news getElementById "tabNews"
// about getElementById "tabAbout"

home.onclick = function() {
    showPage("pageHome");




                                     if new elements
}
news.onclick = function() {
    showPage("pageNews");
}
about.onclick = function() {



                                        are added to
    showPage("pageAbout");
}




                    Contact Js
tabContainer.addChild(
    "tabContact"
                                     register handlers
);


Missing click handler
9 Refactoring:
                               Events Delegation
                               Js
                                     Event delegation
                                       makes code
// home getElementById "tabHome"
// news getElementById "tabNews"
// about getElementById "tabAbout"

home.onclick = function() {



                                     more compact
    showPage("pageHome");
}
news.onclick = function() {
    showPage("pageNews");
}



                                           and
about.onclick = function() {
    showPage("pageAbout");
}




                                      maintainable
9 Refactoring:
                              Events Delegation


                                    Handle the event
                              Js




                                    in an elements
// container getElementById
// "tabContainer"

container.onclick = function(e) {




                                       ancestor.
    var id = e.target.id
    var page = id.replace(
        "tab", "page"
    );
    showPage(page);




                                    Bubbling makes
}




                                         it work
Game Over

Separation of concerns

Weitere ähnliche Inhalte

Mehr von Federico Galassi

Mehr von Federico Galassi (8)

CouchApps: Requiem for Accidental Complexity
CouchApps: Requiem for Accidental ComplexityCouchApps: Requiem for Accidental Complexity
CouchApps: Requiem for Accidental Complexity
 
Please Don't Touch the Slow Parts V3
Please Don't Touch the Slow Parts V3Please Don't Touch the Slow Parts V3
Please Don't Touch the Slow Parts V3
 
Javascript the New Parts
Javascript the New PartsJavascript the New Parts
Javascript the New Parts
 
Event Driven Javascript
Event Driven JavascriptEvent Driven Javascript
Event Driven Javascript
 
Please Don't Touch the Slow Parts V2
Please Don't Touch the Slow Parts V2Please Don't Touch the Slow Parts V2
Please Don't Touch the Slow Parts V2
 
Please Don't Touch the Slow Parts
Please Don't Touch the Slow PartsPlease Don't Touch the Slow Parts
Please Don't Touch the Slow Parts
 
Javascript The Good Parts v2
Javascript The Good Parts v2Javascript The Good Parts v2
Javascript The Good Parts v2
 
Javascript The Good Parts
Javascript The Good PartsJavascript The Good Parts
Javascript The Good Parts
 

Kürzlich hochgeladen

Kürzlich hochgeladen (20)

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...
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
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
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 

Refactoring to Unobtrusive Javascript

  • 1. Refactoring to Unobtrusive Javascript Federico Galassi federico.galassi@gmail.com http://federico.galassi.net/
  • 2. Separation of Concerns Keeping different aspects of an application separate
  • 3. Separation of Concerns So that everyone can focus on one thing at a time
  • 4. Unobtrusive Javascript Techniques to enforce separation of javascript from other web technologies
  • 5. Web Technologies Html Content Css Presentation Javascript Presentation Logic Server side Business Logic
  • 6. Rules of the Game 1 Javascript stays in its own files 2 Files are affected only by changes directly related to presentation logic
  • 7. Game Strategy How do we play? Code refactoring is improving quality of existing code without changing its functional behavior
  • 8. Game Strategy No refactoring without testing • unit testing with jsTestDriver & friends • minimal functional testing with selenium & friends • mock the server by wrapping XMLHttpRequest
  • 9. 1 Round Html You see an <script> doSomething(); // ... more code ... inline script </script>
  • 10. 1 Bad Smell Html <script> doSomething(); Hey, it’s // ... more code ... </script> javascript in html
  • 11. 1 Refactoring: Externalize Inline Script Html Js <script> doSomething(); // ... more code ... </script>
  • 12. 1 Refactoring: Externalize Inline Script Html Js <script src="myjavascript.js"> doSomething(); </script> // ... more code ...
  • 13. 2 Round Html You see an <button onclick="refreshView();"/> event handler registration Refresh </button> by element attribute
  • 14. 2 Bad Smell Html <button onclick="refreshView();"/> Hey, it’s Refresh </button> javascript in html
  • 15. 2 Refactoring: Attribute Event to Dom Event Html Js <button onclick="refreshView();"/> Refresh </button>
  • 16. 2 Refactoring: Attribute Event to Dom Event Html Js <!-- add id to locate it --> var btnrefresh = <button id="btnRefresh"> document.getElementById( Refresh "btnRefresh" </button> ); btnrefresh.addEventListener( "click", refreshView, false ); <!-- loaded after DOM is built --> <script src="myjavascript.js"> </script> </body> </html>
  • 17. 3 Round Html You see a javascript link <a href="javascript:showCredits();"> Show Credits</a>
  • 18. 3 Bad Smell Html <a href="javascript:showCredits();"> Hey, it’s Show Credits</a> javascript in html
  • 19. 3 Refactoring: Javascript Link to Click Event Html Js <a href=""> javascript:showCredits(); Show Credits</a>
  • 20. 3 Refactoring: Javascript Link to Click Event Html Js var showcredits = <!-- add id to locate it --> document.getElementById( <a id="linkShowCredits" "linkShowCredits" href="#"> ); Show Credits</a> // in refreshView you should // event.preventDefault showcredits.addEventListener( "click", refreshView, false ); <!-- loaded after DOM is built --> <script src="myjavascript.js"> </script> </body> </html>
  • 21. Game Break Now HTML should be Javascript free
  • 22. 4 Round Js You see div.onclick = function(e) { // div has been selected presentation set by var clicked = this; clicked.style.border = "1px solid blue"; element.style } properties
  • 23. 4 Bad Smell Js div.onclick = function(e) { // div has been selected Hey, it’s var clicked = this; clicked.style.border = "1px solid blue"; css in } javascript
  • 24. 4 Refactoring: Dynamic Style to Css Class Js Css div.onclick = function(e) { // div has been selected var clicked = this; clicked.style.border = "1px solid blue"; }
  • 25. 4 Refactoring: Dynamic Style to Css Class Js Css div.onclick = function(e) { // div has been selected var clicked = this; .selected: { // should be addClass border: 1px solid blue; clicked.setAttribute( } "class", "selected" ); }
  • 26. 5 Round Js You test a var account = JSON.parse( complex boolean response ); if (account.balance < 0) { expression show("can’t transfer money!"); } which is not presentation
  • 27. 5 Bad Smell Js var account = JSON.parse( response ); Hey, it’s if (account.balance < 0) { show("can’t transfer money!"); } business logic in javascript
  • 28. 5 Refactoring: Business Logic Simple Test Js Server var account = JSON.parse( response ); if () { account.balance < 0 show("can’t transfer money!"); }
  • 29. 5 Refactoring: Business Logic Simple Test Js Server var account = JSON.parse( response <?php ); // use business logic to decide if (account.canTransfer) { $account["canTransfer"] = false; echo json_encode($account); show("can’t transfer money!"); ?> }
  • 30. 6 Round Js // add book to the list var book = doc.createElement("li"); You see complex var title = doc.createElement("strong"); titletext = doc.createTextNode(name); title.appendChild(titletext); var cover = doc.createElement("img"); dom code to cover.src = url; book.appendChild(cover); book.appendChild(title); bookList.appendChild(book); generate html
  • 31. 6 Bad Smell Js // add book to the list var book = doc.createElement("li"); var title = doc.createElement("strong"); titletext = doc.createTextNode(name); Hey, it’s title.appendChild(titletext); var cover = doc.createElement("img"); cover.src = coverurl; book.appendChild(cover); html in book.appendChild(title); bookList.appendChild(book); javascript
  • 32. 6 Refactoring: Dom Creation to Html Template Js Html // add book to the list var book = doc.createElement("li"); var title = doc.createElement("strong"); titletext = doc.createTextNode(name); title.appendChild(titletext); var cover = doc.createElement("img"); cover.src = coverurl; book.appendChild(cover); book.appendChild(title); bookList.appendChild(book);
  • 33. 6 Refactoring: Dom Creation to Html Template Js Html // add book to the list var tplBook = loadTemplate( "book_tpl.html" <li> ); <strong>Title</strong> var book = tplBook.substitute({ <img src="Cover" /> Title: name, </li> Cover: coverurl }); bookList.appendChild(book);
  • 34. Game Extra Time Make javascript play well with other javascript
  • 35. 7 Round Js var counter = 0; // ... more code ... You see code placed outside a function
  • 36. 7 Bad Smell Js var counter = 0; // ... more code ... // ... later ... // counter is 1 Hey, it’s a Other Js // redeclares previous // counter !! global variable var counter = 1;
  • 37. 7 Refactoring: Global Abatement Js var counter = 0; // ... more code ... // ... later ... // counter is 1 Using the Module pattern Other Js // redeclares previous we can make it private // counter !! var counter = 1;
  • 38. 7 Refactoring: Global Abatement Wrap code in (function() { Js var counter = 0; // ... more code ... // ... later ... // counter is still 0 })(); an anonymous Other Js function which is immediately // don’t see previous // counter var counter = 1; invoked
  • 39. 8 Round Login Js btnLogin.onclick = function(e){ login(); toolbar.update(); logger.log("login!"); You see an event handler } function update() { // ... Toolbar Js which calls many unrelated } Logger Js function log(msg) { } // ... modules
  • 40. 8 Bad Smell Login Js btnLogin.onclick = function(e){ login(); toolbar.update(); logger.log("login!"); } Toolbar Js function update() { Hey, it’s // ... } function log(msg) { Logger Js other modules javascript // ... }
  • 41. 8 Impact Login Js btnLogin.onclick = function(e){ login(); toolbar.update(); logger.log("login!"); } FAIL Toolbar Js function update() { Time coupling // ... } function log(msg) { Logger Js issues t initialized // ... No }
  • 42. 8 Impact Login Js btnLogin.onclick = function(e){ login(); toolbar.update(); logger.log("login!"); hange friends.notify("login"); eds C } Ne Toolbar Js function update() { // ... Friends Js Divergent } function notify(event) { // ... dded } A Logger Js function log(msg) { } // ... change
  • 43. 8 Refactoring: Custom Events Login Js Custom events btnLogin.onclick = function(e){ login(); invert } function update() { toolbar.update(); Toolbar Js dependency and make } code readable Logger Js function log(msg) { logger.log("login!"); }
  • 44. 8 Refactoring: Custom Events Login Js btnLogin.onclick = function(e){ login(); event.fire("login"); Fire an high level custom } Toolbar Js function update() {...} event.listen("login", function(e) { update(); event and make other modules }); Logger Js listen to it function log(msg) {...} event.listen("login", function(e) { log("login attempt"); });
  • 45. 9 Round Js // home getElementById "tabHome" // news getElementById "tabNews" // about getElementById "tabAbout" You see many home.onclick = function() { } showPage("pageHome"); news.onclick = function() { similar event handlers showPage("pageNews"); } about.onclick = function() { showPage("pageAbout"); }
  • 46. 9 Bad Smell Js // home getElementById "tabHome" // news getElementById "tabNews" // about getElementById "tabAbout" home.onclick = function() { showPage("pageHome"); } Hey, it’s news.onclick = function() { showPage("pageNews"); } about.onclick = function() { duplicated showPage("pageAbout"); } javascript
  • 47. 9 Impact Js // home getElementById "tabHome" // news getElementById "tabNews" // about getElementById "tabAbout" home.onclick = function() { } showPage("pageHome"); More tabs more code news.onclick = function() { showPage("pageNews"); } about.onclick = function() { more handlers showPage("pageAbout"); } contact.onclick = function() { showPage("pageContact"); } Needs Change more memory usage
  • 48. 9 Impact Js // home getElementById "tabHome" Need to track // news getElementById "tabNews" // about getElementById "tabAbout" home.onclick = function() { showPage("pageHome"); if new elements } news.onclick = function() { showPage("pageNews"); } about.onclick = function() { are added to showPage("pageAbout"); } Contact Js tabContainer.addChild( "tabContact" register handlers ); Missing click handler
  • 49. 9 Refactoring: Events Delegation Js Event delegation makes code // home getElementById "tabHome" // news getElementById "tabNews" // about getElementById "tabAbout" home.onclick = function() { more compact showPage("pageHome"); } news.onclick = function() { showPage("pageNews"); } and about.onclick = function() { showPage("pageAbout"); } maintainable
  • 50. 9 Refactoring: Events Delegation Handle the event Js in an elements // container getElementById // "tabContainer" container.onclick = function(e) { ancestor. var id = e.target.id var page = id.replace( "tab", "page" ); showPage(page); Bubbling makes } it work