I don’t think I words explain it better than the code below.
Here’s the collection program (CollectionFactory.utils.js file):
1: var CollectionFactory = function () {
2: return {
3: Collection:new Array(),
4: add: function (collection_object) {
5: this.Collection.push(collection_object);
6: this.triggerEvent("add");
7: },
8: removeAt:function(index) {
9: this.Collection.splice(index, 1);
10: this.triggerEvent("remove");
11: },
12: empty:function() {
13: this.Collection = null;
14: this.Collection = new Array();
15: this.triggerEvent("empty");
16: },
17: getAt:function (index) {
18: return this.Collection[index];
19: },
20: replaceAt:function (index, collection_object) {
21: this.Collection.splice(index, 1, collection_object);
22: this.triggerEvent("replace");
23: },
24: replaceOrAdd:function (collection_object, compare_key) {
25: var replaced = false;
26: /* see if anything needs to be replaced first */
27: for (var i=0;i<this.Collection.length;i++) {
28: if (this.Collection[i][compare_key] == collection_object[compare_key]) {
29: this.replaceAt(i, collection_object);
30: replaced = true;
31: }
32: }
33: /* if nothing was replaced, then the item needs to be added */
34: if (!replaced) {
35: this.add(collection_object);
36: }
37: return;
38: },
39:
40: getType: function () {
41: return (typeof this.Collection[0])
42: },
43: triggerEvent:function (method_name) {
44: $(document).trigger('COLLECTION_CHANGED', [{methodName:method_name, type:this.getType()}]);
45: }
46: }
47: };
[updated with a jQuery event trigger method]
A System-User super class (SysUser.model.js file):
1: SysUser = function () {}
2: SysUser.prototype.setConfig = function (config) {
3: this.first_name = config.first_name;
4: this.last_name = config.last_name;
5: this.username = (config.username == null || config.username == "" || config.username == undefined)?"guest":config.username;
6: this.password = (config.password == null || config.password == "" || config.password == undefined)?"guest":config.password;
7: this.updated_date = (config.updated_date == null || config.updated_date == "" || config.updated_date == undefined)?new Date():config.updated_date;
8: this.created_date = (config.created_date == null || config.created_date == "" || config.created_date == undefined)?new Date():config.created_date;
9: }
A Customer class derived from System-User (Customer.model.js file):
1: var Customer = function () {}
2: Customer.prototype = new SysUser;
3: Customer.prototype.constructor = this;
4: Customer.prototype.parent = SysUser.prototype;
5: Customer.prototype.setConfig = function (config) {
6: this.parent.prototype.setConfig(config); // call to super
7: this.customer_id = config.customer_id;
8: this.address = config.address;
9: this.city = config.city;
10: this.state = config.state;
11: this.zip = config.zip;
12: }
And finally the CustomerCollectionFactory singleton implementation that will return new CollectionFactory object (CustomerCollectionFactory.utils.js file)
1: var CustomerCollectionFactory = function () {
2: return new CollectionFactory();
3: }();
Now to demonstrate the usage; suppose you are making an AJAX call and retreiving a bunch of “customer” objects (I’m assuming JSON return) displaying them in a master-grid and and making edits to them in a dependant form. You need a central store something like an ArrayCollection in Flex with bindings to the Grid and Form.
You’d use the collection as shown in the code below:
1: // jquery...
2: $.ajax({
3: url:SERVER_URL,
4: type:"POST",
5: dataType:"json",
6: ...
7: success:function (data) {
8: if (data.result) {
9: var config = (data.data[0]); // return from AJAX call is in DATA[0] and is incidentally same format as "config" object expected by Customer's setConfig method
10:
11: var cust = new Customer()
12: cust.setConfig(config);
13: // add or replace
14: CustomerCollectionFactory.replaceAt(0, cust);
15:
16: // for my example I am guranteed only 1 row,
17: // index is always 0, so I just replace
18: // but you could call the add(cust) method here
19: ...
20: ...
21: // do other things
22: ...
23: }
24: else {
25: // do something
26: }
27: }
28: }
Now when you click the “delete” button on your grid all you have to do is:
1: CustomerCollectionFactory.remove(index_from_grid);
To enable the binding, you can bubble the “collection_changed” event upto the document
1: $(document).bind('COLLECTION_CHANGED', function (event, properties){
2: // check the properties object to see if the event is "SysUserCollectionChanged"
3: // do something like:
4: $('#MyGrid').jqGrid('addRowData', rowid, SysUserCollectionChanged.Collection[i], position, srcrowid);
5:
6: // or
7: $('#MyTextBox').val(SysUserCollectionChanged.Collection[i]);
8:
9: });
Hope this helps someone….
1 comment:
I think this is a very useful utility. It makes the developer think in terms of State and has a common place to see the state changes on the objects.
Now the Flex / Silverlight UIs that support 2 way binding automatically see changes and reacts.
Real beauty is this is still pure JS and one does not be sold to SilverLight / FLex / HTML 5 technologies.
I can throw in Phone UIs also.
Server throws just JSON no matter what UI and Object Layer @ UI remains the same.
I do see some sanity in the world of UI insanity.
Post a Comment