Skip to content

Instantly share code, notes, and snippets.

@snit-ram
Created January 17, 2013 17:49
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 snit-ram/4557947 to your computer and use it in GitHub Desktop.
Save snit-ram/4557947 to your computer and use it in GitHub Desktop.
Javascript port of object selector originally in php
/*
* Copyright (c) 2011 Yahoo! Inc. All rights reserved.
*/
/*jslint nomen: true */
(function () {
'use strict';
function mix(target, source){
var attribute;
for(attribute in source){
if(source.hasOwnProperty(attribute)){
target[attribute] = source[attribute];
}
}
return target
}
window.Selector = function Selector(data) {
var selectorInstance = function () {
return selectorInstance.__invoke.apply(selectorInstance, arguments);
};
if (typeof data === 'string') {
data = JSON.parse(data);
}
mix(selectorInstance, {
data: data,
focus: function (path) {
var pathParts = path.split('.'),
data = this.data,
self = this;
pathParts.forEach(function (attribute) {
if (!self.isset(data) || !self.isset(data[attribute])) {
data = null;
return;
}
data = data[attribute];
});
return Selector(data);
},
__invoke: function (path, defaultValue) {
path = this.clearPath(path);
switch (this.askingFor(path)) {
case 'list':
defaultValue = defaultValue === undefined ? [] : defaultValue;
return this.getList(path, defaultValue);
case 'dictionary':
return this.getDictionaryFromPath(path);
default:
return this.getOne(path, defaultValue);
}
},
findOne: function (contextPath, fieldPath, value) {
var items = this.findAll(contextPath, fieldPath, value);
return items[0];
},
findAll: function (contextPath, fieldPath, value) {
var contextObjects = this.getAll(contextPath),
foundObjects = contextObjects.filter(function (item) {
var contextParser = Selector(item),
foundValues = contextParser("[" + fieldPath + "]");
return foundValues.indexOf(value) > -1;
});
return foundObjects;
},
isList: function (data) {
return data instanceof Array;
},
//protected from here
clearPath: function (path) {
return path.replace(/\s+/g, '');
},
askingFor: function (path) {
var posFirstChar = 0,
posLastChar = path.length - 1;
if (path.indexOf('[') === posFirstChar && path.indexOf(']') === posLastChar) {
return 'list';
}
if (path.indexOf('{') === posFirstChar && path.indexOf('}') === posLastChar) {
return 'dictionary';
}
return 'one';
},
getList: function (path, defaultValue) {
path = path.replace(/\[|\]/g, '');
return this.getAll(path, defaultValue);
},
getDictionaryFromPath: function (path) {
var keys, values, pathParts;
path = path.replace(/\{|\}/g, '');
pathParts = path.split(':');
keys = pathParts[0];
values = pathParts[1];
return this.getDictionary(keys, values);
},
getOne: function (path, defaultValue) {
var results = this.getAll(path);
return results[0] !== undefined ? results[0] : defaultValue;
},
getAll: function (path, defaultValue) {
var self = this,
orToken = '|',
possiblePaths = path.split(orToken),
result,
possiblePath;
defaultValue = defaultValue !== undefined ? defaultValue : [];
possiblePaths.forEach(function (possiblePath) {
if (result !== undefined) { return; }
result = self.getAllFromPath(possiblePath);
});
if (result !== undefined) {
return result;
}
return defaultValue;
},
getAllFromPath: function (path) {
var self = this,
pathParts = path.split('.'),
results = [],
data = this.data;
pathParts.forEach(function (attribute) {
if (data === undefined) { return; }
results = data = self.getAllWithAttribute(data, attribute);
});
return results.length === 0 ? undefined : results;
},
getAllWithAttribute: function (data, attribute) {
var results = [],
self = this;
data = data instanceof Array ? data : [data];
data.forEach(function (item) {
if (!self.isset(item)) { return; }
if (!self.isset(item[attribute])) { return; }
if (self.isList(item[attribute])) {
results = results.concat(item[attribute]);
} else {
results.push(item[attribute]);
}
});
return results;
},
isset: function (data) {
return data !== undefined && data !== null;
},
getDictionary: function (keysPath, valuesPath) {
var keys = this.getAll(keysPath),
values = this.getAll(valuesPath, []),
result = {};
if (!keys || !(keys instanceof Array) || !keys.length) {
return {};
}
keys.forEach(function (key, position) {
result[key] = values[position] === undefined ? null : values[position];
});
return result;
}
});
return selectorInstance;
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment