API Docs for: 0.10.0
Show:

File: lib/utils.js

// Copyright 2014-2015, Yahoo! Inc.
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms.

var _ = require('underscore');

/**
 * @class utils
 */

/**
 * An extend function that applies the result of a callback to each item
 *
 * @method extendApply
 * @param {object} obj Destination object to merge into
 * @param {object[]} objects Objects that should get merged into the destination object
 * @param {function} [fn] Apply function for each item, returning the final result
 * @return {object} Destination object
 */
var extendApply = function (obj, objects, fn) {
	fn = fn || function (item /* , previousItem, obj, objectIndex, valueIndex */) {
		return item;
	};
	objects.forEach(function (currentObject, objectIndex) {
		if (currentObject) {
			_.keys(currentObject).forEach(function (key, valueIndex) {
				obj[key] = fn(currentObject[key], obj[key], {
					key: key, currentObject: currentObject, objectIndex: objectIndex, valueIndex: valueIndex
				});
			});
		}
	});
	return obj;
};

/**
 * Deep-extend of an object
 *
 * @method deepExtend
 * @param {object} obj
 * @param {object[]} objects
 * @param {object} [options]
 * @param {boolean} [options.replace=false]
 * @return {object}
 */
var deepExtend = function (obj, objects, options) {
	options = options || {};
	objects.forEach(function (currentObject) {
		if (currentObject) {
			_.keys(currentObject).forEach(function (key) {
				var i, len;
				if ((_.isArray(obj[key]) || !obj[key]) && _.isArray(currentObject[key])) {
					if (options.replace) {
						obj[key] = deepExtend(obj[key] || [], [currentObject[key]]);
					} else {
						obj[key] = (obj[key] || []);
						for (i = 0, len = currentObject[key].length; i < len; i++) {
							if (_.isArray(currentObject[key][i])) {
								obj[key].push(deepExtend([], [currentObject[key][i]]));
							} else if (_.isObject(currentObject[key][i])) {
								obj[key].push(deepExtend({}, [currentObject[key][i]]));
							} else {
								obj[key].push(currentObject[key][i]);
							}
						}
					}
				} else if (_.isFunction(currentObject[key])) {
					obj[key] = currentObject[key];
				} else if ((_.isObject(obj[key]) || !obj[key]) && _.isObject(currentObject[key])) {
					obj[key] = deepExtend(obj[key] || {}, [currentObject[key]]);
				} else {
					obj[key] = currentObject[key];
				}
			});
		}
	});
	return obj;
};

/**
 * Wraps a function into another function that sets another function as the __super() function
 * This is used to wrap every single function of an object so that one can call
 *
 * this.__super();
 *
 * to call its parent function that was overwritten.
 *
 * @method superWrapper
 * @param {*} currentItem
 * @param {*} previousItem
 * @return {*}
 */
var superWrapper = function (currentItem, previousItem) {

	if (_.isFunction(currentItem) && (!previousItem || _.isFunction(previousItem))) {

		previousItem = previousItem || function () {
		};

		return function () {
			var result, self = this, oldSuper = self.__super;

			self.__super = function () {
				return previousItem.apply(self, arguments);
			};
			result = currentItem.apply(self, arguments);
			self.__super = oldSuper;

			return result;
		};

	} else {
		return currentItem;
	}
};

/**
 * Combines multiple strings into one, making sure that the glue-string doesn't get applied when not required
 *
 * @method combine
 * @param {string} glue
 * @param {string} str1
 * @return {string}
 */
var combine = function (glue, str1 /*, ... */) {
	var args = Array.prototype.slice.call(arguments, 2), result = str1;

	args.forEach(function (arg) {
		if ((result.substr(-1) === glue) && (arg.substr(0, 1) === glue)) {
			result += arg.substr(1);
		} else if ((result.substr(-1) === glue) || (arg.substr(0, 1) === glue)) {
			result += arg;
		} else {
			result += glue + arg;
		}
	});

	return result;
};

/**
 * Turns a string into a filesystem safe filename
 *
 * @method fileNameSafe
 * @param {string} str
 * @return {string}
 */
var fileNameSafe = function (str) {
	return str.replace(/[^a-zA-Z\d]/g, '-');
};

/**
 * Safely requires a module
 *
 * @method require
 * @param {string} module Module name or path
 * @param {*} [defaultValue] Default value if the module cannot be found
 * @return {*}
 */
var requir = function (module, defaultValue) {
	try {
		return require(module);
	} catch (err) {
		if (defaultValue === undefined) {
			throw new Error("Cannot find module: " + module);
		}
		return defaultValue;
	}
};

module.exports = {
	superWrapper: superWrapper,
	extendApply: extendApply,
	deepExtend: deepExtend,
	combine: combine,
	fileNameSafe: fileNameSafe,
	require: requir
};