http://www.flickr.com/photos/mocambique/511151694/




Building Large
jQuery Applications
Rebecca Murphey
Me

independent JavaScript developer
based in Durham, N.C.
contributor to O’Reilly’s jQuery Cookbook
co-host of the yayQue...
What counts as
a large application?




http://www.flickr.com/photos/hippie/2475855465/
distinct but related pieces of functionality
extensive server communication
frequent updating of the page without reload
jQuery out of the box doesn’t give us
many tools for developing large applications;
its essentially a DOM manipulation and...
at doesn’t stop people from building
large applications with jQuery.
$(document).ready(function() {
    $('#myFeature li')
        .append('<div/>')
        .click(function() {
            va...
// NAVIGATION
function togglePage(section) {
    // if the clicked section is already the current section AND we're in ful...
How do you write an application that uses
jQuery without making a tangled mess?
e key is to think of our applications as small
pieces of functionality, and then write our code
accordingly.
Patterns & Practices

                  http://www.flickr.com/photos/docman/3270589892/
Above all else: Use jQuery as the DOM and Ajax
tool it is, not as a framework.
Use classes to organize your code; write
methods that do exactly one thing.
myApp.common.Messaging = Class.extend({
    animDuration : 500,
    hideDelay : 1500,

      init : function() {
         ...
Use the server to send data, not markup; use a
templating system (like mustache.js) to create
markup on the client side.
myApp.widgets.Tools = Class.extend({
    itemTemplate : '<li>' +
        '<input type="checkbox" name="{{description}}" ch...
Use a consistent pattern for de ning
components that have a DOM representation.
var DomThinger = Class.extend({
    config : {},

      init : function(el /* jQuery object */, opts /* mixin */) {
      ...
Communicate between components using a
centralized messaging hub (i.e. pub/sub).
myApp.common.Messaging = Class.extend({
    init : function() {
        this.el = $('<div class="message"/>').prependTo('b...
DRY and maintain separation of concerns.
$.proxy


Take control of your functions by specifying
the meaning of “this” inside of them.
myApp.services._base = Class.extend({
    description : '',

      init : function(opts) {
          $.subscribe('/search/...
$.fn.delegate


All the cool kids are using it
(say goodbye to $.fn.live)
myApp.widgets.Saved = Class.extend({

      init : function(el) {
          this.el = el;

           // event delegation ...
Tools for Building &
Dependency Management
              http://www.flickr.com/photos/flightsaber/2204113449/
Only a handful of solutions, none that I love.
RequireJS (building and loading)
LABjs (loading only)
modulr (building only)
Roll your own
Dojo?
Caveats
I’ve written plenty of code that didn’t work
this way. Sometimes for better, sometimes
for worse.
If your needs aren’t complex, don’t write
complex code to solve them. is approach
might be overkill for your project.
$(document).ready(function() {
    $('#myFeature li')
        .append('<div/>')
        .click(function() {
            va...
is approach works really well for applications
with distinct but related pieces of functionality,
and for applications th...
Other options for code org include plugins,
object literals, and prototypal inheritance.
anks.

rebeccamurphey.com
yayquery.com
twitter.com/rmurphey

http://pinboard.in/u:rmurphey/t:large-jquery-apps/
http://gi...
Upcoming SlideShare
Loading in...5
×

Building Large jQuery Applications

28,039

Published on

When you move beyond adding simple enhancements to your website with jQuery and start building full-blown client-side applications, how do you organize your code? At this month's Triangle JS Meetup, we'll take a look at patterns for application development using jQuery that promote the principles of tight encapsulation and loose coupling, including classes, the publish/subscribe paradigm, and dependency management and build systems.

Published in: Technology
3 Comments
81 Likes
Statistics
Notes
  • not helpfull
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Nice presentation
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • This is quite nice. Compact and to the point. I especially like your emphasis on the pub/sub pattern, which is really useful to decouple individual parts of a large javascript application.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
28,039
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
0
Comments
3
Likes
81
Embeds 0
No embeds

No notes for slide

Transcript of "Building Large jQuery Applications"

  1. 1. http://www.flickr.com/photos/mocambique/511151694/ Building Large jQuery Applications Rebecca Murphey
  2. 2. Me independent JavaScript developer based in Durham, N.C. contributor to O’Reilly’s jQuery Cookbook co-host of the yayQuery podcast code organization fanatic
  3. 3. What counts as a large application? http://www.flickr.com/photos/hippie/2475855465/
  4. 4. distinct but related pieces of functionality extensive server communication frequent updating of the page without reload
  5. 5. jQuery out of the box doesn’t give us many tools for developing large applications; its essentially a DOM manipulation and Ajax library.
  6. 6. at doesn’t stop people from building large applications with jQuery.
  7. 7. $(document).ready(function() { $('#myFeature li') .append('<div/>') .click(function() { var $this = $(this); var $div = $this.find('div'); $div.load('foo.php?item=' + $this.attr('id'), function() { $div.show(); $this.siblings() .find('div').hide(); } ); }) });
  8. 8. // 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
  9. 9. How do you write an application that uses jQuery without making a tangled mess?
  10. 10. e key is to think of our applications as small pieces of functionality, and then write our code accordingly.
  11. 11. Patterns & Practices http://www.flickr.com/photos/docman/3270589892/
  12. 12. Above all else: Use jQuery as the DOM and Ajax tool it is, not as a framework.
  13. 13. Use classes to organize your code; write methods that do exactly one thing.
  14. 14. myApp.common.Messaging = Class.extend({ animDuration : 500, hideDelay : 1500, init : function() { this.el = $('<div class="message"/>').prependTo('body').hide(); $.subscribe('/message/notification', $.proxy(this._showMessage, this)); }, _showMessage : function(msg) { var hide = $.proxy(this._hideMessage, this); this.el.append('<p>' + msg + '</p>'); if (!this.el.is(':visible')) { this.el.slideDown(this.animDuration, $.proxy(function() { this.showTimeout = setTimeout(hide, this.hideDelay); }, this)); } else { clearTimeout(this.showTimeout); this.showTimeout = setTimeout(hide, this.hideDelay); } }, _hideMessage : function() { this.el.slideUp(this.animDuration); this._cleanup(); }, _cleanup : function() { this.el.empty(); } });
  15. 15. Use the server to send data, not markup; use a templating system (like mustache.js) to create markup on the client side.
  16. 16. myApp.widgets.Tools = Class.extend({ itemTemplate : '<li>' + '<input type="checkbox" name="{{description}}" checked>' + '<label for="{{description}}">{{description}}</label>' + '</li>', services : [], init : function(el) { this.el = el; this.el.delegate('input', 'click', $.proxy(this._handleChoice, this)); $.subscribe('/service/add', $.proxy(this._handleAdd, this)); }, _handleChoice : function(e) { var input = $(e.target), service = input.attr('name'); $.publish('/service/' + service + '/toggle', [ input.is(':checked') ]); }, _handleAdd : function(service) { if ($.inArray(service, this.services) >= 0) { return; } var html = Mustache.to_html(this.itemTemplate, { description : service }); this.el.append(html); } });
  17. 17. Use a consistent pattern for de ning components that have a DOM representation.
  18. 18. var DomThinger = Class.extend({ config : {}, init : function(el /* jQuery object */, opts /* mixin */) { this.el = el; $.extend(this.config, opts); } });
  19. 19. Communicate between components using a centralized messaging hub (i.e. pub/sub).
  20. 20. myApp.common.Messaging = Class.extend({ init : function() { this.el = $('<div class="message"/>').prependTo('body').hide(); $.subscribe('/message/notification', $.proxy(this._showMessage, this)); }, _showMessage : function(msg) { /* ... */ }, _hideMessage : function() { /* ... */ }, _cleanup : function() { /* ... */ } }); myApp.services._base = Class.extend({ description : '', init : function(opts) { $.subscribe('/search/term', $.proxy(this._doSearch, this)); $.publish('/message/notification', [ 'Service ' + this.description + ' added' ] ); }, _doSearch : function(term) { /* ... */ }, });
  21. 21. DRY and maintain separation of concerns.
  22. 22. $.proxy Take control of your functions by specifying the meaning of “this” inside of them.
  23. 23. myApp.services._base = Class.extend({ description : '', init : function(opts) { $.subscribe('/search/term', $.proxy(this._doSearch, this)); $.publish('/message/notification', [ 'Service ' + this.description + ' added' ] ); }, _doSearch : function(term) { /* ... */ }, });
  24. 24. $.fn.delegate All the cool kids are using it (say goodbye to $.fn.live)
  25. 25. myApp.widgets.Saved = Class.extend({ init : function(el) { this.el = el; // event delegation for searching and removing searches this.el.delegate('li', 'click', $.proxy(this._doSearch, this)); this.el.delegate('span.remove', 'click', $.proxy(this._removeSearch, this)); }, _doSearch : function(e) { /* ... */ }, _removeSearch : function(e) { /* ... */ } });
  26. 26. Tools for Building & Dependency Management http://www.flickr.com/photos/flightsaber/2204113449/
  27. 27. Only a handful of solutions, none that I love.
  28. 28. RequireJS (building and loading) LABjs (loading only) modulr (building only) Roll your own Dojo?
  29. 29. Caveats
  30. 30. I’ve written plenty of code that didn’t work this way. Sometimes for better, sometimes for worse.
  31. 31. If your needs aren’t complex, don’t write complex code to solve them. is approach might be overkill for your project.
  32. 32. $(document).ready(function() { $('#myFeature li') .append('<div/>') .click(function() { var $this = $(this); var $div = $this.find('div'); $div.load('foo.php?item=' + $this.attr('id'), function() { $div.show(); $this.siblings() .find('div').hide(); } ); }) });
  33. 33. is approach works really well for applications with distinct but related pieces of functionality, and for applications that are always evolving.
  34. 34. Other options for code org include plugins, object literals, and prototypal inheritance.
  35. 35. anks. rebeccamurphey.com yayquery.com twitter.com/rmurphey http://pinboard.in/u:rmurphey/t:large-jquery-apps/ http://github.com/rmurphey/large-jquery-apps Special thanks to Alex Sexton, Paul Irish, Adam Sontag, James Burke, and Peter Higgins

×