SlideShare a Scribd company logo
1 of 36
Download to read offline
Beyond the DOM:
            Sane Structure for JS Apps
            Rebecca Murphey • @rmurphey • BVJS 2012

Wednesday, March 7, 12
github.com/rmurphey/bvjs




Wednesday, March 7, 12
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
Wednesday, March 7, 12
Wednesday, March 7, 12
<!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
$('#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
Wednesday, March 7, 12
// NAVIGATION
               function togglePage(section) {
                   // if the clicked section is already the current section AND we're 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 we're NOT in full page mode
                   // then let's 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
$('#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);
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
Wednesday, March 7, 12
Wednesday, March 7, 12
Wednesday, March 7, 12
<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
<script data-main="app/config" src="/assets/js/libs/require.js"></script>




Wednesday, March 7, 12
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
define([
                       "components/page",
                       "components/search/input",
                       "components/search/results",
                     ], function(Page, SearchInput, SearchResults) {
                       return {
                          // ...
                       };
                     });




Wednesday, March 7, 12
// NAVIGATION
               function togglePage(section) {
                   // if the clicked section is already the current section AND we're 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 we're NOT in full page mode
                   // then let's 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(){
component              controller


                         component




                                                 service



               components display data, observe input, and
               broadcast messages that controllers can react
               to; may also provide an API for updating


Wednesday, March 7, 12
component            controller


                         component




                                               service



               controllers set up components and broker
               communications between them, eliminating
               the need for direct communication


Wednesday, March 7, 12
component              controller


                         component




                                                 service




               services expose an API for controllers
               to retrieve and persist data


Wednesday, March 7, 12
Wednesday, March 7, 12
controller




                         twitter search




Wednesday, March 7, 12
components display data, observe input, and
               broadcast messages that controllers can react
               to; may also provide an API for updating




Wednesday, March 7, 12
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
<form>
                 <input placeholder="enter your search term">
                 <button>submit</button>
               </form>




Wednesday, March 7, 12
controllers set up components and broker
               communications between them, eliminating
               the need for direct communication




Wednesday, March 7, 12
<!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
var Router = Backbone.Router.extend({
                      routes: {
                         "": "twitter",
                         ":hash": "twitter"
                      },

                      twitter : function(hash) {
                        SearchController.init();
                      }
                    });




Wednesday, March 7, 12
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
services expose an API for controllers
               to interact with data




Wednesday, March 7, 12
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
“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
github.com/rmurphey/bvjs




Wednesday, March 7, 12
rmurphey.com • @rmurphey




Wednesday, March 7, 12

More Related Content

What's hot

Kick start with j query
Kick start with j queryKick start with j query
Kick start with j query
Md. Ziaul Haq
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
Inbal Geffen
 

What's hot (20)

jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace Pattern
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
Intro to Advanced JavaScript
Intro to Advanced JavaScriptIntro to Advanced JavaScript
Intro to Advanced JavaScript
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Kick start with j query
Kick start with j queryKick start with j query
Kick start with j query
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
jQuery
jQueryjQuery
jQuery
 
jQuery
jQueryjQuery
jQuery
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
 
Matters of State
Matters of StateMatters of State
Matters of State
 
JQuery
JQueryJQuery
JQuery
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 

Similar to BVJS

[removed] $file, removeRemove}, list #su.docx
[removed] $file, removeRemove}, list #su.docx[removed] $file, removeRemove}, list #su.docx
[removed] $file, removeRemove}, list #su.docx
gerardkortney
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
Jarod Ferguson
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
adamlogic
 

Similar to BVJS (20)

Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
[removed] $file, removeRemove}, list #su.docx
[removed] $file, removeRemove}, list #su.docx[removed] $file, removeRemove}, list #su.docx
[removed] $file, removeRemove}, list #su.docx
 
Introducing jQuery
Introducing jQueryIntroducing jQuery
Introducing jQuery
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applications
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page Applications
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
 
Unit – II (1).pptx
Unit – II (1).pptxUnit – II (1).pptx
Unit – II (1).pptx
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
 
jQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and Performance
 
course js day 3
course js day 3course js day 3
course js day 3
 
Backbone - TDC 2011 Floripa
Backbone - TDC 2011 FloripaBackbone - TDC 2011 Floripa
Backbone - TDC 2011 Floripa
 
JQuery Presentation
JQuery PresentationJQuery Presentation
JQuery Presentation
 
Jquery examples
Jquery examplesJquery examples
Jquery examples
 

More from Rebecca Murphey (7)

Getting Started with Mulberry
Getting Started with MulberryGetting Started with Mulberry
Getting Started with Mulberry
 
Introducing Mulberry
Introducing MulberryIntroducing Mulberry
Introducing Mulberry
 
DojoConf: Building Large Apps
DojoConf: Building Large AppsDojoConf: Building Large Apps
DojoConf: Building Large Apps
 
Lessons from-a-rewrite-gotham
Lessons from-a-rewrite-gothamLessons from-a-rewrite-gotham
Lessons from-a-rewrite-gotham
 
Lessons from a Rewrite
Lessons from a RewriteLessons from a Rewrite
Lessons from a Rewrite
 
Modern JavaScript
Modern JavaScriptModern JavaScript
Modern JavaScript
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 

BVJS

  • 1. Beyond the DOM: Sane Structure for JS Apps Rebecca Murphey • @rmurphey • BVJS 2012 Wednesday, 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
  • 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
  • 9. // NAVIGATION function togglePage(section) { // if the clicked section is already the current section AND we're 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 we're NOT in full page mode // then let's 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
  • 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
  • 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 we're 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 we're NOT in full page mode // then let's 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 updating Wednesday, March 7, 12
  • 21. component controller component service controllers set up components and broker communications between them, eliminating the need for direct communication Wednesday, March 7, 12
  • 22. component controller component service services expose an API for controllers to retrieve and persist data Wednesday, March 7, 12
  • 24. controller twitter search Wednesday, March 7, 12
  • 25. components display data, observe input, and broadcast messages that controllers can react to; may also provide an API for updating Wednesday, 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 communication Wednesday, 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 data Wednesday, 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