Thoughts on Modern Web Development …

Backbone.js provides a light-weight, extensible API which focuses primarily on general structure, and the utility of that structure, without requiring a rigid adherence to specific patterns or prescribing certain design philosophies. This focused approach affords developers a significant level of flexibility which can prove to be essential to the success of many modern client side web applications – especially when considering the challenges surrounding the ever changing landscape of the web.

Naturally, it follows that such flexibility imparts additional responsibility on the developer. In my experience with architectural frameworks in general, and Backbone in particular, many times this kind of trade off can be quite preferable.

Extending Backbone

As mentioned above, Backbone implements the essential building blocks necessary to provide general structure within an application. If a feature is needed which is not provided by default, by design, Backbone allows for easily extending the core APIs in order to implement additional features as needed. In fact, developers are encouraged to do so.

Perhaps a good example of this can be found in the need to persist collections in Backbone; that is, interestingly, while the Backbone Model API implements a default save method, the Backbone Collection does not provide a similar API for explicitly saving the models within a collection; that is, saving the collection itself. This feature may have been left out intentionally as part of an initial design decision, as there are some complexities to saving an entire collection as a general use-case; such as saving deltas, propagating saved state to models within the collection and so forth; or, perhaps it simply may have been an oversite. Regardless of the reason, in certain scenarios it can be useful to save an entire collection rather than saving each model individually – fortunately, given the flexibility of Backbone, writing an extension to implement this feature is quite simple.

The PersistableCollection

As a basic solution for saving a Backbone Collection, I wrote a general abstraction – PersistableCollection, which extends Backbone.Collection, implementing a default save method.

The PersistableCollection API is quite simple in that it essentially just implements a proxy which wraps the collection in a Backbone Model, and ensures there is only one proxy created per collection. The url and toJSON methods, respectively, of the proxy Model reference the url and toJSON methods of the collection to which the proxy is bound. You can either extend PersistableCollection or generate a proxy for an existing collection via the static createProxy method. Examples of each follow.

Using a PersistableCollection

A PersistableCollection can be instantiated and used directly, just like a Backbone.Collection:

1

2

3

4

5

6

7

8

9

varusers=newBackbone.PersistableCollection([

{name:'Jane',id:25},

{name:'Joe',id:26}

],{

url:'/users';

);

users.save();// saves the collection ...

Extending PersistableCollection

You can extend PersistableCollection and simply invoke save to persist the models in the collection:

1

2

3

4

5

6

7

8

9

10

11

varUsers=Backbone.PersistableCollection.extend({

url:'/users',

model:User

});

varusers=newUsers([[

{name:'Jane',id:25},

{name:'Joe',id:26}

]);

users.save();// saves the collection ..

Creating a proxy for an existing collection

An existing collection can be saved by creating a proxy for it:

1

2

3

4

5

6

7

8

9

varusers=newUsersCollection([

{name:'Jane',id:25},

{name:'Joe',id:26}

]);

users.url='/users';

varproxy=PersistableCollection.createProxy(users);

proxy.save();// saves the collection ...

The PersistableCollection can be used as a general extension for saving entire collections based on the representation of all models within the collection. If you are interested in extending it to account for more specific use-cases, you can simply override the default save implementation as needed.

The jQote2 API Reference provides plenty of useful examples which are sure to help users get up and running quickly. I found it a bit unclear, though, as to how templates could be loaded externally as, in the reference examples, templates are defined within the containing page. For the sake of simplicity this approach certainly makes sense in the context of examples. However, in practice, templates would ideally be loaded externally.

While jQote2 provides a perfect API for templating, it does not provide a method specifically for loading external templates; this is likely due to the fact that loading external templates could easily be accomplished natively in jQuery. However, since this is a rather common development use case, having such a facility available would be quite useful.

After reviewing the comments I came across a nice example from aefxx (the author of jQote2) which demonstrated a typical approach to loading external templates which was simular to what I had been implementing myself.

And so, I wrote a simple jQuery Plug-in which provides a tested, reusable solution for loading external templates. After having leveraged the Plugin on quite a few different projects, I decided to open source it as others may find it useful as well.

When dynamically creating or updating a list in jQuery Mobile; either via AJAX or by other means, one must take care to explicitly invoke the target listview widget to “refresh” in order to instruct the framework to apply the augmented markup and styles to the corresponding elements of the underlying list.

For example, consider the following simplified example which creates an li element for each item in an Array:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

varlist="",

items=[{

name:"Item A",

url:"/#item-a"

},{

name:"Item B",

url:"/#item-b"

},{

name:"Item C",

url:"/#item-c"

}];

$.each(items,function(i,item){

list+='<li><a href="'+item.url+'">';

list+=item.name;

list+='</a></li>';

});

$("ul:jqmData(role='listview')").append(list);

While this will create the list items and add them to the target listviewul element, JQM will not auto enhance the newly added items unless instructed to do so. I imagine this is due to a necessary design decision as, constantly monitoring the DOM for changes would certainly incur a performance hit.

In order to correct this, we just need to invoke .listview("refresh"); after appending the new elements to the list. This will notify JQM to apply the expected enhancements. And so, the following example will result in the expected list enhancements being applied:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

varlist="",

items=[{

name:"Item A",

url:"/#item-a"

},{

name:"Item B",

url:"/#item-b"

},{

name:"Item C",

url:"/#item-c"

}];

$.each(items,function(i,item){

list+='<li><a href="'+item.url+'">';

list+=item.name;

list+='</a></li>';

});

$("ul:jqmData(role='listview')").append(list).listview("refresh");

You can try an example which demonstrates both of the above implementations here.

Having worked with jQuery Mobile since Alpha 1, in the time since, the framework has certainly evolved into a mature, premier platform on which Mobile Web Applications can be built.

On a personal note, as I am currently in the process of working towards the release of a multi form-factor Mobile Web Application built on jQuery Mobile, the 1.0 release couldn’t have come at a better time.

The power of CSS Selectors can not be understated; for, without them, there would be no simple means by which developers could target specific elements for styling in a manner abstracted from, or external to, the actual markup to which the styles will bind.

Attribute Presence and Value Selectors

CSS2 introduced four Attribute Selectors; referred to as Attribute Presence and Value Selectors, which allow for coarse grained matching of specific elements based on their attributes and / or attribute values. These include the following:

e[attr]

Where e is an element and [attr] is an attribute of element e. For example, p[title] would match all p tags with a title, regardless of the value of the title.

1

2

3

4

5

6

7

8

9

10

/*

Matches all <p> tags with a title and changes their

background color to red with white text

*/

p[title]{

background-color:red;

color:white;

}

e[attr=val]

Where e is an element and [attr=val] represent an attribute of element e which contains the exact value of val. For example, p[title="Example 1"] would match all p tags with a title which equals “Example 1” exactly.

1

2

3

4

5

6

7

8

9

10

11

/*

Matches all <p> tags with a title equal to "Example 1"

and changes their background color to green and text

color to white

*/

p[title="Example 1"]{

background-color:green;

color:white;

}

e[attr~=val]

Where e is an element and [attr~=val] is an attribute of element e which has a value containing a whitespace-separated list of words, one of which equals val exactly. For example, p[title~="Example-1a"] would match all p tags with a title containing the word “Example-1a” in a list of whitespace delimited words.

1

2

3

4

5

6

7

8

9

10

11

/*

Matches all <p> tags with a title containing the exact

word to "Example-1a" and changes their background color

to black and text color to red

*/

p[title~="Example-1a"]{

background-color:black;

color:red;

}

e[attr|=val]

Where e is an element and [attr|=val] is an attribute of element e that has a value of val exactly, or begins with val immediately followed by a hyphen “-“. For example, p[title!="Example"] would match all p tags with a title containing the word “Example-“, followed by any other value, such as “Example-1”, “Example-A”, etc..

Substring Matching Attribute Selectors

In addition to the above Attribute Presence and Value Selectors, CSS3 expands on this by defining three additional Attribute Selectors; referred to as Substring Matching Attribute Selectors. These additions allow for fine grained matching of specific elements based on their attribute values.

In simplest terms, the new Attribute Selectors in CSS3 can be used to match an element with a given attribute whose value begins, ends or contains a certain value. The following is a basic description and example of each new Attribute Selector:

e[attr^=val]

Where e is an element and [attr^=val] is an attribute of element e which contains a value that begins with val.

1

2

3

4

5

6

/* Matches all linked resources sent over https */

a[href^="https"]{

color:red;

}

e[attr$=val]

Where e is an element and [attr$=val] represent an attribute of element e which contains a value that ends with val.

1

2

3

4

5

6

/* Matches all anchor tags to .html documents */

a[href$=".html"]{

color:green;

}

e[attr*=val]

Where e is an element and [attr*=val] is an attribute of element e which has a value that contains val.

To summarize, there are a total of seven Attribute Selectors in CSS3, three of which are new. Whether used for general matches, such as global Attributes; e.g. *[hreflang|=en] or more specific matches, such as chaining; e.g, a[href^="https"][target="_blank"], Attribute Selectors provide a powerful mechanism for selecting both general and specific content within a page.

The ability to facilitate interconnectivity between multiple clients has always presented some rather interesting possibilities for both simple and complex Web Applications alike. More often than not, such interconnected applications would require complex server-side configurations (often proprietary in nature) in addition to numerous infrastructure considerations.

Peerbind, a new JavaScript API, remedies many of these complications by providing a very simple client-side API built on jQuery.

Peerbind is quite unique in that it provides an event binding API (on top of jQuery) that is shared amongst all connected clients of the same interest. Essentially this allows for binding something as common as a “click” event (or any event for that matter, including custom events) such that each active instance of the same application across the web will be notified of the event. As one might imagine, this allows for some rather compelling possibilities.

To demonstrate just how quickly and easily interconnectivity can be plugged into a web application using Peerbind (and the Peerbind public server), below is a simple example which displays a new item each time a new “peer” views the example page since loaded (hint: try opening a few instances, either in tabs or separate browsers).

Of course, for most applications there are obvious security concerns which would need to be addressed as well as issues of scale and availability to take into consideration. That being said, if you haven’t checked out Peerbind yet and would like to quickly and easily add interconnectivity to your application or leverage it’s simplicity to prototype such features, it is certainly worth taking for a test drive.