Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encapsulating UI components with jQuery

Tags:

jquery

I'm building an app that involves creating several unique UI "widgets", and I'm having trouble figuring out a good practice for encapsulating the logic behind these UI components with jQuery. These are mostly one-off components that aren't reused several places in the app.

I've been experimenting with the lowpro plugin, and while it does allow more or less what I want, I feel like I'm going against "the jQuery way" by using it.

To provide some context, here's an abbreviated extract of something I wrote using lowpro. It's a sortable list that other elements can be drug into. When it's initialized empty, it shows a placeholder.

FieldList = $.klass({
  initialize: function() {
    this.placeholder = $('#get-started-placeholder');
    if (this.items().length == 0) {
      this.deactivateList();
    } else {
      this.activateList();
    }
  },

  items: function() {
    return this.element.children('li:visible');
  },

  deactivateList: function() {
    this.element.hide();
    this.element.sortable('destroy');
    this.placeholder.show();
    var instance = this;
    this.placeholder.droppable({
      hoverClass: 'hovered',
      drop: function(e, ui) { instance.receiveFirstField(ui.helper); }
    });
  },

  activateList: function() {
    this.placeholder.hide();
    this.placeholder.droppable('destroy');
    this.element.show();
    var instance = this;
    this.element.sortable({
      placeholder: 'placeholder',
      forcePlaceholderSize: false,
      tolerance: 'pointer',
      handle: 'h4',
      opacity: 0.9,
      zIndex: 90,
      stop: function(e, ui) { instance.receiveField(ui.item); }
    });
  },

  receiveFirstField: function(element) {
    ...
    this.activateList();
  },

  receiveField: function(element) {
    ...
  }
});

$(function() {
  $('ol#fields').attach(FieldList);
}

Notice that I have a bit of state going on here, and some instance methods that I wish I could make private, etc. So, any jQuery pros out there that can tell me how they'd do this without relying on something like lowpro that perhaps contorts Javsacript into something it shouldn't be? I have a feeling there's a clean way to accomplish something like this with the Module Pattern I saw mentioned in this thread, but the pieces aren't really coming together for me.

Thanks!

like image 902
Brent Dillingham Avatar asked Jan 10 '10 18:01

Brent Dillingham


1 Answers

Use the jQuery UI "widget factory". It's what all the other UI widgets (Accordion, Dialog, etc) use.

There's an OK, but slightly confusing tutorial here. (It's the best one I've found.)

Basically, you define your widget in a much more jQuery way, like:

$.widget("ui.myCustomWidget", {
   _init: function(){
      //initialize your function
   },

   somethingElse: function(){
     //do something else here
   }
});

An underscore before the function name will make it private. You can also set the widget functions into an object and access the variable, if that's what you want:

var foo = {
   _init: function(){
    //yada yada
  },
  somethingElse: function(){
     //do something else here
  }
};

$.widget("ui.myCustomWidget", foo);

Then you just "create" your widget the same way you create any other UI widget:

$('div#myWidget').myCustomWidget();

Tons of options and built in jQuery tools that allow you to build your own widgets. Rather than making this a tutorial, though, I'll let you read all about them yourself. Happy widgeting!

like image 182
munch Avatar answered Dec 06 '22 06:12

munch