Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Event Oriented Architecture and Client side apps

Event Oriented Architecture and Client side apps

Mihael Konjević

November 16, 2012
Tweet

More Decks by Mihael Konjević

Other Decks in Programming

Transcript

  1. EOA and Client side
    applications
    Mihael Konjević - @mihaelkonjevic

    View Slide

  2. WHO AM I?
    • JavaScript developer at Bitovi
    • Development, training and consulting
    • JavaScriptMVC, CanJS, StealJS, jQuery++...
    http://javascriptmvc.com
    http://canjs.us
    http://jquerypp.com

    View Slide

  3. WHAT WE WANT?

    View Slide

  4. WHAT WE WANT?
    • Ease of development

    View Slide

  5. WHAT WE WANT?
    • Ease of development
    • Maintainability of code

    View Slide

  6. WHAT WE WANT?
    • Ease of development
    • Maintainability of code
    • Testability

    View Slide

  7. SRCHR APP

    View Slide

  8. WHAT WE’LL COVER

    View Slide

  9. WHAT WE’LL COVER
    • Modules and isolation

    View Slide

  10. WHAT WE’LL COVER
    • Modules and isolation
    • Directory structure

    View Slide

  11. WHAT WE’LL COVER
    • Modules and isolation
    • Directory structure
    • Application glue

    View Slide

  12. MODULES
    Perfect module is dumb, lonely and replaceable

    View Slide

  13. Modules should be
    Dumb

    View Slide

  14. Modules should be
    Lonely

    View Slide

  15. Modules should be
    Replaceable

    View Slide

  16. Application structure

    View Slide

  17. Search module
    • User can select services to search
    • User can enter the search term and trigger search

    View Slide

  18. History module
    • Keep track of searches
    • On click redo search
    • User can delete search

    View Slide

  19. Search Results
    • Perform search
    • List results

    View Slide

  20. Tabs
    • Clicking on the tabs shows search results for that service

    View Slide

  21. Events

    View Slide

  22. Events
    • DOM events

    View Slide

  23. Events
    • DOM events
    • Synthetic events on DOM elements

    View Slide

  24. Events
    • DOM events
    • Synthetic events on DOM elements
    • Synthetic events on JavaScript objects

    View Slide

  25. Search module
    • Triggers search event on the Search model
    $([Models.Search]).trigger("search",search);

    View Slide

  26. History module
    • Listens to search event on the search
    model
    • Triggers selected event on the clicked
    element
    "{Models.Search} search": function(el, ev, searchInst){
    ! if(this.history.indexOf(searchInst) === -1){
    ! ! this.history.push(searchInst)
    ! }
    },
    "li click" : function(el, ev){
    ! el.trigger("selected", el.data('search'))
    }

    View Slide

  27. Tabs module
    • Triggers activated event on clicked tab
    • Listens to activated event on clicked tab
    • Triggers show event on search results
    element
    this.tab(el.addClass('active')).show().trigger("show");
    "li click": function( el, ev ) {
    ! ev.preventDefault();
    ! el.trigger("activate");
    },
    "li activate": function( el, ev ) {
    ! this.activate(el);
    },

    View Slide

  28. Search Results module
    • Listens to show event on the element
    triggered by the tabs module
    • Listens to search event on the search
    model
    "{Models.Search} search": function(el, ev, searchInst){
    ! this.currentSearch = searchInst.query;
    ! ...
    },
    activate: function( el ) {
    ! this.tab(this.element.find('.active').removeClass('active')).hide();
    ! this.tab(el.addClass('active')).show().trigger("show");
    }

    View Slide

  29. What about disabled
    tabs?

    View Slide

  30. "li activate": function( el, ev ) {
    ! if(!el.hasClass('disabled')){
    ! ! this.activate(el);
    ! }
    }
    What about disabled
    tabs?

    View Slide

  31. Disabler module
    Disabler = can.Control({}, {
    ! "{Models.Search} search": function(el, ev, searchInst){
    ! ! var types = searchInst.attr('types');
    ! ! this.element.find('li').removeClass('disabled').map(function(i, el){
    ! ! ! var $el = $(el);
    ! ! ! if(types.indexOf($el.data('service')) === -1){
    ! ! ! ! $el.addClass('disabled');
    ! ! ! }
    ! ! });
    ! ! this.element.find('li:not(.disabled):first').trigger('activate')
    ! },
    ! "li activate" : function(el, ev){
    ! ! if(el.hasClass('disabled')){
    ! ! ! ev.stopImmediatePropagation();
    ! ! }
    ! }
    })

    View Slide

  32. Application workflow

    View Slide

  33. Events diagram

    View Slide

  34. • Keep your modules dumb, isolated and
    replaceable
    • Define inputs and outputs
    • Use events instead callbacks
    Summary

    View Slide

  35. The secret to building
    large apps is to never
    build large apps.

    View Slide

  36. button.js
    jquery.ui.calendar.js
    contactmanager.js
    tabs.js
    jquery.js
    nav.js
    resizer.js
    \test
    button_test.js
    contactmanager.js
    tabs_test.js
    nav_test.js

    View Slide

  37. \tabs
    tabs.js - the code for a tabs widget
    tabs.html - a demo page
    funcunit.html - a test page
    tabs_test.js - test code
    tabs.css - css for the tab

    View Slide

  38. Assembling the app
    • load dependencies
    • initialize the code
    \srchr
    \disabler
    \history
    \search
    \search_results
    search_results.js
    search_results.html
    search_results.css
    funcunit.html
    \tabs
    srchr.js
    srchr.html

    View Slide

  39. Gluing it together
    var searchController = new Search($("#searchArea"))
    new SearchResult($('#upcoming'), { modelType: Models.Upcoming,
    resultView: 'searchResultUpcomingEJS' })
    new SearchResult($('#twitter'), { modelType: Models.Twitter,
    resultView: 'searchResultTwitterEJS' })
    new Disabler($('#resultsTabs'))
    new Tabs($("#resultsTabs"))
    new History($('#history'))
    $('#history').bind("selected", function(ev, search){
    ! searchController.val(search)
    })

    View Slide

  40. Questions?

    View Slide