Skip to content

Instantly share code, notes, and snippets.

@atuttle
Created November 15, 2012 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save atuttle/4080686 to your computer and use it in GitHub Desktop.
Save atuttle/4080686 to your computer and use it in GitHub Desktop.
Pagination plugin & Query plugin, sitting in a tree...
/*
Confused? Start here: http://brian.io/lawnchair/
This plugin takes two awesome other plugins and mashes their naughty bits together.
Queries are awesome. Pagination is awesome. Paginated Queries are awesome^2.
I take no credit for any of the heavy lifting done here, all I did was take two genius
things and smash them together.
*/
// - NOT jsonPath or jsonQuery which are horrendously complex and fugly
// - simple query syntax 'its just javascript'
// - simple string interpolation
// - search then sorting
Lawnchair.plugin((function(){
//
var interpolate = function(template, args) {
var parts = template.split('?').filter(function(i) { return i != ''})
, query = ''
for (var i = 0, l = parts.length; i < l; i++) {
query += parts[i] + args[i]
}
return query
}
var sorter = function(p) {
return function(a, b) {
if (a[p] < b[p]) return -1
if (a[p] > b[p]) return 1
return 0
}
}
//
return {
// query the storage obj
where: function() {
// ever notice we do this sort thing lots?
var args = [].slice.call(arguments)
, tmpl = args.shift()
, last = args[args.length - 1]
, qs = tmpl.match(/\?/g)
, q = qs && qs.length > 0 ? interpolate(tmpl, args.slice(0, qs.length)) : tmpl
, is = new Function(this.record, 'return !!(' + q + ')')
, r = []
, cb
// iterate the entire collection
// TODO should we allow for chained where() to filter __results? (I'm thinking no b/c creates funny behvaiors w/ callbacks)
this.all(function(all){
for (var i = 0, l = all.length; i < l; i++) {
if (is(all[i])) r.push(all[i])
}
})
// overwrite working results
this.__results = r
// callback / chain
if (args.length === 1) this.fn(this.name, last).call(this, this.__results)
return this
},
// FIXME should be able to call without this.__results
// ascending sort the working storage obj on a property (or nested property)
asc: function(property, callback) {
this.fn(this.name, callback).call(this, this.__results.sort(sorter(property)))
return this
},
// descending sort on working storage object on a property
desc: function(property, callback) {
this.fn(this.name, callback).call(this, this.__results.sort(sorter(property)).reverse())
return this
},
//mash in the page method from the pagination plugin
page: function (page, callback) {
// some defaults
var objs = []
, count = 20 // TODO make this configurable
, cur = ~~page || 1
, next = cur + 1
, prev = cur - 1
, start = cur == 1 ? 0 : prev*count
, end = start >= count ? start+count : count
// grab all the records
// FIXME if this was core we could use this.__results for faster queries
objs = this.__results
// grab the metadata
var max = Math.ceil(objs.length/count)
, page = { max: max
, next: next > max ? max : next
, prev: prev == 0 ? 1 : prev
}
// reassign to the working resultset
this.__results = page[this.name] = objs.slice(start, end)
// callback / chain
if (callback) this.fn('page', callback).call(this, page)
return this
}
}
/////
})())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment