Created
September 23, 2010 16:41
-
-
Save ghinch/593942 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var data = [ | |
{author : {surname : 'Roberts', firstname : 'Gregory David'}, title : 'Shantaram', published : (new Date('09/25/2005'))}, | |
{author : {surname : 'Gibson', firstname : 'William'}, title : 'Neuromancer', published : (new Date('07/01/1984'))}, | |
{author : {surname : 'Rowling', firstname : 'J.K.'}, title : 'Harry Potter', published : (new Date('06/30/1997'))}, | |
{author : {surname : 'Simon', firstname : 'Ted'}, title : 'Jupiter\'s Travels', published : (new Date('01/01/1979'))}, | |
{author : {surname : 'Tolkien', firstname : 'J.R.R.'}, title : 'The Hobbit', published : (new Date('09/21/1937'))} | |
]; | |
var ds = new Y.DataSource.Local({ | |
source : data, | |
plugins : [ | |
{fn : Y.Plugin.DataSourceArraySchema} | |
] | |
}); | |
var Author = Y.Base.create('author', Y.Model, [], { | |
}, { | |
ATTRS : { | |
surname : {}, | |
firstname : {} | |
} | |
}); | |
var Book = Y.Base.create('book', Y.Model, [], { | |
}, { | |
ATTRS : { | |
author : { | |
setter : Y.Model.reference(Author) | |
}, | |
title : { | |
setter : 'string' | |
}, | |
published : { | |
setter : 'date' | |
} | |
}, | |
RENDERERS : { | |
published : {fn : Y.Model.RENDER.DATE, cfg : {format : '%D'}}, | |
author : { | |
fn : function (val, key) { | |
return val.render('firstname') + ' ' + val.render('surname'); | |
} | |
} | |
} | |
}); | |
function sortAuthor (a, b, desc) { | |
var aName = a.surname, | |
bName = b.surname; | |
return Y.Sort.compare(aName, bName, desc); | |
} | |
var qm = new Y.QueryManagerLocal({ | |
sortedBy : 'author', | |
sortFunctions : { | |
author : sortAuthor | |
}, | |
datasource : ds, | |
model : Book | |
}); | |
var t = new Y.Table({ | |
sortColumn : 'author', | |
columns : Book.members() | |
}); | |
t.on('sortColumnChange', function (e) { | |
qm.set('sortedBy', e.newVal); | |
qm.fetch(); | |
}); | |
qm.after('results', function (e) { | |
t.set('data', e.results); | |
}); | |
t.render('#content'); | |
qm.fetch(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
YUI.add('model', function (Y) { | |
Y.Model = Y.Base.create('model', Y.Base, [], { | |
// These methods allow setters to be strings for primitive types | |
'string' : function (val, key) { | |
return String(val); | |
}, | |
'number' : function (val, key) { | |
return Number(val); | |
}, | |
'date' : function (val, key) { | |
return new Date(val); | |
}, | |
// @TODO : implement editors | |
edit : function (key) { | |
return this.constructor.EDITORS[key].call(this, this.get(key)); | |
}, | |
// Draws out the value for the given key using a supplied render function (or just returns the value) | |
render : function (key) { | |
var renderer = (this.constructor.RENDERERS ? this.constructor.RENDERERS[key] : null), | |
val = this.get(key); | |
if (renderer) { | |
if (Y.Lang.isFunction(renderer)) { | |
return renderer.call(this, val); | |
} else if (Y.Lang.isObject(renderer) && renderer.fn) { | |
return renderer.fn.call(this, val, renderer.cfg); | |
} | |
} | |
return val; | |
}, | |
// Compare if two instances are the same by turning them into objects and comparing them as JSON. | |
// Would be nice if we had md5 here... this may have problems though, if Model references are included, | |
// may just need to do top level comparison | |
compare : function (other) { | |
if (!other instanceof this.constructor) { | |
return false; | |
} | |
var selfHash = Y.JSON.stringify(this.toObject()), | |
otherHash = Y.JSON.stringify(other.toObject()); | |
return selfHash == otherHash; | |
}, | |
// Turns this model instance into a Javascript object which can be serialized into another data format | |
toObject : function () { | |
var c = this.constructor, | |
members = c.members(), | |
obj = {}; | |
Y.Array.each(members, function (member) { | |
obj[member] = this.get(member); | |
}, this); | |
return obj; | |
} | |
}, { | |
// @TODO : implement some default editors | |
EDIT : { | |
}, | |
// @TODO : implement more default renderers | |
RENDER : { | |
DATE : function (val, key, cfg) { | |
return Y.DataType.Date.format(val, cfg); | |
} | |
}, | |
// Class method for returning a list of all the member properties (ATTRS) of this constructor, | |
// up the inheritance chain | |
members : function () { | |
var c = this.prototype.constructor, | |
map = []; | |
while (c) { | |
try { | |
if (c.ATTRS) { | |
Y.Object.each(c.ATTRS, function (val, key) { | |
if (!val.readOnly) { | |
map.push(key); | |
} | |
}); | |
} | |
} catch (err) {} | |
c = (c.superclass ? c.superclass.constructor : null); | |
} | |
return map; | |
}, | |
// Utility method to create a reference to another Model constructor as the | |
// value to set for a property. | |
// @TODO : Look into making this lazy to a remote source | |
reference : function (model) { | |
if (model.prototype) { | |
function createModel (cfg, key, construct) { | |
try { | |
return new construct(cfg); | |
} catch (err) {} | |
} | |
return Y.rbind(createModel, this, model); | |
} | |
}, | |
// Same as above but creates an array of Models rather than just one | |
referenceMany : function (model) { | |
if (model.prototype) { | |
function createModels (cfg, key, construct) { | |
var data = []; | |
try { | |
Y.Array.each(cfg, function (o) { | |
data.push(new construct(o)); | |
}); | |
} finally { | |
return data; | |
} | |
} | |
return Y.rbind(createModels, this, model); | |
} | |
} | |
}); | |
// Allows the class method 'members' to be aggregated across all classes | |
// which inherit from Y.Model | |
Y.Base._buildCfg.custom.members = function (prop, r, s) { | |
var c = r.superclass.constructor; | |
while (c.superclass) { | |
if (c == Y.Model) { | |
r.members = Y.Model.members; | |
break; | |
} | |
c = c.superclass.constructor; | |
} | |
}; | |
}, '', {requires : ['base-build', 'datatype-date', 'json-stringify']}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
YUI.add('query-manager', function (Y) { | |
// Taken more or less verbatim from YUI 2 | |
Y.namespace('Sort').compare = function (a, b, desc) { | |
if((a === null) || a === undefined) { | |
if((b === null) || b === undefined) { | |
return 0; | |
} | |
else { | |
return 1; | |
} | |
} else if((b === null) || b === undefined) { | |
return -1; | |
} | |
if(Y.Lang.isString(a)) { | |
a = a.toLowerCase(); | |
} | |
if(Y.Lang.isString(b)) { | |
b = b.toLowerCase(); | |
} | |
if(a < b) { | |
return (desc) ? 1 : -1; | |
} | |
else if (a > b) { | |
return (desc) ? -1 : 1; | |
} | |
else { | |
return 0; | |
} | |
}; | |
Y.QueryManagerBase = Y.Base.create('query-manager', Y.Base, [], { | |
// Takes an array of results and turns them into an ArrayList | |
// of model instances | |
_processResults : function (results) { | |
var resultSet = [], | |
model = this.get('model'); | |
Y.Array.each(results, function (result) { | |
var m = new model(result); | |
if (m) { | |
resultSet.push(m); | |
} | |
}); | |
this.fire('results', { | |
results : (new Y.ArrayList(resultSet)) | |
}); | |
}, | |
initializer : function () { | |
this.publish('results'); | |
}, | |
// Makes the request to the datasource | |
fetch : function (request) { | |
var ds = this.get('datasource'); | |
request = request || ''; | |
ds.sendRequest({ | |
request : request, | |
callback : { | |
success : Y.bind(function (e) { | |
this._processResults(e.response.results); | |
}, this) | |
} | |
}); | |
} | |
}, { | |
ATTRS : { | |
model : {}, | |
datasource : { | |
setter : function (val, key) { | |
var model = this.get('model'); | |
if(model && val.schema) { | |
var fields = model.members(), | |
currentSchema = val.schema.get('schema') || {}; | |
newSchema = Y.merge(currentSchema, { | |
resultFields : fields | |
}); | |
val.schema.set('schema', newSchema); | |
} | |
} | |
} | |
} | |
}); | |
// For use in any case where all data is local (ie: no AJAX request required) | |
Y.QueryManagerLocal = Y.Base.create('query-manager-local', Y.QueryManagerBase, [], { | |
// Sorts the results as defined by the config before processing them | |
_processResults : function (results) { | |
var sortedBy = this.get('sortedBy'), | |
sortDesc = this.get('sortDesc'), | |
sortFunctions = this.get('sortFunctions'), | |
sortFn = sortFunctions[sortedBy] || Y.Sort.compare; | |
results.sort(Y.bind(function (a, b) { | |
return sortFn.call(this, a[sortedBy], b[sortedBy], sortDesc); | |
}, this)); | |
Y.QueryManagerLocal.superclass._processResults.call(this, results); | |
}, | |
initializer : function () { | |
// If we sort on the same col we already have selected, we just reverse the order | |
this.on('sortedByChange', function (e) { | |
var sortDesc = this.get('sortDesc'); | |
this.set('sortDesc', (e.newVal == e.prevVal ? (!sortDesc) : this.get('defaultSortDesc'))); | |
}, this); | |
} | |
}, { | |
ATTRS : { | |
defaultSortDesc : { | |
value : false | |
}, | |
sortFunctions : {}, | |
sortDesc : { | |
valueFn : function () { | |
return this.get('defaultSortDesc'); | |
} | |
}, | |
sortedBy : { | |
valueFn : function () { | |
var model = this.get('model'); | |
if (model) { | |
return model.members()[0]; | |
} | |
} | |
} | |
} | |
}); | |
}, '', {requires : ['collection', 'base-build']}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment