Refactoring to Unobtrusive Javascript

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    2 Favorites

    Refactoring to Unobtrusive Javascript - Presentation Transcript

    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
    51. Game Over Separation of concerns

    + Federico GalassiFederico Galassi, 2 months ago

    custom

    486 views, 2 favs, 3 embeds more stats

    Talk i gave at JsCamp09 on September 25th 2009.
    Sl more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 486
      • 343 on SlideShare
      • 143 from embeds
    • Comments 0
    • Favorites 2
    • Downloads 8
    Most viewed embeds
    • 122 views on http://federico.galassi.net
    • 20 views on http://www.javascriptcamp.com
    • 1 views on http://www.galassi.net

    more

    All embeds
    • 122 views on http://federico.galassi.net
    • 20 views on http://www.javascriptcamp.com
    • 1 views on http://www.galassi.net

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories