API Docs for:
Show:

File: development/js/utils/enums.js

import type from './type';
import arrays from './array';

/**
 * Provides functions for enumerables (object/arrays)
 *
 * @module Utils
 * @class Utils.Enums
 * @static
 */

/**
 * Allows to iterate over any enumerable with a function taking up to three
 *     arguments
 *
 * @method each
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} [scope] Optional context to execute the given function in
 * @return {undefined} This returns just nothing
 *
 * @example
 *     import {each} from './utils/enums';
 * 
 *     var colors = {red: '#f00', green: '#0f0'},
 *         result = '';
 *
 *     each(colors, function (colorValue, colorName, allColors) {
 *          result += colorName + ' has HEX of ' + colorValue + '<br>';
 *     });
 *
 *     result;
 *     // -> 'green has HEX of #0f0<br>red has HEX of #f00<br>'
 */
export const each = function (list, fn, scope) {
    if (type.isObject(list)) {
        return Object.keys(list).forEach(function (key) {
            fn.call(scope || null, list[key], key, list);
        });
    }

    if (type.isSeq(list)) {
        return arrays.toArray(list).forEach(fn, scope || null);
    }
}

/**
 * Allows to map a function over a enumerable
 *
 * @method map
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} [scope] Optional context to execute the given function in
 * @return {array} The mapping
 *
 * @example
 *     import {map} from './utils/enums';
 *     
 *     var result = map([1, 2, 3], function (n) {
 *         return n * n;
 *     });
 *
 *     result;
 *     // -> [1, 4, 9]
 */
export const map = function (list, fn, scope) {
    var _mapped = [];
    each(list, function (item, id, seq) {
        _mapped.push(fn.call(scope || null, item, id, seq));
    });
    return _mapped;
}

/**
 * Allows to filter any enumerable with a function
 *
 * @method filter
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} [scope] Optional context to execute the function in
 * @return {array} Filtered enumerable
 *
 * @example
 *     import {filter} from './utils/enums';
 *     
 *     var result = filter([1, 2, 3], function (n) {
 *         return n % 2 !== 0;
 *     });
 *
 *     result;
 *     // -> [1, 3]
 */
export const filter = function (list, fn, scope) {
    var _filtered = [];
    each(list, function (item, id, seq) {
        if (fn.call(scope || null, item, id, seq)) {
            _filtered.push(item);
        }
    });
    return _filtered;
}

/**
 * Allows to reduce or fold a enumerable into a single value
 *
 * @method reduce
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} seed Starting value
 * @param {*} [scope] Optional context to execute the function in
 * @return {*} Depends on seed
 *
 * @example
 *     import {reduce} from './utils/enums';
 *     
 *     var add = function (a, b) { return a + b; };
 *     
 *     var result = reduce(['hallo', ' ', 'welt'], add, '');
 *
 *     result;
 *     // -> 'hallo welt'
 */
export const reduce = function (list, fn, seed, scope) {
    var _base = seed;
    each(list, function (item, id, seq) {
        _base = fn.call(scope || null, _base, item, id, seq);
    });
    return _base;
}

/**
 * Allows to reduce or fold a enumerable into a single value from right
 *
 * @method reduceRight
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} seed Starting value
 * @param {*} [scope] Optional context to execute the function in
 * @return {*} Depends on seed
 *
 * @example
 *     import {reduceRight} from './utils/enums';
 *     
 *     var add = function (a, b) { return a + b; };
 *
 *     var result = reduceRight(['hallo', ' ', 'welt'], div, '');
 *
 *     result;
 *     // -> 'welt hallo'
 */
export const reduceRight = function (list, fn, seed, scope) {
    if (type.isSeq(list)) {
        return reduce(arrays.toArray(list).reverse(), fn, seed, scope);
    }
    return reduce(list, fn, seed, scope);
}

/**
 * Evaluates each item in a enumerable against a predicate function until
 *     the first truthy evaluation is encountered, returns true if at least
 *     one item evaluates to true
 *
 * @method some
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} [scope] Optional scope to execute the function in
 * @return {boolean} True if one item evaluates to true, false otherwise
 *
 * @example
 *     import {some} from './utils/enums';
 * 
 *     var betweenTwoAndFive = function (n) {
 *         return n >= 2 && n <= 5;
 *     };
 *
 *     var result = some([1, 3, 10], betweenTwoAndFive);
 *
 *     result;
 *     // -> true
 */
export const some = function (list, fn, scope) {
    var _i;

    if (type.isObject(list)) {
        for (_i in list) {
            if (list.hasOwnProperty(_i) && !!fn.call(scope || null, list[_i], _i, list)) {
                return true;
            }
        }
        return false;
    }

    if (type.isSeq(list)) {
        return arrays.toArray(list).some(fn, scope || null);
    }

    return false;
}

/**
 * Evaluates each item in a enumerable against a predicate function. Returns
 *     false as soon as the first falsy evaluation is encountered. Does only
 *     return true if all items evaluate to true
 *
 * @method every
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The iteration function
 * @param {*} [scope] Optional context to execute the function in
 * @return {boolean} True if all evaluations are truthy, false otherwise
 *
 * @example
 *     import {every} from './utils/enums';
 *     
 *     var betweenTwoAndFive = function (n) {
 *         return n >= 2 && n <= 5;
 *     };
 *
 *     var result = every([2, 3, 4], betweenTwoAndFive);
 *
 *     result;
 *     // -> true
 */
export const every = function (list, fn, scope) {
    var _i;
    if (type.isObject(list)) {
        for (_i in list) {
            if (list.hasOwnProperty(_i) && !fn.call(scope || null, list[_i], _i, list)) {
                return false;
            }
        }
        return true;
    }

    if (type.isSeq(list)) {
        return arrays.toArray(list).every(fn, scope || null);
    }

    return false;
}

/**
 * Returns the index of a given item inside a enumerable from the left
 *
 * @method indexOf
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {*} item The item to compare against
 * @return {number} Index or key, -1 if not in enumerable
 *
 * @example
 *     import {indexOf} from './utils/enums';
 *     
 *     var list = [1, 2, 3, 2, 1];
 *
 *     indexOf(list, 2);
 *     // -> 1
 */
export const indexOf = function (list, item) {
    var _i;
    if (type.isObject(list)) {
        for (_i in list) {
            if (list.hasOwnProperty(_i) && list[_i] === item) {
                return _i;
            }
        }
        return -1;
    }

    if (type.isSeq(list)) {
        return arrays.toArray(list).indexOf(item);
    }

    return -1;
}

/**
 * Returns the index of a given item inside a enumerable from the right
 *
 * @method lastIndexOf
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {*} item The item to compare against
 * @return {number} Index or key, -1 if not in enumerable
 *
 * @example
 *     import {lastIndexOf} from './utils/enums';
 *     
 *     var list = [1, 2, 3, 2, 1];
 *
 *     lastIndexOf(list, 2);
 *     // -> 3
 */
export const lastIndexOf = function (list, item) {
    var _i;
    if (type.isObject(list)) {
        for (_i in list) {
            if (list.hasOwnProperty(_i) && list[_i] === item) {
                return _i;
            }
        }
        return -1;
    }

    if (type.isSeq(list)) {
        return arrays.toArray(list).lastIndexOf(item);
    }

    return -1;
}

/**
 * Finds the first item in a enumerable from the left which evaluates truthy
 *     by applying a predicate to it
 *
 * @method find
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The predicate function
 * @param {*} [scope] Optional context to execute the predicate in
 * @return {*} First item from the left if available
 *
 * @example
 *     import {find} from './utils/enums';
 *     
 *     const startsWith = (x) => (y) => y[0] === x;
 *
 *     find(['a1', 'b1', 'a2', 'b2'], startsWith('b'));
 *     // -> 'b1'
 */
export const find = function (list, fn, scope) {
    return arrays.first(filter(list, fn, scope));
}

/**
 * Finds the first item in a enumerable from the right which evaluates truthy
 *     by applying a predicate to it
 *
 * @method findLast
 * @for Utils.Enums
 * @param {string|array|array-like|object} list The enumerable
 * @param {function} fn The predicate function
 * @param {*} [scope] Optional context to execute the predicate in
 * @return {*} First item from the right if available
 *
 * @example
 *     import {findLast} from './utils/enums';
 *     
 *     const startsWith = (x) => (y) => y[0] === x;
 *
 *     findLast(['a1', 'b1', 'a2', 'b2'], startsWith('b'));
 *     // -> 'b2'
 */
export const findLast = function (list, fn, scope) {
    return arrays.last(filter(list, fn, scope));
}



export default {
    each, map, filter, reduce, reduceRight, every,
    some, find, findLast, indexOf, lastIndexOf
};