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. 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. Search module • User can select services to search •

    User can enter the search term and trigger search
  3. History module • Keep track of searches • On click

    redo search • User can delete search
  4. Events • DOM events • Synthetic events on DOM elements

    • Synthetic events on JavaScript objects
  5. Search module • Triggers search event on the Search model

    $([Models.Search]).trigger("search",search);
  6. 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')) }
  7. 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); },
  8. 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"); }
  9. "li activate": function( el, ev ) { ! if(!el.hasClass('disabled')){ !

    ! this.activate(el); ! } } What about disabled tabs?
  10. 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(); ! ! } ! } })
  11. • Keep your modules dumb, isolated and replaceable • Define

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