Building Large jQuery Applications

  • 27,145 views
Uploaded 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, …

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.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • not helpfull
    Are you sure you want to
    Your message goes here
  • Nice presentation
    Are you sure you want to
    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.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
27,145
On Slideshare
0
From Embeds
0
Number of Embeds
7

Actions

Shares
Downloads
0
Comments
3
Likes
77

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. http://www.flickr.com/photos/mocambique/511151694/ Building Large jQuery Applications Rebecca Murphey
  • 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. What counts as a large application? http://www.flickr.com/photos/hippie/2475855465/
  • 4. distinct but related pieces of functionality extensive server communication frequent updating of the page without reload
  • 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. at doesn’t stop people from building large applications with jQuery.
  • 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. // 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. How do you write an application that uses jQuery without making a tangled mess?
  • 10. e key is to think of our applications as small pieces of functionality, and then write our code accordingly.
  • 11. Patterns & Practices http://www.flickr.com/photos/docman/3270589892/
  • 12. Above all else: Use jQuery as the DOM and Ajax tool it is, not as a framework.
  • 13. Use classes to organize your code; write methods that do exactly one thing.
  • 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. Use the server to send data, not markup; use a templating system (like mustache.js) to create markup on the client side.
  • 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. Use a consistent pattern for de ning components that have a DOM representation.
  • 18. var DomThinger = Class.extend({ config : {}, init : function(el /* jQuery object */, opts /* mixin */) { this.el = el; $.extend(this.config, opts); } });
  • 19. Communicate between components using a centralized messaging hub (i.e. pub/sub).
  • 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. DRY and maintain separation of concerns.
  • 22. $.proxy Take control of your functions by specifying the meaning of “this” inside of them.
  • 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. $.fn.delegate All the cool kids are using it (say goodbye to $.fn.live)
  • 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. Tools for Building & Dependency Management http://www.flickr.com/photos/flightsaber/2204113449/
  • 27. Only a handful of solutions, none that I love.
  • 28. RequireJS (building and loading) LABjs (loading only) modulr (building only) Roll your own Dojo?
  • 29. Caveats
  • 30. I’ve written plenty of code that didn’t work this way. Sometimes for better, sometimes for worse.
  • 31. If your needs aren’t complex, don’t write complex code to solve them. is approach might be overkill for your project.
  • 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. is approach works really well for applications with distinct but related pieces of functionality, and for applications that are always evolving.
  • 34. Other options for code org include plugins, object literals, and prototypal inheritance.
  • 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