BVJS
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

BVJS

on

  • 4,461 views

 

Statistics

Views

Total Views
4,461
Views on SlideShare
4,038
Embed Views
423

Actions

Likes
9
Downloads
18
Comments
0

3 Embeds 423

http://coderwall.com 399
http://www.scoop.it 22
http://us-w1.rockmelt.com 2

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

BVJS Presentation Transcript

  • 1. Beyond the DOM: Sane Structure for JS Apps Rebecca Murphey • @rmurphey • BVJS 2012Wednesday, March 7, 12
  • 2. github.com/rmurphey/bvjsWednesday, March 7, 12
  • 3. function ObjInlineDown(e) { if( is.ie ) e = event if( is.ie && !is.ieMac && e.button!=1 && e.button!=2 ) return if( is.ieMac && e.button != 0 ) return if( is.ns && !is.ns4 && e.button!=0 && e.button!=2 ) return if( is.ns4 && e.which!=1 && e.which!=3 ) return this.onSelect() this.onDown() } function ObjInlineUp(e) { if( is.ie ) e = event if( is.ie && !is.ieMac && e.button!=1 && e.button!=2 ) return if( is.ieMac && e.button!=0 ) return if( is.ns && !is.ns4 && !is.nsMac && e.button!=0 && e.button!=2 ) return if( is.ns4 && e.which!=1 && e.which!=3 ) return if( ( !is.ns4 && e.button==2 ) || ( is.ns4 && e.which==3 ) ) { if( this.hasOnRUp ) { document.oncontextmenu = ocmNone this.onRUp() setTimeout( "document.oncontextmenu = ocmOrig", 100) } } else if( this.hasOnUp ) this.onUp() }Wednesday, March 7, 12
  • 4. Wednesday, March 7, 12
  • 5. Wednesday, March 7, 12
  • 6. <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Twitter Search</title> <link rel="stylesheet" href="/assets/css/index.css"> </head> <body> <h1>Twitter Search</h1> <div id="searchInput"> <form> <input placeholder="enter your search term"> <button>submit</button> </form> </div> <ul id="searchResults"></ul> <script src="/assets/js/libs/jquery.js"></script> <script src="/assets/js/app.js"></script> </body> </html>Wednesday, March 7, 12
  • 7. $(#searchInput form).submit(function(e){ e.preventDefault(); var term = $(#searchInput input).val(), req = $.getJSON(http://search.twitter.com/search.json?callback=?&q= + escape(term)); req.then(function(resp) { var resultsHtml = $.map(resp.results, function(r) { return <li> + <p class="tweet"> + r.text + </p> + <p class="username"> + r.from_user + </p> + </li>; }).join(); $(#searchResults).html(resultsHtml); }); });Wednesday, March 7, 12
  • 8. Wednesday, March 7, 12
  • 9. // NAVIGATION function togglePage(section) { // if the clicked section is already the current section AND were in full page mode // minimize the current tab if (jQuery(#md_tab_+ section).hasClass(current) && jQuery(#md_tab_+ section + a).hasClass(md_fullpage)) { // alert(clicked section is current section AND fullpage mode is active; teaser should load); // Minimize jQuery(#md_tabs_navigation a).removeClass(md_fullpage); jQuery(.md_body).hide(); jQuery(#md_feature).slideDown(normal,function(){ var bodyContent = jQuery(#md_body_+ section); bodyContent.fadeOut(normal,function(){ jQuery(#md_tabs_navigation a).each(function(){ var thisSection = jQuery(this).html().replace(<span<,).replace(</span<,); var thisSection_comp = thisSection.toLowerCase().replace( ,_); jQuery(#md_body_+ thisSection_comp).load( /app/modules/info/loadTeaser.php?sect=+ thisSection_comp, function(){ tb_init(.md_body a.thickbox, .md_body area.thickbox, .md_body input.thickbox); bodyContent.animate({ height: toggle, opacity: toggle },"slow"); } ); }); }); }); jQuery(#expandtabs span).empty().append(Expand Tabs); } else { // if the clicked section is NOT the current section OR were NOT in full page mode // then lets go to full page mode and show the whole tab // Maximize // alert(clicked section is not the current section OR full page mode is not active; full section should load); jQuery(#md_tabs_navigation li).removeClass(current); jQuery(#md_tab_+ section).addClass(current); jQuery(#md_tabs_navigation a).addClass(md_fullpage); jQuery(.md_body).hide(); jQuery(#md_feature).slideUp(normal,function(){ var bodyContent = jQuery(#md_body_+ section); bodyContent.fadeOut(normal,function(){ bodyContent.empty(); var pageLoader = info/loadSection.php?sect=+ section; if (section == contact_us) { pageLoader = contact/loadContactForm.php?form_id=1; } bodyContent.load(/app/modules/+ pageLoader,function(){ // ADD THICKBOXES tb_init(.md_body a.thickbox, .md_body area.thickbox, .md_body input.thickbox); $recent_news_links = jQuery(ul.md_news li a.recent_news_link); $recent_news_links .unbind(click) .each(function(){ var hrefMod = this.href; hrefMod = hrefMod.replace(/article/,loadNews).replace(/storyid/,id); this.href = hrefMod; }) .click(function(){ var t = this.title || this.name || null; var a = this.href || this.alt; var g = this.rel || false; tb_show(t,a,g); this.blur(); return false; });Wednesday, March 7, 12 // ACCORDION
  • 10. $(#btn-co-complete).live(click, function() { jobCompleted = true; $.mobile.changePage(#page-clockout-deficiency, {changeHash: false}); }); $(#btn-co-nocomplete).live(click, function() { jobCompleted = false; $.mobile.changePage(#page-clockout-deficiency, {changeHash: false}); }); $(#btn-co-nodef).live(click, function() { clockOut(activeJob, { completed:jobCompleted }, DW_JOB_COMPLETED); }); $(#btn-co-otherdef).live(click, function() { $.mobile.changePage(#page-clockout-redtag, {changeHash: false}); }); $(#btn-co-redtag).live(click, function() { clockOut(activeJob, { completed:jobCompleted, redTag:true }, DW_JOB_FOLLOWUP) }); $(#btn-co-noredtag).live(click, function() { $(#page-clockout-resolve).page(); $.mobile.changePage(#page-clockout-resolve, {changeHash: false}); }); $(#btn-clockout-resolve).live(click, function() { switch ($(#page-clockout-resolve :checked).val()) { case return:Wednesday, March 7, 12 clockOut(activeJob, { completed:false }, DW_JOB_RETURN);
  • 11. search input $(#searchInput form).submit(function(e){ e.preventDefault(); var term = $(#searchInput input).val(), req = $.getJSON(http://search.twitter.com/searc escape(term)); req.then(function(resp) { search data var resultsHtml = $.map(resp.results, function(r) return <li> + <p class="tweet"> + r.text + </p> + <p class="username"> + r.from_user + </p> </li>; }).join(); $(#searchResults).html(resultsHtml); search results }); });Wednesday, March 7, 12
  • 12. Wednesday, March 7, 12
  • 13. Wednesday, March 7, 12
  • 14. Wednesday, March 7, 12
  • 15. <script type="text/javascript" src="http://static.a2cdn.net/misc/jquery.js?9"></script> <script type="text/javascript" src="http://static.a2cdn.net/misc/drupal.js?9"></script> <script type="text/javascript" src="/google_analytics/googleanalytics.js?9"></script> <script type="text/javascript" src="/mollom/mollom.js?9"></script> <script type="text/javascript" src="/js/jquery-1.4.2.min.js?9"></script> <script type="text/javascript" src="/js/jquery-ui-1.8.4.custom.min.js?9"></script> <script type="text/javascript" src="/js/jquery.infieldlabel.min.js?9"></script> <script type="text/javascript" src="/js/jquery.nivo.slider.js?9"></script> <script type="text/javascript" src="/js/validations.js?9"></script> <script type="text/javascript" src="/js/site.js?9"></script> <script type="text/javascript" src="/js/noconflict.js?9"></script>Wednesday, March 7, 12
  • 16. <script data-main="app/config" src="/assets/js/libs/require.js"></script>Wednesday, March 7, 12
  • 17. require.config({ deps: ["main"], paths: { // JavaScript folders libs: "../assets/js/libs", plugins: "../assets/js/plugins", // Libraries jquery: "../assets/js/libs/jquery", underscore: "../assets/js/libs/underscore", backbone: "../assets/js/libs/backbone" } });Wednesday, March 7, 12
  • 18. define([ "components/page", "components/search/input", "components/search/results", ], function(Page, SearchInput, SearchResults) { return { // ... }; });Wednesday, March 7, 12
  • 19. // NAVIGATION function togglePage(section) { // if the clicked section is already the current section AND were in full page mode // minimize the current tab if (jQuery(#md_tab_+ section).hasClass(current) && jQuery(#md_tab_+ section + a).hasClass(md_fullpage)) { // alert(clicked section is current section AND fullpage mode is active; teaser should load); // Minimize jQuery(#md_tabs_navigation a).removeClass(md_fullpage); jQuery(.md_body).hide(); jQuery(#md_feature).slideDown(normal,function(){ var bodyContent = jQuery(#md_body_+ section); bodyContent.fadeOut(normal,function(){ jQuery(#md_tabs_navigation a).each(function(){ var thisSection = jQuery(this).html().replace(<span<,).replace(</span<,); var thisSection_comp = thisSection.toLowerCase().replace( ,_); jQuery(#md_body_+ thisSection_comp).load( /app/modules/info/loadTeaser.php?sect=+ thisSection_comp, function(){ tb_init(.md_body a.thickbox, .md_body area.thickbox, .md_body input.thickbox); bodyContent.animate({ height: toggle, opacity: toggle },"slow"); } ); }); }); }); jQuery(#expandtabs span).empty().append(Expand Tabs); } else { // if the clicked section is NOT the current section OR were NOT in full page mode // then lets go to full page mode and show the whole tab // Maximize // alert(clicked section is not the current section OR full page mode is not active; full section should load); jQuery(#md_tabs_navigation li).removeClass(current); jQuery(#md_tab_+ section).addClass(current); jQuery(#md_tabs_navigation a).addClass(md_fullpage); jQuery(.md_body).hide(); jQuery(#md_feature).slideUp(normal,function(){ var bodyContent = jQuery(#md_body_+ section); bodyContent.fadeOut(normal,function(){ bodyContent.empty(); var pageLoader = info/loadSection.php?sect=+ section; if (section == contact_us) { pageLoader = contact/loadContactForm.php?form_id=1; } bodyContent.load(/app/modules/+ pageLoader,function(){ // ADD THICKBOXES tb_init(.md_body a.thickbox, .md_body area.thickbox, .md_body input.thickbox); $recent_news_links = jQuery(ul.md_news li a.recent_news_link); $recent_news_links .unbind(click) .each(function(){ var hrefMod = this.href; hrefMod = hrefMod.replace(/article/,loadNews).replace(/storyid/,id); this.href = hrefMod; }) .click(function(){ var t = this.title || this.name || null; var a = this.href || this.alt; var g = this.rel || false; tb_show(t,a,g); this.blur(); return false; }); // ACCORDION jQuery(div.applemenu div.submenu).hide(); jQuery(div.applemenu div.silverheader < a).click(Wednesday, March 7, 12 function(){
  • 20. component controller component service components display data, observe input, and broadcast messages that controllers can react to; may also provide an API for updatingWednesday, March 7, 12
  • 21. component controller component service controllers set up components and broker communications between them, eliminating the need for direct communicationWednesday, March 7, 12
  • 22. component controller component service services expose an API for controllers to retrieve and persist dataWednesday, March 7, 12
  • 23. Wednesday, March 7, 12
  • 24. controller twitter searchWednesday, March 7, 12
  • 25. components display data, observe input, and broadcast messages that controllers can react to; may also provide an API for updatingWednesday, March 7, 12
  • 26. define([ "components/base" ], function(Component) { return Component({ template : "app/templates/search/input.html", className : search-input, events : { "submit form" : "_onSubmit" }, _onSubmit : function(e) { e.preventDefault(); var term = $.trim(this.$el.find(input)[0].value); if (!term) { return; } this.trigger(search, term); } }); });Wednesday, March 7, 12
  • 27. <form> <input placeholder="enter your search term"> <button>submit</button> </form>Wednesday, March 7, 12
  • 28. controllers set up components and broker communications between them, eliminating the need for direct communicationWednesday, March 7, 12
  • 29. <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Searchr</title> <!-- Application styles --> <link rel="stylesheet" href="/assets/css/index.css"> </head> <body> <!-- Main container --> <div role="main" id="main"></div> <!-- Application source --> <script data-main="app/config" src="/assets/js/libs/require.js"></ script> </body> </html>Wednesday, March 7, 12
  • 30. var Router = Backbone.Router.extend({ routes: { "": "twitter", ":hash": "twitter" }, twitter : function(hash) { SearchController.init(); } });Wednesday, March 7, 12
  • 31. define([ "components/page", "components/search/input", "components/search/results", "services/twitter" ], function(Page, SearchInput, SearchResults, twitterService) { return { init : function() { this.page = new Page({ template : app/templates/pages/search.html }); this.page.render().then(_.bind(this.setupPage, this)); }, setupPage : function() { var p = this.page; this.searchInput = p.place(new SearchInput(), searchInput); this.searchResults = p.place(new SearchResults(), searchResults); this.searchInput.on(search, _.bind(this.handleSearch, this)); }, handleSearch : function(term) { twitterService.query(term).then(_.bind(this.showResults, this)); }, showResults : function(results) { this.searchResults.show(results); } }; });Wednesday, March 7, 12
  • 32. services expose an API for controllers to interact with dataWednesday, March 7, 12
  • 33. define([ "use!backbone" ], function(Backbone) { var TwitterResult = Backbone.Model.extend({ // ... }); var TwitterResults = Backbone.Collection.extend({ type : twitter, model : TwitterResult }); return { query : function(term) { var req = $.getJSON(http://search.twitter.com/search.json?callback=?&q= + escape(term)), dfd = $.Deferred(); req.then(function(resp) { dfd.resolve(new TwitterResults(resp.results)); }); return dfd.promise(); } }; });Wednesday, March 7, 12
  • 34. “Writing to be read means writing code ... with the idea that someone else will read it. is fact alone will make you edit and think of better ways to solve the problem you have at hand.” Stoyan Stefanov, “JavaScript Patterns”Wednesday, March 7, 12
  • 35. github.com/rmurphey/bvjsWednesday, March 7, 12
  • 36. rmurphey.com • @rmurpheyWednesday, March 7, 12