SlideShare a Scribd company logo
Organizing Code with
                              JavaScriptMVC
                       git clone git://github.com/tdreyno/jquery-demo.git



                                      Thomas Reynolds




Sunday, October 17, 2010
Who am I?



Sunday, October 17, 2010
Who am I?
                • JavascriptMVC Core Committer

                • jQuery Plugin Developer

                • @tdreyno

                • github.com/tdreyno

                • awardwinningfjords.com


Sunday, October 17, 2010
Sunday, October 17, 2010
Sunday, October 17, 2010
Getting to Know You



Sunday, October 17, 2010
Getting to Know You

                • Traditional Website Developers

                • Web Application Developers

                • Mobile Web Developers




Sunday, October 17, 2010
Organizing Code



Sunday, October 17, 2010
Common Problems



Sunday, October 17, 2010
One BIG File



Sunday, October 17, 2010
$(function(){

                             // make external links open in new window
                             $('a[rel="external"]').attr('target','_blank');

                             if ($("body").attr('id') == 'homepage'){
                               bindHomepage();
                             } else if ($("body").hasClass('lessons_index') || $("body").hasClass('lessons_list')) {
                               bindLessonsList();
                             } else if ($("body").hasClass('documents_detail')) {
                               if (weird === 0){
                                 showDetail();
                               }
                               weird++;
                             } else if ($("body").hasClass('lessons_detail')) {
                               if (weird === 0){
                                 showDetail();
                               }
                               weird++;

                               // look for requests to launch the activity editor
                               var edit_matches = window.location.search.match(/[?&]edit_activity=(d+)&type=([^=?&]+)/)
                               if (edit_matches) {
                                 var edit_activity_id = edit_matches[1];
                                 var edit_activity_type = edit_matches[2];
                                 launchCreatorModal({
                                   id: edit_activity_id,
                                   type: edit_activity_type,
                                   mode: 'edit'
                                 });
                               }

                             } else if ($("body").attr('id')=='my_classroom'){
                                 bindMyClassroom();
                             } else if ($("body").hasClass('templates_index')){
                                 bindTemplates();
                             }

                             bindCreatorLinks();

                             // This can cause an error in Chrome, but the problem is already patched (03/2010)
                             // and awaiting a release.
                             window.onbeforeunload = handleOnBeforeUnload;
                             window.onunload = handleOnUnload;

                             if (window.location.search.match(/[?&]from_activity=1/)) {
                               $('#back_to_activity a').pulse();
                             }

                             bindSearchToggle();

                             // Load the "Star This" code
                             // Should be inlined using something like Sprockets in the future
                             $.getScript("/js/stars-and-add-to-buttons.js");

                             // Handle resources page toggles
                             $("p.more a.morelink, ul.more a.morelink, a.arrow").click(function(e) {
                               e.preventDefault();
                               var parentElem = $(this).parents(".openRow, .closedRow");
                               parentElem[0].className = parentElem.is(".openRow") ? "closedRow" : "openRow";
                             });

                             if (document.location.hash.length) {
                               $("a[name=" + document.location.hash.replace(/#/, "") + "]").parents(".closedRow").find(".arrow").click();
Sunday, October 17, 2010     }
One BIG File

                • 800+ Lines

                • Difficult to read

                • No Documentation

                • No Test Cases

                • Not DRY


Sunday, October 17, 2010
The Solution?

                     Break into Maintainable
                        Chunks of Code



Sunday, October 17, 2010
Problems with
                            Multiple Files
                • Does everything go into one folder?

                • What if something is needed in two different
                  places?

                • Communication

                • Loading speed

                • Loading order


Sunday, October 17, 2010
JavascriptMVC Provides

                           Dependency
                           Management



Sunday, October 17, 2010
StealJS
                • Asynchronously Loading

                • Provides a structure for organizing files

                • Cleans, Combines & Compresses

                • Bundles Presentational CSS

                • Supports CoffeeScript & Less.js


Sunday, October 17, 2010
StealJS Example
                            steal.plugins("jquery/controller",
                                           "jquery/event/drag",
                                           "jquery/dom/within")
                            .then(function($) {
                               // Configure JavascriptMVC plugins
                            })
                            .resources("jquerytools.tabs",
                                        "jquery.ui.position",
                                        "jquerytools.scrollable")
                            .then(function($) {
                               // Configure jQuery plugins
                            })
                            .controllers("tile",
                                          "large_zoom",
                                          "medium_zoom",
                                          "small_zoom",
                                          "control",
                                          "image")
                            .then(function($) {
                             // All dependencies are satisfied
                            })


Sunday, October 17, 2010
Plugin
                    • Basic unit of organization
                    • Simply, a folder.
                    • Initialized by a .js file named the same as
                           the app.
                           • For example: my_plugin/my_plugin.js
                    • Can include other plugins
Sunday, October 17, 2010
Resources
                • A folder named “resources/” in your plugin

                • Contains raw Javascript files, often a jQuery plugin

                     • jQuery UI

                     • jQuery Tools

                     • Modernizr

                     • Et cetera



Sunday, October 17, 2010
Controller

                • Could be called several things:

                     • View Controller

                     • Widget

                     • $.fn on Steroids




Sunday, October 17, 2010
Controller
                • Controls a DOM element

                     • Uses templates to create & manipulate
                       the DOM

                • Manages state

                • Uses PubSub (OpenAjax) to communicate

                • Responds to events


Sunday, October 17, 2010
Example Site




Sunday, October 17, 2010
Example Site




Sunday, October 17, 2010
Example Site




Sunday, October 17, 2010
Example Site
                •          Homepage
                    •       A slideshow
                    •       Tabs
                    •       Custom Autocomplete Search
                •          Contact Page
                    •       Form with Validator
                    •       “Success” lightbox
                    •       Custom Autocomplete Search


Sunday, October 17, 2010
Getting Started
                     • Download zip file from GitHub
                           • http://github.com/jupiterjs/framework/
                             downloads
                           • Unzip
                     • Install gem
                           • gem install javascriptmvc --pre
                           • jmvc-init jqconf-demo


Sunday, October 17, 2010
Fresh JavascriptMVC
                         Application




Sunday, October 17, 2010
Homepage “App”




Sunday, October 17, 2010
Homepage HTML
                           <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
                                       "http://www.w3.org/TR/html4/strict.dtd">
                           <html lang="en">
                             <head>
                               <title>homepage</title>
                             </head>
                             <body>
                               <h1>Thanks for stealing StealJS!</h1>
                               <p>Don't worry, it's open source. It's only
                           stealing if you don't do something awesome with it.</p>
                               <div id='content'></div>

                               <script type='text/javascript'
                                        src='../steal/steal.js?homepage'></script>
                             </body>
                           </html>




Sunday, October 17, 2010
Homepage Javascript
                 steal( 'resources/example' )   // Loads 'resources/example.js'
                   .css( 'homepage' )           // Loads 'homepage.css'
                   .plugins(
                     'steal/less',
                     'steal/coffee' )           // Loads 'steal/less/less.js' and
                                                // 'steal/coffee/coffee.js'

                    .then(function(){           // Adds a function to be called back
                                                // once all prior files have been
                                                // loaded and run
                      steal.coffee('resources/example') // Loads 'resources/example.coffee'
                             .less('resources/example'); // Loads 'resources/example.less'
                    });




Sunday, October 17, 2010
Resources
                           (jQuery Plugins)




Sunday, October 17, 2010
homepage/homepage.js
                           steal.plugins("jquery")
                                .resources("slider", "tabs")
                                .then(function($) {

                           $(document).ready(function() {
                             $("#slider").slider();
                             $("#tabs").tabs();
                           });

                           });




Sunday, October 17, 2010
Sunday, October 17, 2010
Contact Page “App”




Sunday, October 17, 2010
Contact Page
                           steal.plugins("jquery")
                                .resources("validator", "lightbox")
                                .then(function() {

                           $("form").validator();

                           $("form").submit(function() {
                             $.lightbox();
                           });

                           });




Sunday, October 17, 2010
Autocomplete Search
                        (Plugin)



Sunday, October 17, 2010
TR.SearchControl
                                Plugin




Sunday, October 17, 2010
But Wait!?



Sunday, October 17, 2010
FuncUnit
                • Test-Driven Development:

                     • Results well thought-out code

                     • Inspires trust in your users

                     • Documents logic

                     • Provides an automated means of making
                       sure everything still works


Sunday, October 17, 2010
TR.SearchControl
                               FuncUnit
                             module("TR.SearchControl", {
                                setup: function() {
                                  $("form#search").tr_search_control();
                                }
                             })

                             test("Autocomplete", function(){
                                // Type into text box
                                // Extra results should appear
                             })

                             test("Submit", function(){
                                // Clicking submit or hitting enter
                                // Should submit the form
                             })




Sunday, October 17, 2010
TR.SearchControl
                               FuncUnit




Sunday, October 17, 2010
Search Controller
                            steal.plugins("jquery/controller")
                                 .resources("autocomplete")
                                 .then(function($) {

                            $.Controller.extend("TR.SearchControl", { }, {
                              init: function() {
                                 this.element.autocomplete();
                              },

                              "input:text change": function() {
                                 // Autocomplete lookup
                              },

                              "submit": function() {
                                // Ajax form submit
                              }
                            });

                            $(document).ready(function() {
                              $("form#search").tr_search_control();
                            });

                            });
Sunday, October 17, 2010
TR.SearchControl
                               FuncUnit




Sunday, October 17, 2010
homepage/homepage.js
                           steal.plugins("jquery")
                                .resources("slider", "tabs")
                                .plugins("tr/search_control")
                                .then(function($) {

                           $(document).ready(function() {
                             $("#slider").slider();
                             $("#tabs").tabs();
                           });

                           });




Sunday, October 17, 2010
Sunday, October 17, 2010
All Done Coding,
                           Time to Optimize



Sunday, October 17, 2010
Building & Compression
                    •      Packages
                           • 0.js - Shared between all apps
                             (jQuery, JavascriptMVC componetns, etc)
                           • homepage/production.js
                             Unique to Homepage
                           • contacts/contact.js
                             Unique to Contact
                    •      Google Closure Compiler
                           • Dojo Shrinksafe also available

Sunday, October 17, 2010
Building & Compression


                       ./steal/js steal/buildjs homepage contact




Sunday, October 17, 2010
Building & Compression




Sunday, October 17, 2010
Production HTML
                           <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
                                       "http://www.w3.org/TR/html4/strict.dtd">
                           <html lang="en">
                             <head>
                               <title>homepage</title>
                             </head>
                             <body>
                               <h1>Thanks for stealing StealJS!</h1>
                               <p>Don't worry, it's open source. It's only stealing if you
                           don't do something awesome with it.</p>
                               <div id='content'></div>

                               <script type='text/javascript'
                                         src='../steal/steal.js?homepage,production'>
                               </script>
                             </body>
                           </html>




Sunday, October 17, 2010
Sunday, October 17, 2010
Summary
                • Organize code into apps & plugins

                • Always Test Your Code

                • Use consistent naming and organization

                • Create sharable modules (Github)

                • Optimize!


Sunday, October 17, 2010
JavascriptMVC Provides
                           Models (JSON API wrappers)


                           Views (EJS, Micro, Jaml)


                           Controllers (Event system, data binding)


                           Functional testing (FuncUnit, qunit, selenium)


                           Dependency management (Optimization)
Sunday, October 17, 2010
My Plugins

                     JavascriptMVC convenience gem

                     • gem install javascriptmvc --pre

                           • jmvc-init newproject

                           • jmvc-gen newapp




Sunday, October 17, 2010
My Plugins
                • steal.plugins("ss/state_machine")
                     http://github.com/secondstory/secondstoryjs-
                     statemachine

                • steal.plugins("ss/router")
                     http://github.com/secondstory/secondstoryjs-router

                • steal.plugins("tr/views/mustache")
                     http://github.com/tdreyno/mustache-javascriptmvc

                • steal.plugins("tr/controller/pure")
                     http://github.com/tdreyno/javascriptmvc-pure



Sunday, October 17, 2010
Thank you
                • Questions?

                • http://v3.javascriptmvc.com/index.html

                • @tdreyno

                • awardwinningfjords.com

                • github.com/secondstory

                • github.com/tdreyno

                • http://github.com/tdreyno/jquery-demo



Sunday, October 17, 2010

More Related Content

What's hot

jQuery('#knowledge').appendTo('#you');
jQuery('#knowledge').appendTo('#you');jQuery('#knowledge').appendTo('#you');
jQuery('#knowledge').appendTo('#you');
mikehostetler
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
Remy Sharp
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
Bedis ElAchèche
 
OOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetupOOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetup
Brian Cavalier
 
jQuery
jQueryjQuery
jQuery
Jay Poojara
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgets
velveeta_512
 
jQuery
jQueryjQuery
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutes
Simon Willison
 
A Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETA Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NET
James Johnson
 
JQuery introduction
JQuery introductionJQuery introduction
JQuery introduction
NexThoughts Technologies
 
jQuery Basic API
jQuery Basic APIjQuery Basic API
jQuery Basic API
Hyeonseok Shin
 
Stack Overflow Austin - jQuery for Developers
Stack Overflow Austin - jQuery for DevelopersStack Overflow Austin - jQuery for Developers
Stack Overflow Austin - jQuery for DevelopersJonathan Sharp
 
Prototype & jQuery
Prototype & jQueryPrototype & jQuery
Prototype & jQuery
Remy Sharp
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
Rebecca Murphey
 
The jQuery Library
The  jQuery LibraryThe  jQuery Library
The jQuery Library
LearnNowOnline
 
jQuery in the [Aol.] Enterprise
jQuery in the [Aol.] EnterprisejQuery in the [Aol.] Enterprise
jQuery in the [Aol.] Enterprise
Dave Artz
 
Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...
Thinqloud
 
jQuery
jQueryjQuery

What's hot (20)

jQuery('#knowledge').appendTo('#you');
jQuery('#knowledge').appendTo('#you');jQuery('#knowledge').appendTo('#you');
jQuery('#knowledge').appendTo('#you');
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
 
OOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetupOOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetup
 
jQuery
jQueryjQuery
jQuery
 
jQuery Introduction
jQuery IntroductionjQuery Introduction
jQuery Introduction
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgets
 
jQuery
jQueryjQuery
jQuery
 
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutes
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
A Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETA Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NET
 
JQuery introduction
JQuery introductionJQuery introduction
JQuery introduction
 
jQuery Basic API
jQuery Basic APIjQuery Basic API
jQuery Basic API
 
Stack Overflow Austin - jQuery for Developers
Stack Overflow Austin - jQuery for DevelopersStack Overflow Austin - jQuery for Developers
Stack Overflow Austin - jQuery for Developers
 
Prototype & jQuery
Prototype & jQueryPrototype & jQuery
Prototype & jQuery
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
 
The jQuery Library
The  jQuery LibraryThe  jQuery Library
The jQuery Library
 
jQuery in the [Aol.] Enterprise
jQuery in the [Aol.] EnterprisejQuery in the [Aol.] Enterprise
jQuery in the [Aol.] Enterprise
 
Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...
 
jQuery
jQueryjQuery
jQuery
 

Viewers also liked

You and Your Stylesheet
You and Your StylesheetYou and Your Stylesheet
You and Your Stylesheet
Virginia DeBolt
 
Html5 accessibility
Html5 accessibilityHtml5 accessibility
Html5 accessibility
Virginia DeBolt
 
Clase auxiliar transito_y_calculo_de_ejes_equivalentes
Clase auxiliar transito_y_calculo_de_ejes_equivalentesClase auxiliar transito_y_calculo_de_ejes_equivalentes
Clase auxiliar transito_y_calculo_de_ejes_equivalentes
oscar torres
 
Lab pavimentos
Lab pavimentosLab pavimentos
Lab pavimentos
oscar torres
 
Sass Introduction
Sass IntroductionSass Introduction
Sass Introduction
Thomas Reynolds
 
Manual de diseño de pavimentos
Manual de diseño de pavimentosManual de diseño de pavimentos
Manual de diseño de pavimentos
oscar torres
 
Practica dirigida de mezclas asfálticas
Practica dirigida de mezclas asfálticasPractica dirigida de mezclas asfálticas
Practica dirigida de mezclas asfálticas
oscar torres
 
Twitter For Writers
Twitter For WritersTwitter For Writers
Twitter For Writers
Virginia DeBolt
 
How To Build iOS Apps Without interface Builder
How To Build iOS Apps Without interface BuilderHow To Build iOS Apps Without interface Builder
How To Build iOS Apps Without interface Builder
dasdom
 
HTML5 Web Messaging
HTML5 Web MessagingHTML5 Web Messaging
HTML5 Web Messaging
Mike Taylor
 
Diseodeescaleradeconcretoarmado
DiseodeescaleradeconcretoarmadoDiseodeescaleradeconcretoarmado
Diseodeescaleradeconcretoarmado
oscar torres
 

Viewers also liked (13)

Is these a bug
Is these a bugIs these a bug
Is these a bug
 
You and Your Stylesheet
You and Your StylesheetYou and Your Stylesheet
You and Your Stylesheet
 
Html5 accessibility
Html5 accessibilityHtml5 accessibility
Html5 accessibility
 
Clase auxiliar transito_y_calculo_de_ejes_equivalentes
Clase auxiliar transito_y_calculo_de_ejes_equivalentesClase auxiliar transito_y_calculo_de_ejes_equivalentes
Clase auxiliar transito_y_calculo_de_ejes_equivalentes
 
Lab pavimentos
Lab pavimentosLab pavimentos
Lab pavimentos
 
Sass Introduction
Sass IntroductionSass Introduction
Sass Introduction
 
Manual de diseño de pavimentos
Manual de diseño de pavimentosManual de diseño de pavimentos
Manual de diseño de pavimentos
 
Practica dirigida de mezclas asfálticas
Practica dirigida de mezclas asfálticasPractica dirigida de mezclas asfálticas
Practica dirigida de mezclas asfálticas
 
Twitter For Writers
Twitter For WritersTwitter For Writers
Twitter For Writers
 
How To Build iOS Apps Without interface Builder
How To Build iOS Apps Without interface BuilderHow To Build iOS Apps Without interface Builder
How To Build iOS Apps Without interface Builder
 
App in a Browser
App in a BrowserApp in a Browser
App in a Browser
 
HTML5 Web Messaging
HTML5 Web MessagingHTML5 Web Messaging
HTML5 Web Messaging
 
Diseodeescaleradeconcretoarmado
DiseodeescaleradeconcretoarmadoDiseodeescaleradeconcretoarmado
Diseodeescaleradeconcretoarmado
 

Similar to Organizing Code with JavascriptMVC

Week 4 - jQuery + Ajax
Week 4 - jQuery + AjaxWeek 4 - jQuery + Ajax
Week 4 - jQuery + Ajaxbaygross
 
Jquery Best Practices
Jquery Best PracticesJquery Best Practices
Jquery Best Practicesbrinsknaps
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryRebecca Murphey
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
Alive Kuo
 
Intro to HTML5 Web Storage
Intro to HTML5 Web StorageIntro to HTML5 Web Storage
Intro to HTML5 Web Storagedylanks
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
Sylvain Zimmer
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
Andrew Dupont
 
Jquery optimization-tips
Jquery optimization-tipsJquery optimization-tips
Jquery optimization-tips
anubavam-techkt
 
jQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't KnowjQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't Knowgirish82
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
Doris Chen
 
J query1
J query1J query1
J query1
Manav Prasad
 
Introduction to jQuery - Barcamp London 9
Introduction to jQuery - Barcamp London 9Introduction to jQuery - Barcamp London 9
Introduction to jQuery - Barcamp London 9
Jack Franklin
 
JavaScript JQUERY AJAX
JavaScript JQUERY AJAXJavaScript JQUERY AJAX
JavaScript JQUERY AJAX
Makarand Bhatambarekar
 
Jquery introduction
Jquery introductionJquery introduction
Jquery introduction
musrath mohammad
 
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
Jonas De Smet
 
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.jsJarod Ferguson
 
2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx
Le Hung
 
Trimming The Cruft
Trimming The CruftTrimming The Cruft
Trimming The Cruft
Peter Higgins
 

Similar to Organizing Code with JavascriptMVC (20)

Week 4 - jQuery + Ajax
Week 4 - jQuery + AjaxWeek 4 - jQuery + Ajax
Week 4 - jQuery + Ajax
 
Jquery Best Practices
Jquery Best PracticesJquery Best Practices
Jquery Best Practices
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
Intro to HTML5 Web Storage
Intro to HTML5 Web StorageIntro to HTML5 Web Storage
Intro to HTML5 Web Storage
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Jquery optimization-tips
Jquery optimization-tipsJquery optimization-tips
Jquery optimization-tips
 
jQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't KnowjQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't Know
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
bcgr3-jquery
bcgr3-jquerybcgr3-jquery
bcgr3-jquery
 
bcgr3-jquery
bcgr3-jquerybcgr3-jquery
bcgr3-jquery
 
J query1
J query1J query1
J query1
 
Introduction to jQuery - Barcamp London 9
Introduction to jQuery - Barcamp London 9Introduction to jQuery - Barcamp London 9
Introduction to jQuery - Barcamp London 9
 
JavaScript JQUERY AJAX
JavaScript JQUERY AJAXJavaScript JQUERY AJAX
JavaScript JQUERY AJAX
 
Jquery introduction
Jquery introductionJquery introduction
Jquery introduction
 
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
 
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
 
2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx2a-JQuery AJAX.pptx
2a-JQuery AJAX.pptx
 
Trimming The Cruft
Trimming The CruftTrimming The Cruft
Trimming The Cruft
 

Recently uploaded

Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website
Pixlogix Infotech
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Vladimir Iglovikov, Ph.D.
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 

Recently uploaded (20)

Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website20 Comprehensive Checklist of Designing and Developing a Website
20 Comprehensive Checklist of Designing and Developing a Website
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 

Organizing Code with JavascriptMVC

  • 1. Organizing Code with JavaScriptMVC git clone git://github.com/tdreyno/jquery-demo.git Thomas Reynolds Sunday, October 17, 2010
  • 2. Who am I? Sunday, October 17, 2010
  • 3. Who am I? • JavascriptMVC Core Committer • jQuery Plugin Developer • @tdreyno • github.com/tdreyno • awardwinningfjords.com Sunday, October 17, 2010
  • 6. Getting to Know You Sunday, October 17, 2010
  • 7. Getting to Know You • Traditional Website Developers • Web Application Developers • Mobile Web Developers Sunday, October 17, 2010
  • 10. One BIG File Sunday, October 17, 2010
  • 11. $(function(){ // make external links open in new window $('a[rel="external"]').attr('target','_blank'); if ($("body").attr('id') == 'homepage'){ bindHomepage(); } else if ($("body").hasClass('lessons_index') || $("body").hasClass('lessons_list')) { bindLessonsList(); } else if ($("body").hasClass('documents_detail')) { if (weird === 0){ showDetail(); } weird++; } else if ($("body").hasClass('lessons_detail')) { if (weird === 0){ showDetail(); } weird++; // look for requests to launch the activity editor var edit_matches = window.location.search.match(/[?&]edit_activity=(d+)&type=([^=?&]+)/) if (edit_matches) { var edit_activity_id = edit_matches[1]; var edit_activity_type = edit_matches[2]; launchCreatorModal({ id: edit_activity_id, type: edit_activity_type, mode: 'edit' }); } } else if ($("body").attr('id')=='my_classroom'){ bindMyClassroom(); } else if ($("body").hasClass('templates_index')){ bindTemplates(); } bindCreatorLinks(); // This can cause an error in Chrome, but the problem is already patched (03/2010) // and awaiting a release. window.onbeforeunload = handleOnBeforeUnload; window.onunload = handleOnUnload; if (window.location.search.match(/[?&]from_activity=1/)) { $('#back_to_activity a').pulse(); } bindSearchToggle(); // Load the "Star This" code // Should be inlined using something like Sprockets in the future $.getScript("/js/stars-and-add-to-buttons.js"); // Handle resources page toggles $("p.more a.morelink, ul.more a.morelink, a.arrow").click(function(e) { e.preventDefault(); var parentElem = $(this).parents(".openRow, .closedRow"); parentElem[0].className = parentElem.is(".openRow") ? "closedRow" : "openRow"; }); if (document.location.hash.length) { $("a[name=" + document.location.hash.replace(/#/, "") + "]").parents(".closedRow").find(".arrow").click(); Sunday, October 17, 2010 }
  • 12. One BIG File • 800+ Lines • Difficult to read • No Documentation • No Test Cases • Not DRY Sunday, October 17, 2010
  • 13. The Solution? Break into Maintainable Chunks of Code Sunday, October 17, 2010
  • 14. Problems with Multiple Files • Does everything go into one folder? • What if something is needed in two different places? • Communication • Loading speed • Loading order Sunday, October 17, 2010
  • 15. JavascriptMVC Provides Dependency Management Sunday, October 17, 2010
  • 16. StealJS • Asynchronously Loading • Provides a structure for organizing files • Cleans, Combines & Compresses • Bundles Presentational CSS • Supports CoffeeScript & Less.js Sunday, October 17, 2010
  • 17. StealJS Example steal.plugins("jquery/controller", "jquery/event/drag", "jquery/dom/within") .then(function($) { // Configure JavascriptMVC plugins }) .resources("jquerytools.tabs", "jquery.ui.position", "jquerytools.scrollable") .then(function($) { // Configure jQuery plugins }) .controllers("tile", "large_zoom", "medium_zoom", "small_zoom", "control", "image") .then(function($) { // All dependencies are satisfied }) Sunday, October 17, 2010
  • 18. Plugin • Basic unit of organization • Simply, a folder. • Initialized by a .js file named the same as the app. • For example: my_plugin/my_plugin.js • Can include other plugins Sunday, October 17, 2010
  • 19. Resources • A folder named “resources/” in your plugin • Contains raw Javascript files, often a jQuery plugin • jQuery UI • jQuery Tools • Modernizr • Et cetera Sunday, October 17, 2010
  • 20. Controller • Could be called several things: • View Controller • Widget • $.fn on Steroids Sunday, October 17, 2010
  • 21. Controller • Controls a DOM element • Uses templates to create & manipulate the DOM • Manages state • Uses PubSub (OpenAjax) to communicate • Responds to events Sunday, October 17, 2010
  • 25. Example Site • Homepage • A slideshow • Tabs • Custom Autocomplete Search • Contact Page • Form with Validator • “Success” lightbox • Custom Autocomplete Search Sunday, October 17, 2010
  • 26. Getting Started • Download zip file from GitHub • http://github.com/jupiterjs/framework/ downloads • Unzip • Install gem • gem install javascriptmvc --pre • jmvc-init jqconf-demo Sunday, October 17, 2010
  • 27. Fresh JavascriptMVC Application Sunday, October 17, 2010
  • 29. Homepage HTML <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <title>homepage</title> </head> <body> <h1>Thanks for stealing StealJS!</h1> <p>Don't worry, it's open source. It's only stealing if you don't do something awesome with it.</p> <div id='content'></div> <script type='text/javascript' src='../steal/steal.js?homepage'></script> </body> </html> Sunday, October 17, 2010
  • 30. Homepage Javascript steal( 'resources/example' ) // Loads 'resources/example.js' .css( 'homepage' ) // Loads 'homepage.css' .plugins( 'steal/less', 'steal/coffee' ) // Loads 'steal/less/less.js' and // 'steal/coffee/coffee.js' .then(function(){ // Adds a function to be called back // once all prior files have been // loaded and run steal.coffee('resources/example') // Loads 'resources/example.coffee' .less('resources/example'); // Loads 'resources/example.less' }); Sunday, October 17, 2010
  • 31. Resources (jQuery Plugins) Sunday, October 17, 2010
  • 32. homepage/homepage.js steal.plugins("jquery") .resources("slider", "tabs") .then(function($) { $(document).ready(function() { $("#slider").slider(); $("#tabs").tabs(); }); }); Sunday, October 17, 2010
  • 34. Contact Page “App” Sunday, October 17, 2010
  • 35. Contact Page steal.plugins("jquery") .resources("validator", "lightbox") .then(function() { $("form").validator(); $("form").submit(function() { $.lightbox(); }); }); Sunday, October 17, 2010
  • 36. Autocomplete Search (Plugin) Sunday, October 17, 2010
  • 37. TR.SearchControl Plugin Sunday, October 17, 2010
  • 39. FuncUnit • Test-Driven Development: • Results well thought-out code • Inspires trust in your users • Documents logic • Provides an automated means of making sure everything still works Sunday, October 17, 2010
  • 40. TR.SearchControl FuncUnit module("TR.SearchControl", { setup: function() { $("form#search").tr_search_control(); } }) test("Autocomplete", function(){ // Type into text box // Extra results should appear }) test("Submit", function(){ // Clicking submit or hitting enter // Should submit the form }) Sunday, October 17, 2010
  • 41. TR.SearchControl FuncUnit Sunday, October 17, 2010
  • 42. Search Controller steal.plugins("jquery/controller") .resources("autocomplete") .then(function($) { $.Controller.extend("TR.SearchControl", { }, { init: function() { this.element.autocomplete(); }, "input:text change": function() { // Autocomplete lookup }, "submit": function() { // Ajax form submit } }); $(document).ready(function() { $("form#search").tr_search_control(); }); }); Sunday, October 17, 2010
  • 43. TR.SearchControl FuncUnit Sunday, October 17, 2010
  • 44. homepage/homepage.js steal.plugins("jquery") .resources("slider", "tabs") .plugins("tr/search_control") .then(function($) { $(document).ready(function() { $("#slider").slider(); $("#tabs").tabs(); }); }); Sunday, October 17, 2010
  • 46. All Done Coding, Time to Optimize Sunday, October 17, 2010
  • 47. Building & Compression • Packages • 0.js - Shared between all apps (jQuery, JavascriptMVC componetns, etc) • homepage/production.js Unique to Homepage • contacts/contact.js Unique to Contact • Google Closure Compiler • Dojo Shrinksafe also available Sunday, October 17, 2010
  • 48. Building & Compression ./steal/js steal/buildjs homepage contact Sunday, October 17, 2010
  • 49. Building & Compression Sunday, October 17, 2010
  • 50. Production HTML <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <title>homepage</title> </head> <body> <h1>Thanks for stealing StealJS!</h1> <p>Don't worry, it's open source. It's only stealing if you don't do something awesome with it.</p> <div id='content'></div> <script type='text/javascript' src='../steal/steal.js?homepage,production'> </script> </body> </html> Sunday, October 17, 2010
  • 52. Summary • Organize code into apps & plugins • Always Test Your Code • Use consistent naming and organization • Create sharable modules (Github) • Optimize! Sunday, October 17, 2010
  • 53. JavascriptMVC Provides Models (JSON API wrappers) Views (EJS, Micro, Jaml) Controllers (Event system, data binding) Functional testing (FuncUnit, qunit, selenium) Dependency management (Optimization) Sunday, October 17, 2010
  • 54. My Plugins JavascriptMVC convenience gem • gem install javascriptmvc --pre • jmvc-init newproject • jmvc-gen newapp Sunday, October 17, 2010
  • 55. My Plugins • steal.plugins("ss/state_machine") http://github.com/secondstory/secondstoryjs- statemachine • steal.plugins("ss/router") http://github.com/secondstory/secondstoryjs-router • steal.plugins("tr/views/mustache") http://github.com/tdreyno/mustache-javascriptmvc • steal.plugins("tr/controller/pure") http://github.com/tdreyno/javascriptmvc-pure Sunday, October 17, 2010
  • 56. Thank you • Questions? • http://v3.javascriptmvc.com/index.html • @tdreyno • awardwinningfjords.com • github.com/secondstory • github.com/tdreyno • http://github.com/tdreyno/jquery-demo Sunday, October 17, 2010