jQuery.Controller  class     

tags: core
plugin: jquery/controller
test: qunit.html

Controllers organize event handlers using event delegation. If something happens in your application (a user click or a Model instance being updated), a controller should respond to it.

Controllers make your code deterministic, reusable, organized and can tear themselves down auto-magically. Read about the theory behind controller and a walkthrough of its features on Jupiter's blog.

Basic Example

Instead of

$(function(){
  $('#tabs').click(someCallbackFunction1)
  $('#tabs .tab').click(someCallbackFunction2)
  $('#tabs .delete click').click(someCallbackFunction3)
});

do this

$.Controller('Tabs',{
  click: function() {...},
  '.tab click' : function() {...},
  '.delete click' : function() {...}
})
$('#tabs').tabs();

Tabs Example

Using Controller

Controller helps you build and organize jQuery plugins. It can be used to build simple widgets, like a slider, or organize multiple widgets into something greater.

To understand how to use Controller, you need to understand the typical lifecycle of a jQuery widget and how that maps to controller's functionality:

A controller class is created.

$.Controller("MyWidget",
{
  defaults :  {
    message : "Remove Me"
  }
},
{
  init : function(rawEl, rawOptions){ 
    this.element.append(
       "<div>"+this.options.message+"</div>"
      );
  },
  "div click" : function(div, ev){ 
    div.remove();
  }  
}) 

This creates a $.fn.my_widget jQuery helper function that can be used to create a new controller instance on an element.

An instance of controller is created on an element

$('.thing').my_widget(options) // calls new MyWidget(el, options)

This calls new MyWidget(el, options) on each '.thing' element.

When a new Class instance is created, it calls the class's prototype setup and init methods. Controller's setup method:

The controller responds to events

Typically, Controller event handlers are automatically bound. However, there are multiple ways to listen to events with a controller.

Once an event does happen, the callback function is always called with 'this' referencing the controller instance. This makes it easy to use helper functions and save state on the controller.

The widget is destroyed

If the element is removed from the page, the controller's jQuery.Controller.destroy method is called. This is a great place to put any additional teardown functionality.

You can also teardown a controller programatically like:

$('.thing').my_widget('destroy');

Todos Example

Lets look at a very basic example - a list of todos and a button you want to click to create a new todo. Your HTML might look like:

<div id='todos'>
 <ol>
   <li class="todo">Laundry</li>
   <li class="todo">Dishes</li>
   <li class="todo">Walk Dog</li>
 </ol>
 <a class="create">Create</a>
</div>

To add a mousover effect and create todos, your controller might look like:

$.Controller.extend('Todos',{
  ".todo mouseover" : function( el, ev ) {
   el.css("backgroundColor","red")
  },
  ".todo mouseout" : function( el, ev ) {
   el.css("backgroundColor","")
  },
  ".create click" : function() {
   this.find("ol").append("<li class='todo'>New Todo</li>"); 
  }
})

Now that you've created the controller class, you've must attach the event handlers on the '#todos' div by creating a new controller instance. There are 2 ways of doing this.

//1. Create a new controller directly:
new Todos($('#todos'));
//2. Use jQuery function
$('#todos').todos();

Controller Initialization

It can be extremely useful to add an init method with setup functionality for your widget.

In the following example, I create a controller that when created, will put a message as the content of the element:

$.Controller.extend("SpecialController",
{
  init: function( el, message ) {
     this.element.html(message)
  }
})
$(".special").special("Hello World")

Removing Controllers

Controller removal is built into jQuery. So to remove a controller, you just have to remove its element:

$(".special_controller").remove()
$("#containsControllers").html("")

It's important to note that if you use raw DOM methods (innerHTML, removeChild), the controllers won't be destroyed.

If you just want to remove controller functionality, call destroy on the controller instance:

$(".special_controller").controller().destroy()

Accessing Controllers

Often you need to get a reference to a controller, there are a few ways of doing that. For the following example, we assume there are 2 elements with className="special".

//creates 2 foo controllers
$(".special").foo()

//creates 2 bar controllers
$(".special").bar()

//gets all controllers on all elements:
$(".special").controllers() //-> [foo, bar, foo, bar]

//gets only foo controllers
$(".special").controllers(FooController) //-> [foo, foo]

//gets all bar controllers
$(".special").controllers(BarController) //-> [bar, bar]

//gets first controller
$(".special").controller() //-> foo

//gets foo controller via data
$(".special").data("controllers")["FooController"] //-> foo

Calling methods on Controllers

Once you have a reference to an element, you can call methods on it. However, Controller has a few shortcuts:

//creates foo controller
$(".special").foo({name: "value"})

//calls FooController.prototype.update
$(".special").foo({name: "value2"})

//calls FooController.prototype.bar
$(".special").foo("bar","something I want to pass")
© Jupiter IT - JavaScriptMVC Training and Support