tbranyen/combyne

View on GitHub
lib/shared/map.js

Summary

Maintainability
A
2 hrs
Test Coverage
/**
 * Iterates various JavaScript types.
 *
 * @module utils/map
 * @requires utils/type
 * @requires utils/create_object
 */
define(function(require, exports, module) {
  "use strict";

  // Utils.
  var type = require("../utils/type");
  var createObject = require("../utils/create_object");

  // Support.
  require("../support/array/is_array");

  /**
   * Allows iteration of an Array, Arguments, NodeList, or plain Object.
   *
   * @memberOf module:utils/map
   * @param {*} obj - Object or Array to iterate.
   * @param {String} index - An identifier name for index.
   * @param {String} value - An identifier name for value.
   * @param {object} data - Data from parent scope.
   * @param {Function} iterator - Function that is called within the template.
   * @returns {Array} String output to be joined.
   */
  function map(obj, index, value, data, iterator) {
    var isArrayLike = type(obj) === "arguments" || type(obj) === "nodelist";
    var isArray = Array.isArray(obj) || isArrayLike;
    var output = [];
    var dataObject;

    // Iteration branch if Array.
    if (isArray) {
      // Make a clone of the Array to operate on, also potentially coercing.
      obj = [].slice.call(obj);

      for (var i = 0; i < obj.length; i++) {
        // Create a new scoped data object.
        dataObject = createObject(data);
        dataObject[index] = i;

        if (value) {
          dataObject[value] = obj[i];
        }
        // If no value was supplied, use this object to key off of.
        else {
          dataObject = obj[i];
        }

        // Add return value of iterator function to output.
        output.push(iterator(dataObject));
      }

      return output;
    }
    // Iteration branch if Object.
    else {
      for (var key in obj) {
        if (!obj.hasOwnProperty(key)) {
          continue;
        }

        // Create a new scoped data object.
        dataObject = createObject(data);
        dataObject[index] = key;

        if (value) {
          dataObject[value] = obj[key];
        }
        // If no value was supplied, use this object to key off of.
        else {
          dataObject = obj[key];
        }

        // Add return value of iterator function to output.
        output.push(iterator(dataObject));
      }

      return output;
    }
  }

  module.exports = map;
});