Skip to content

Instantly share code, notes, and snippets.

@madbook
Created December 22, 2012 14:42
Show Gist options
  • Save madbook/4359133 to your computer and use it in GitHub Desktop.
Save madbook/4359133 to your computer and use it in GitHub Desktop.
/**
* creates an array-like list of items. each item can have multiple 'terms'
* associated with it, and you can filter the list of items down by accessing
* those terms as properties of the object. To get the results of the query
* just end with parens, like:
*
* myObj.foo.bar() = [all objects with foo and bar terms];
*
* passing in values into the function call will add them as values with the
* current query as their terms. so
*
* myObj.foo.bar(fooBarObject);
*
* adds fooBarObject with terms 'foo' and 'bar', as well as returns an array of
* all 'foo' and 'bar' objects (including the new one); any number of values
* can be passed.
*
* It also doesn't matter what order you query in
*
* myObj.foo.bar();
* myObj.bar.foo();
*
* passing in arguments when there is no query adds the arguments as new terms.
* These should be strings only!
*
* myObj('bat'); // adds new 'bat' term
*
* query state is saved until function is called.
*
* myObj.foo;
* myObj.bar(); // returns result of 'foo' and 'bar'!
*
* to clear query state, just call the function with no arguments
*
* myObj(); // returns current query and resets query state
*
* still to do!
* - modify terms associated with values in the list after setting
* could revert to returning an array of objects, but thats less cool
* - array-like methods (push, pop, splice, etc)
* - setter functions, what does myObj.foo.bar = 1; do?
*
*/
function MultiDimensionalList () {
var terms = [];
var items = [];
var query = [];
var search = []; // items list filtered by query;
var filter = MultiDimensionalList.filter; // local reference to filter method
var map = MultiDimensionalList.map; // local reference to map method
var list = function (/* terms */) {
var args = Array.prototype.slice.call(arguments);
var i, l;
var item;
if (query.length) {
// add new items with current query as terms
for (i = 0, l = args.length; i < l; i++) {
item = { value: args[i], terms : query.slice() };
items.push(item);
search.push(item);
}
} else {
// add new terms
for (i = 0, l = args.length; i < l; i++) {
if (terms.indexOf(args[i])===-1) {
terms.push(args[i]);
}
}
// add new property getters
for (i = 0, l = args.length; i < l; i++) {
(function (prop) {
Object.defineProperty(list, prop, {
get : function () {
if (query.indexOf(prop)==-1)
query.push(prop);
search = filter(search, query);
return list;
},
set : function (v) {
// what to do here?
// myArray.foo.bar.js = ??? what makes sense here? full replace?
}
});
})(args[i]);
}
}
// any time we call the list object as a function, we
// do the necessary work (add new things) then return
// the results of the current query and reset
var res = search.map(map);
query = [];
search = items.slice();
return res;
};
list.apply(this, Array.prototype.slice.call(arguments));
return list;
}
MultiDimensionalList.filter = function (search, query) {
var i, l, j, k, _in;
var res = [];
for (i = 0, l = search.length; i < l; i++) {
_in = true;
for (j = 0, k = query.length; j < k; j++) {
if (search[i].terms.indexOf(query[j])==-1) _in = false;
}
if (_in) res.push(search[i]);
}
return res;
};
MultiDimensionalList.map = function (item) {
return item.value;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment