Nub is a model-view-controller (MVC) plugin for jQuery. It allows data stored in a central in-page model to be displayed at different places on the page (the views). Updates made to the model data through the Nub controller are immediately reflected in the affected views.
Before using Nub on an HTML page, jQuery and the Nub plugin must be included in your page.
<script src="jquery.js"></script> <script src="jquery.nub.js"></script>
Suppose you have a simple JSON object like the following:
{ "fruit":"banana" }The object data can be stored in Nub's model with the following code:
var data = { "fruit":"banana" }; $.nub.set('/favourite', data );This stores the object at the location /favourite. We can now display the object's data somewhere within the page using the following HTML:
<div class="nub-view" data="/favourite/fruit"></div>This will result in something like the following being shown:
$.nub.set('/favourite', { "fruit":"pomegranate" }The value in the page will be updated appropriately:
The following sections delve a bit deeper into Nub's workings.
When the page is loaded all views in the page are initiated using the following code:
$.nub.init();(This code is usually placed inside a
$(document).ready(..)
callback function).
The nub.init method searches the page for any elements marked with the nub-view CSS class and does the following:
Data paths are used by Nub to identify the location in the model of a data value. A data path is simply a sequence of object property names separated by forward slashes, e.g. as seen above: /favourite/fruit. Data paths can be absolute or relative. Normally (as in the preceeding example) absolute paths are used, and begin with a forward slash. However, sometimes it can be convenient to specify a data path as being relative to some other - presumably absolute - path. This can be useful if a large number of paths need to be defined which all share the same prefix - i.e. if the paths are all referencing different properties of the same object. In this case, a context path can be used, and the nub.init function uses the nub-context CSS class to identify context elements.
In the following example, a series of DIVs are used to display different properties of the same object. A parent element with the nub-context class is used to provide a context path for each of the view elements.
<div class="nub-context" data="/my-car"> <div class="nub-view" data="registration"/> <div class="nub-view" data="colour"/> <div class="nub-view" data="doors"/> </div>This results, for example, in the first element displaying the value stored at /my-car/registration in the model.
Any form input can be turned into a model view by adding the nub-view class to the element:
<input class="nub-view" type="text" name="/favourite/colour"/>Inputs are handled a bit differently from other elements: the name attribute (instead of a data attribute) is used as the data path; and the input's value is set to the data value. Additional to displaying the value stored in the model, the input can now also be used to update the model. If a new value is entered into the input then the value stored in the model is updated correspondingly (and if other views are observing the same data item then they also will be updated).
Forms marked with the nub-form class on their FORM element get special treatment from Nub - the entire form is turned into an in-page model. This means that the form's inputs contain the actual values stored in the model, and in effect can be edited directly, while other elements in the page can observe the form's value and be updated as the form is edited. Nub creates a reference to the form model at a special place within the global model, under /nub:forms. Each Nub form has a reference to itself created under this location using the form's name (if the form isi unnamed then Nub will allocate a unique one; but this is rarely useful, as the name must be know if other views are to reference it).
This is easiest understood using an example. In the following example -
<form name="some" class="nub-form"> <input name="word" type="text"/> ... <div class="nub-view" data="/nub:forms/some/word"/>
Nub forms are also able to submit data using Ajax, see the Remote Data section below.
It is often useful for the list of options displayed by a select list to be read from somewhere in the model. This can be done by marking the SELECT element as a nub-view and giving it a data attribute. If the data item stored at the location specified by the data attribute is an array then it will be used to populate the select list's options. If the data item is a 1-dimensional array then each option will have the same data and value; if the data item is a 2-dimensional array then the first item of each array value is used as the option value and the second item is used as the option label.
If the SELECT list element contains OPTION elements then these won't be replaced by the list data; instead, these will be retained and will always be included at the top of the list. This is useful, for example, if you always want to display a default item on the list:
<select name="pattern" data="/wallpaper/patterns"> <option>Please select one...</option> </select>Note that the difference between the select's name and data attributes: the data attribute specifies where to read the data which generates the list; while the name attribute specifies where to store the list's selected value.
Functions can be registered with Nub as views on data in the model. This is useful when you want a value to be calculated from other values in the model, and you want that value to be updated whenever the other values are updated.
To take a simple example, suppose you want to calculate a value as being the sum of two other values. These values will be stored in this model under the location /values. We can write a 'sum' function and register it with Nub using the following code:
function sum() { var a = $.nub.get('/values/a'); var b = $.nub.get('/values/b'); $.nub.set('/sum', a + b ); } $.nub.view('/values', sum );The nub.view function allows a callback function to be registered which will be called whenever an update takes place at the specified path. Here, the path /values includes updates to /values/a and /values/b.
The following HTML uses the previous view function to update the sum of two values whenever the user enters new ones.
<input class="nub-view" type="text" name="/values/a"/> <input class="nub-view" type="text" name="/values/b"/> <span class="nub-view" data="/sum"></span>
Filters provide a way to generate new model data from other data already in the model, and are implemented using functional views. Conceptually, a filter is simply a function which is invoked whenever a data item is updated, and is passed the data value as an argument; the value returned by the function is then stored at a separate model location. Nub provides the nub.filter function for setting up a filter.
For example, suppose we have a list of people stored in the model, such as the following:
[ { "name":"Andy Matland", "age":27 }, { "name":"Jean Decaux", "age":17 }, { "name":"Sandy Williams", "age":32 }, { "name":"Chen Dawei", "age":16 } ]If we then want a list generated which only contains the people on the list who are teenagers, we can use the following code to set this up:
function teenagersOnly( people ) { var result = []; for( var i = 0; i < people.length; i++ ) { if( people[i].age > 12 && people[i].age < 20 ) { result.push( people[i] ); } } return result; } $.nub.filter('/everyone', teenagersOnly, '/teenagers');The nub.filter command takes three arguments:
Filters can also take arguments, see the Nub API documentation for more details.
Nub provides a number of mechanisms for passing data between the model and a remote server using Ajax.
Form models (see above), as well as providing access to data within a page form, can also be used to read data from and write data to a server. Nub uses the form's ACTION and METHOD attributes to decide where to write data to and what HTTP method to use. The form model object can then be used to initiate the Ajax operation.
Take the following form as an example:
<form name="login" method="POST" action="/login" class="nub-form"> <input type="text" name="username"/> <input type="password" name="password"/> </form>This is obviously a login form, and has been marked as a Nub form (i.e. because of the class attribute on the FORM element). Nub can be used to perform the login action over Ajax with the following code, which for example could be called when the user clicks a login button:
var form = $.nub.get('/nub:forms/login'); form.submit({ success: function() { alert('Login success!'); } });The first line reads the form object from the Nub model. This object actually represents the form model, and provides a number of methods for accessing data and loading or submitting data. The next line submits the form data using Ajax. The Ajax call will by default use the HTTP method and action URI specified on the form element; however, these can all be overriden using the argument passed to this function. (The argument takes all the same properties of the standard jQuery ajax() function call). If the form submit is successful then an alert is displayed with a success message.
The form object also allows data to be loaded into the form over Ajax, see the Nub API documentation for more details.
Remote objects are special objects within Nub's data model which read their data from a remote server using Ajax and can write their data back to the server. A remote object is created within the model with the nub.remote command:
var account = $.nub.remote('/remote/account');This command creates a new remote object at the location /remote/account in the model. (Placing all remote objects under /remote in the model is a Nub convention). At this stage, the remote object doesn't contain any data. Data could now be written to the object using nub.set(); instead, here we will first load data from the server using the remote object's httpGet method:
account.httpGet('/account-data');(Note that here, /account-data is a path on the server from which the HTML page hosting the code was loaded from, and not a data path). This command will load data from the specified server URI into the remote object. Suppose that the server returns the following object:
{ "name": "Mindy Collins", "type": "guest", "username": "mindyc" }The data can now be referenced and displayed in a view using a path like /remote/account/data/name. Note the 'data' component in the path. A remote object always places the data it loads under a top-level property called 'data'. Remote objects also supply a second top-level property called 'meta'. This property is used to store information about the status of the data contained by the remote object. This includes information such as the full URI the remote data was last loaded from and the status of the load operation.
See the Nub API documentation for more information on the meta object, and the full set of methods available on a remote object.
Nub provides a simple list framework for displaying array data stored in the model. This framework allows HTML tables or lists (i.e. OL or UL elements) to be used to display list data using all the formatting capabilities available in HTML. The framework also supports paging of large lists and allows full customization of the list pager.
Before using the list framework it must be included in the page, after the line including the Nub plugin:
<script src="jquery.nub-list.js"></script>The list framework uses a couple of additional Nub classes to mark the elements within a page which are to be used by a list:
<table id="people-list" data="/everyone"> <tr> <th>Name</th> <th>Age</th> </tr> <tr class="nub-list-row"> <td><b class="nub-list-view" data="name"/><td> <td class="nub-list-view" data="age"/> </tr> </table>The list is then initialized using the nubList function:
$('#people-list').nubList();The list framework supports a number of customization options and event callbacks; these are all described in the Nub API documentation.