Event Oriented Architecture and Client side apps

Event Oriented Architecture and Client side apps

9976060bfb26220dd042340394d06b31?s=128

Mihael Konjević

November 16, 2012
Tweet

Transcript

  1. 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
  2. 17.

    Search module • User can select services to search •

    User can enter the search term and trigger search
  3. 18.

    History module • Keep track of searches • On click

    redo search • User can delete search
  4. 21.
  5. 24.

    Events • DOM events • Synthetic events on DOM elements

    • Synthetic events on JavaScript objects
  6. 25.

    Search module • Triggers search event on the Search model

    $([Models.Search]).trigger("search",search);
  7. 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')) }
  8. 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); },
  9. 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"); }
  10. 30.

    "li activate": function( el, ev ) { ! if(!el.hasClass('disabled')){ !

    ! this.activate(el); ! } } What about disabled tabs?
  11. 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(); ! ! } ! } })
  12. 34.

    • Keep your modules dumb, isolated and replaceable • Define

    inputs and outputs • Use events instead callbacks Summary
  13. 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
  14. 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
  15. 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) })