Skip to content

Instantly share code, notes, and snippets.

@snit-ram
Created January 17, 2013 17:49

Revisions

  1. snit-ram created this gist Jan 17, 2013.
    204 changes: 204 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,204 @@
    /*
    * 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;
    };
    })();