views:

194

answers:

2

I've decided I need to improve my javascript programming skills, as well as my OO skills. I am currently reading through some books, but sometimes it's hard to get a grip on the theory without seeing some practical examples first. So, I have a theoretical question about "best practices" for the following scenario...

I would like to create an OO script that displays a list of searchtag records retrieved from the server. I also want to be able to edit each searchtag record in place.

Currently I am doing this procedurally with a bit of help from the jQuery library:

I accept a JSON-encoded list of searchtag records from the server. It looks like this:

[
   { "searchTagName" : "tagOne", "searchTagID" : "1" },
   { "searchTagName" : "tagTwo", "searchTagID" : "2" },
   { "searchTagName" : "tagThree", "searchTagID" : "3" },
   etc...
]

I dump the JSON directly into jTemplates to create the appropriate html, like so:

$("#searchTagList")
   .setTemplateElement("template_searchTagList")
   .processTemplate(searchTagData);

Finally I want it to be possible to modify each searchtag with an edit-in-place method, so I attach a pre-built edit-in-place method to each html element:

$(".searchTag").editInPlace();

This works very well procedurally. And maybe the smartest thing would be to leave well enough alone. :) But, for the sake of argument, what is the best way to write something like this from an OO perspective.

Should I have a single object "searchTagList" that has methods for each of the steps discussed above?

var searchTagList = 
{
    searchTagData: JSONdata,
    renderList: function () { /*send to jTemplates */ }
    bindEdit: function() { /* attach edit-in-place */ }
}

Or is that incorrect? (It seems like all I'm doing is wrapping my procedural functions in an object.) Should I somehow be parsing the JSON data into instances of each searchtag, and then attaching individual methods to each searchtag? (This seems like a lot of overhead, for no gain.)

Apologies in advance if it seems like I am picking at hairs. But I really want to get this stuff straight in my head.

Thanks,

Travis

+2  A: 

Actually, the jQuery examples you posted are not procedual, they're OO. Specifically they are an implementation of chainable objects which comes from the Fluid Programming school of OO design.

Procedual would be something like:

var el = cssQuery("#searchTagList");
var templateObject = makeTemplate(el,"template_searchTagList");
processTemplate(templateObject,searchTagData);

Functional would be something like:

processTemplate(
    makeTemplate(
        cssQuery("#searchTagList"),
        "template_searchTagList"
    ),
    searchTagData
);

jQuery have done a pretty good job of objectifying the DOM API. It's OK to use it as an inspiration of your own OO DOM library. Another one that I'd recommend you to look at is YUI3 (YUI2 is very procedual).

Specifically, the general pattern of jQuery and YUI3 is:

nodeListConstructor(query_string).nodeMethods();

Where they define an OO-like node object to wrap around DOM HTMLElements and then another OO style nodeList object to allow you to batch process nodes. This in my humble opinion is a good design pattern.

slebetman
Thanks for the reply. I should clarify. When I meant procedural, I meant that I have 3 distinct functions in the global space. One to handle retrieving JSON from the server. One to convert the JSON over to html. And a final function to attach an edit in place method to the html nodes. It's true that each of those functions uses OO jQuery techniques internally. But I am more concerned about the best way to organize the three higher level functions, which currently look very procedural - ie should they all be wrapped together in an object. I will take a look at YUI3, thanks.
Travis
A: 

You could use Javascript Module pattern to good effect here.

According to that pattern your searchTagList definition would change to:

var searchTagList = function() {
    searchTagData: JSONdata;
    return {
    renderList: function () { /*send to jTemplates */ },
    bindEdit: function() { /* attach edit-in-place */ }
   };
}();

The two functions renderList and bindEdit would still be able to access searchTagData but will remain inaccessible to code outside searchTagList module.

Observe that the anonymous function executes immediately and returns an object containing two public methods ( renderList and bindEdit ) that form a closure on the private member searchTagData.

You could read more about the Module pattern here.

ardsrk
Thanks for the info. I have been playing around the module pattern. But I found very quickly (not in the above example but in the actual production code) that I sometimes run into situations where it would be handy to have a private method call a public method -- and that doesn't work. Maybe that is just bad design on my part... :)
Travis
In the module pattern calling a public method from a private method is not possible because the public members form a closure over the private members and not the other way round. This just struck to me now and I hadn't thought about such a scenario before. Thanks.
ardsrk
@Travis, if you need to call public methods from private methods, just define the public method the same way you do the private ones, and add it to the returned object by name instead of as an anonymous function.
Matthew Crumley
@Matthew, good to know, thanks.
Travis