Thursday, March 12th, 2009

Object Oriented Event Handling and Widgets

Category: JavaScript, jQuery

Paul Chiu, author of Passbook, has written up his thoughts on reuse for widgets in large Ajax applications.

The solution?

For Passbook I decided to solve this problem once and for all. The solution I believe is in objectifying page elements as a block so that a panel with an edit and delete button can be duplicated quickly without having the Javascript code keep track of which panel on the page was clicked and trying to modify that page element. An object oriented approach would mean the page object could edit or delete it self because it knows what it is and what it represents.

While there are some existing solutions that use custom methods to streamline the object oriented process and work around Javascript’s event target scoping of “this”. I believe a better method existed that did not require so much prototype modification and was more self contained and flexible. My solution is to use jQuery’s plugin model to control on page elements, or widgets.

To see the basic pattern it is easiest to first checkout the functional demo. The demo contains two main elements: a widgets container where an add action exists, and a widget controller that offers the user the ability to submit it or remove it. The demo shows the widget manipulating it self, its parent, as well as using a basic ajax callback within it self.

Paul then walks through an example, that ends up with the following code.

javascript

  1. // Widget container
  2. (function($) {
  3. // Widget container plugin
  4. $.fn.widgetContainer = function() {
  5.  this.each(function() {
  6.   // Vars
  7.   var wc = $(this);
  8.  
  9.   // Set events
  10.   wc.find('#add').click(function(e) { if (e) e.preventDefault(); add(wc) });
  11.  });
  12. }
  13.  
  14. // Add a widget to the container
  15. function add(wc) {
  16.  var widget = $($.fn.widget.template);
  17.  widget
  18.   .appendTo(wc)
  19.   .fadeIn('slow')
  20.   .widget(wc);
  21. }
  22.  
  23. // Widget
  24. (function() {
  25.  // Widget plugin
  26.  $.fn.widget = function(container) {
  27.   this.each(function() {
  28.    // Vars
  29.    var w = $(this);
  30.    w.parent = container;
  31.  
  32.    // Set events
  33.    w.find('form').submit(function(e) { if (e) e.preventDefault(); submit(w) });
  34.    w.find('.remove').click(function(e) { if (e) e.preventDefault(); remove(w) });
  35.   });
  36.  }
  37.  $.fn.widget.template = '<div class="widget"><form action="" method="POST"><input type="text" value=""/><input type="submit" value="Action!"/><a href="#" class="remove">Remove</a></form></div>';
  38.  
  39.  // Remove widget
  40.  function remove(w) {
  41.   w.remove();
  42.  }
  43.  
  44.  // Submit widget data
  45.  function submit(w) {
  46.   w.css('background', 'red');
  47.   $.post('/', w.find('form').serialize(), function(data) {
  48.    w.find(':text').val((new Date()).toString());
  49.    w.parent.fadeOut();
  50.    setTimeout(function() { w.parent.fadeIn() }, 500);
  51.   });
  52.  }
  53. })();
  54. })(jQuery);
  55.  
  56. // Main
  57. $(function() {
  58. $('.widgetContainer').widgetContainer();
  59. });

Posted by Dion Almaer at 6:21 am
Comment here

+++--
3.2 rating from 32 votes

Comments Here »

Comments feed TrackBack URI

Leave a comment

You must be logged in to post a comment.