<commit_before>/**
 * rc.js - Row/Column Conversions
 * v0.06 - Proxy fixes
 */

(function(root){
	"use strict";

	/**
	 * Create an object and add a .commit() prototype to place the values back into the original.
	 * Useful for moving simple data types around. Objects and arrays will be automatically referenced.
	 * @constructor
	 * @param obj - A columnar object
	 * @param {number} index - The index to convert into a row-based object
	 * @param {Boolean} [clearUndef] - Clear undefined attributes when copying the object.
	 */
	var Proxy = (function() {
			var __obj = [],
				__idx = [],
				__clr = [],
				__this = [],
				guid = 0;

		function __getId(proxy) {
			var i = __this.length, pid;

			// Most likely to be at the end, so start there
			for (;i;) {
				i--;
				if (__this[i] === proxy) {
					pid = i;
					break;
				}
			}

			if (pid === undefined) {
				throw new ReferenceError("Proxy is finalized and cannot be used again.");
			}
			return pid;
		}

		function Proxy(obj, index, clearUndef) {

			var att;

			// Increment the guid
			++guid;

			// Set the private data.
			__obj[guid] = obj;
			__idx[guid] = index;
			__clr[guid] = clearUndef;
			__this[guid] = this;

			for ( att in obj ) {
				if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][index] !== undefined ) ) {
					this[att] = obj[att][index];
				}
			}
		}

		// Defined inside the constructor to give it access to the originating object and parameters
		Proxy.prototype.commit = function(){
			var guid = __getId(this),
				obj = __obj[guid],
				index = __idx[guid],
				clearUndef = __clr[guid],
				att;

			for ( att in this ) {
				if ( att !== '__rcProxyId' && this.hasOwnProperty(att) && ( !clearUndef || this[att] !== undefined ) ) {
					obj[att][index] = this[att];
				}
			}
		};

		Proxy.prototype.destroy = function() {
			var guid = __getId(this);
			delete __this[guid];
			delete __obj[guid];
			delete __idx[guid];
			delete __clr[guid];
		};

		Proxy.prototype.finalize = function() {
			this.commit();
			this.destroy();
		};

		return Proxy;
	})();

	var Opt = Object.prototype.toString,
		self = {
		array: {
			getIndexes: function(array, filter) {
				var indexes = [],
					len = array.length,
					isFn = (typeof filter === 'function'),
					i;

				if (isFn) {
					for (i = 0; i < len; i++) {
						if ( filter(i, array[i]) ) {
							indexes.push(i);
						}
					}
				} else {
					for (i = 0; i < len; i++) {
						if ( array[i] === filter ) {
							indexes.push(i);
						}
					}
				}
			},
			getByIndexes: function(array, indexes) {
				var len = indexes.length,
					data = [];

				for (;len;) {
					len--;
					data[len] = array[indexes[len]];
				}
				return data;
			},
			rotate: function(arr, result, limited, softFail) {
				var obj, i, att;

				// Not an array? Send it back.
				if ( Opt.call(arr) !== '[object Array]' ) {
					throw new TypeError("RC: Argument is not an array");
				}

				// Clean truthy/falsy values & undefined
				limited = !!limited;
				softFail = !!softFail;

				if ( !!result || typeof result !== 'object' ) {
					if ( limited ) {
						throw new TypeError("RC: Must pass a result object when 'limited' is true");
					} else {
						result = {};
					}
				}

				i = arr.length;

				for (;i;) {
					i--;
					obj = arr[i];

					// All variables submit to for-in loops
					for (att in obj) {
						if ( obj.hasOwnProperty(att) ) {
							if ( result[att] === undefined ) {
								if ( limited ) {
									continue;
								} else {
									result[att] = [];
								}
							}
							result[att][i] = obj[att];
						}
					}
				}
				return result;
			}
		},
		object: {
			filter: function(obj, field, filter) {
				return self.object.filterMerge(obj, self.object.filterIndexes(obj, field, filter));
			},
			filterIndexes: function(obj, field, filter) {
				var indexes = false;

				if ( obj.hasOwnProperty(field) ) {
					indexes = self.array.getIndexes(obj[field], filter);
				}
				return indexes;
			},
			filterMerge: function(obj, indexes) {
				var result = {},
					att;

				if ( indexes ) {
					for (att in obj) {
						if ( obj.hasOwnProperty(att) ) {
							result[att] = self.array.getByIndexes(obj[att], indexes);
						}
					}
				}
				return result;
			},
			rotate: function(obj, result, clearUndef) {
				var att, i, len = 0;

				// Not an array? Send it back.
				if ( typeof obj !== 'object' ) {
					throw new TypeError("RC: Argument is not an object");
				}

				if ( result === undefined ) {
					result = [];
				} else if ( Object.prototype.toString.call(result) !== '[object Array]' ) {
					throw new TypeError("RC: Result argument is an array");
				}

				// Get the longest length of all properties
				for (att in obj) {
					if ( obj.hasOwnProperty(att) ) {
						len = Math.max(len, att.length);
					}
				}

				for (i = 0; i < len; i++) {
					if ( result[i] === undefined ) {
						result[i] = {};
					} else if ( typeof result[i] !== 'object' ) {
						throw new TypeError("RC: Result contains incorrect type at index " + i);
					}

					for (att in obj) {
						if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][i] !== undefined ) ) {
							result[i][att] = obj[att][i];
						}
					}
				}

				return result;
			},
			objFromIndex: function(obj, index, clearUndef) {
				return new Proxy(obj, index, clearUndef);
			},
			proxy: function(obj, index, clearUndef) {
				return new Proxy(obj, index, clearUndef);
			}
		},
		rotate: function(obj) {
			// Generic, which directs to the appropriate array/object rotate
			if (typeof obj !== 'object') throw new TypeError("RC: rotate requires an object or an array");
			if ( Opt.call(obj) === '[object Array]' ) {
				return self.array.rotate.apply(this, arguments);
			} else {
				return self.object.rotate.apply(this, arguments);
			}
		},
		version: 'v0.05'
	};

	root.rc = self;

	// Can we build a chaining mode?
	// Should we move this into the same namespace?
	/**
	 * @constructor
	 * @param obj - A (hopefully) columnar object
	 * @param {Boolean} [clearUndef] - Clear undefined attributes when copying the object.
	 */
	root.RC = function(obj, clearUndef) {
		var att;

		for ( att in obj ) {
			if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att] !== undefined ) ) {
				this[att] = obj[att];
			}
		}
	};

	root.RC.prototype.filter = function(field, filter) {
		return new root.RC(self.object.filter(this, field, filter));
	};
	root.RC.prototype.proxy = function(index, clearUndef) {
		return self.object.proxy(this, index, clearUndef);
	};
	root.RC.prototype.rotate = function(mergeObj, clearUndef) {
		return self.object.rotate(this, mergeObj, clearUndef);
	};
}(this));<commit_msg>v0.06<commit_after>/**
 * rc.js - Row/Column Conversions
 * v0.06 - Proxy fixes
 */

(function(root){
	"use strict";

	/**
	 * Create an object and add a .commit() prototype to place the values back into the original.
	 * Useful for moving simple data types around. Objects and arrays will be automatically referenced.
	 * @constructor
	 * @param obj - A columnar object
	 * @param {number} index - The index to convert into a row-based object
	 * @param {Boolean} [clearUndef] - Clear undefined attributes when copying the object.
	 */
	var Proxy = (function() {
			var __obj = [],
				__idx = [],
				__clr = [],
				__this = [],
				guid = 0;

		function __getId(proxy) {
			var i = __this.length, pid;

			// Most likely to be at the end, so start there
			for (;i;) {
				i--;
				if (__this[i] === proxy) {
					pid = i;
					break;
				}
			}

			if (pid === undefined) {
				throw new ReferenceError("Proxy is finalized and cannot be used again.");
			}
			return pid;
		}

		function Proxy(obj, index, clearUndef) {

			var att;

			// Increment the guid
			++guid;

			// Set the private data.
			__obj[guid] = obj;
			__idx[guid] = index;
			__clr[guid] = clearUndef;
			__this[guid] = this;

			for ( att in obj ) {
				if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][index] !== undefined ) ) {
					this[att] = obj[att][index];
				}
			}
		}

		// Defined inside the constructor to give it access to the originating object and parameters
		Proxy.prototype.commit = function(){
			var guid = __getId(this),
				obj = __obj[guid],
				index = __idx[guid],
				clearUndef = __clr[guid],
				att;

			for ( att in this ) {
				if ( att !== '__rcProxyId' && this.hasOwnProperty(att) && ( !clearUndef || this[att] !== undefined ) ) {
					obj[att][index] = this[att];
				}
			}
		};

		Proxy.prototype.destroy = function() {
			var guid = __getId(this);
			delete __this[guid];
			delete __obj[guid];
			delete __idx[guid];
			delete __clr[guid];
		};

		Proxy.prototype.finalize = function() {
			this.commit();
			this.destroy();
		};

		return Proxy;
	})();

	var Opt = Object.prototype.toString,
		self = {
		array: {
			getIndexes: function(array, filter) {
				var indexes = [],
					len = array.length,
					isFn = (typeof filter === 'function'),
					i;

				if (isFn) {
					for (i = 0; i < len; i++) {
						if ( filter(i, array[i]) ) {
							indexes.push(i);
						}
					}
				} else {
					for (i = 0; i < len; i++) {
						if ( array[i] === filter ) {
							indexes.push(i);
						}
					}
				}
			},
			getByIndexes: function(array, indexes) {
				var len = indexes.length,
					data = [];

				for (;len;) {
					len--;
					data[len] = array[indexes[len]];
				}
				return data;
			},
			rotate: function(arr, result, limited, softFail) {
				var obj, i, att;

				// Not an array? Send it back.
				if ( Opt.call(arr) !== '[object Array]' ) {
					throw new TypeError("RC: Argument is not an array");
				}

				// Clean truthy/falsy values & undefined
				limited = !!limited;
				softFail = !!softFail;

				if ( !!result || typeof result !== 'object' ) {
					if ( limited ) {
						throw new TypeError("RC: Must pass a result object when 'limited' is true");
					} else {
						result = {};
					}
				}

				i = arr.length;

				for (;i;) {
					i--;
					obj = arr[i];

					// All variables submit to for-in loops
					for (att in obj) {
						if ( obj.hasOwnProperty(att) ) {
							if ( result[att] === undefined ) {
								if ( limited ) {
									continue;
								} else {
									result[att] = [];
								}
							}
							result[att][i] = obj[att];
						}
					}
				}
				return result;
			}
		},
		object: {
			filter: function(obj, field, filter) {
				return self.object.filterMerge(obj, self.object.filterIndexes(obj, field, filter));
			},
			filterIndexes: function(obj, field, filter) {
				var indexes = false;

				if ( obj.hasOwnProperty(field) ) {
					indexes = self.array.getIndexes(obj[field], filter);
				}
				return indexes;
			},
			filterMerge: function(obj, indexes) {
				var result = {},
					att;

				if ( indexes ) {
					for (att in obj) {
						if ( obj.hasOwnProperty(att) ) {
							result[att] = self.array.getByIndexes(obj[att], indexes);
						}
					}
				}
				return result;
			},
			rotate: function(obj, result, clearUndef) {
				var att, i, len = 0;

				// Not an array? Send it back.
				if ( typeof obj !== 'object' ) {
					throw new TypeError("RC: Argument is not an object");
				}

				if ( result === undefined ) {
					result = [];
				} else if ( Object.prototype.toString.call(result) !== '[object Array]' ) {
					throw new TypeError("RC: Result argument is an array");
				}

				// Get the longest length of all properties
				for (att in obj) {
					if ( obj.hasOwnProperty(att) ) {
						len = Math.max(len, att.length);
					}
				}

				for (i = 0; i < len; i++) {
					if ( result[i] === undefined ) {
						result[i] = {};
					} else if ( typeof result[i] !== 'object' ) {
						throw new TypeError("RC: Result contains incorrect type at index " + i);
					}

					for (att in obj) {
						if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][i] !== undefined ) ) {
							result[i][att] = obj[att][i];
						}
					}
				}

				return result;
			},
			objFromIndex: function(obj, index, clearUndef) {
				return new Proxy(obj, index, clearUndef);
			},
			proxy: function(obj, index, clearUndef) {
				return new Proxy(obj, index, clearUndef);
			}
		},
		rotate: function(obj) {
			// Generic, which directs to the appropriate array/object rotate
			if (typeof obj !== 'object') throw new TypeError("RC: rotate requires an object or an array");
			if ( Opt.call(obj) === '[object Array]' ) {
				return self.array.rotate.apply(this, arguments);
			} else {
				return self.object.rotate.apply(this, arguments);
			}
		},
		version: 'v0.06'
	};

	root.rc = self;

	// Can we build a chaining mode?
	// Should we move this into the same namespace?
	/**
	 * @constructor
	 * @param obj - A (hopefully) columnar object
	 * @param {Boolean} [clearUndef] - Clear undefined attributes when copying the object.
	 */
	root.RC = function(obj, clearUndef) {
		var att;

		for ( att in obj ) {
			if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att] !== undefined ) ) {
				this[att] = obj[att];
			}
		}
	};

	root.RC.prototype.filter = function(field, filter) {
		return new root.RC(self.object.filter(this, field, filter));
	};
	root.RC.prototype.proxy = function(index, clearUndef) {
		return self.object.proxy(this, index, clearUndef);
	};
	root.RC.prototype.rotate = function(mergeObj, clearUndef) {
		return self.object.rotate(this, mergeObj, clearUndef);
	};
}(this));
<|endoftext|>


<commit_before>function kindOf (value) {
  return typeof value === 'object'
    ? Object.prototype.toString.call(value)
      .replace(/^\[object |\]$/g, '')
      .toLowerCase()
    : typeof value
}

function kindOfType (value) {
  // Return the constructor name if not a primative, array or function
  // A more performant `kindOf` with cavets. Must test ES6 after upgrade.
  // Does not handle arguments.
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  if (typeof value === 'string') return 'string'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'symbol') return 'symbol'
  if (typeof value === 'function') return 'function'

  // this will pick out PlainObjects, regexps, and dates
  // more quickly than a toString.call(). Fails on arguments,
  // not really though --> arguments [object]
  var type = value.constructor.name

  if (type === 'Object') return 'object'
  if (type === 'Date') return 'date'
  if (type === 'RegExp') return 'regexp'

  return type.toLowerCase()
}

function kindOfObjs (value) {
  // a speedy version to obtain common object "types"
  // Does not handle arguments.
  if (typeof value === 'function') return 'function'
  if (Array.isArray(value)) return 'array'
  if (typeof value === 'string') return 'string'

  var type = value.constructor.name

  if (type === 'Object') return 'object'
  if (type === 'Date') return 'date'
  if (type === 'RegExp') return 'regexp'

  return type.toLowerCase()
}

function kindOfSafe (value) {
  // Object.create(null) throws an error. Code below
  // prevents this from happening. Does not handle arguments.
  try {
    if (value === null) return 'null'
    if (value === undefined) return 'undefined'

    if (Array.isArray(value)) return 'array'

    var type = value.constructor.name

    if (type === 'String') return 'string'
    if (type === 'Boolean') return 'boolean'
    if (type === 'Number') return 'number'
    if (type === 'Symbol') return 'symbol'
    if (type === 'Function') return 'function'
    if (type === 'RegExp') return 'regexp'
    if (type === 'Date') return 'date'
    if (type === 'Object') return 'object'

    return type.toLowerCase()
  } catch (err) {
    return Object.prototype.toString.call(value)
      .replace(/^\[object |\]$/g, '')
      .toLowerCase()
  }
}

module.exports = kindOf
module.exports.type = kindOfType
module.exports.objs = kindOfObjs
module.exports.safe = kindOfSafe
<commit_msg>update lang/KindOf<commit_after>function kindOf (value) {
  return typeof value === 'object'
    ? Object.prototype.toString.call(value)
      .replace(/^\[object |\]$/g, '')
      .toLowerCase()
    : typeof value
}

function kindOfType (value) {
  // Return the constructor name if not a primative, array or function
  // A more performant `kindOf` with cavets. Must test ES6 after upgrade.
  // Does not handle arguments.
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  if (typeof value === 'string') return 'string'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'symbol') return 'symbol'
  if (typeof value === 'function') return 'function'

  // this will pick out PlainObjects, regexps, and dates
  // more quickly than a toString.call(). Fails on arguments,
  // not really though --> arguments [object]
  var type = value.constructor.name

  if (type === 'Object') return 'object'
  if (type === 'RegExp') return 'regexp'
  if (type === 'Date') return 'date'

  return type.toLowerCase()
}

function kindOfObjs (value) {
  // a speedy version to obtain common object "types"
  // Does not handle arguments.
  if (typeof value === 'function') return 'function'
  if (Array.isArray(value)) return 'array'
  if (typeof value === 'string') return 'string'

  var type = value.constructor.name

  if (type === 'Object') return 'object'
  if (type === 'RegExp') return 'regexp'
  if (type === 'Date') return 'date'

  return type.toLowerCase()
}

function kindOfSafe (value) {
  // Object.create(null) throws an error. Code below
  // prevents this from happening. Does not handle arguments.
  try {
    if (value === null) return 'null'
    if (value === undefined) return 'undefined'

    if (Array.isArray(value)) return 'array'

    var type = value.constructor.name

    if (type === 'String') return 'string'
    if (type === 'Boolean') return 'boolean'
    if (type === 'Number') return 'number'
    if (type === 'Symbol') return 'symbol'
    if (type === 'Function') return 'function'
    if (type === 'Object') return 'object'
    if (type === 'RegExp') return 'regexp'
    if (type === 'Date') return 'date'

    return type.toLowerCase()
  } catch (err) {
    return Object.prototype.toString.call(value)
      .replace(/^\[object |\]$/g, '')
      .toLowerCase()
  }
}

module.exports = kindOf
module.exports.type = kindOfType
module.exports.objs = kindOfObjs
module.exports.safe = kindOfSafe
<|endoftext|>


<commit_before>/** section: Language
 * class Number
 *
 *  Extensions to the built-in `Number` object.
 *
 *  Prototype extends native JavaScript numbers in order to provide:
 *
 *  * [[ObjectRange]] compatibility, through [[Number#succ]].
 *  * Numerical loops with [[Number#times]].
 *  * Simple utility methods such as [[Number#toColorPart]] and
 *    [[Number#toPaddedString]].
 *  * Instance-method aliases of many functions in the `Math` namespace.
 *
**/
Object.extend(Number.prototype, (function() {
  /**
   *  Number#toColorPart() -> String
   *
   *  Produces a 2-digit hexadecimal representation of the number
   *  (which is therefore assumed to be in the [0..255] range).
   *  Useful for composing CSS color strings.
  **/
  function toColorPart() {
    return this.toPaddedString(2, 16);
  }

  /**
   *  Number#succ() -> Number
   *
   *  Returns the successor of the current Number, as defined by current + 1.
   *  Used to make numbers compatible with ObjectRange.
  **/
  function succ() {
    return this + 1;
  }

  /**
   *  Number#times(iterator) -> Number
   *
   *  Calls `iterator` the specified number of times.
   *  The function takes an integer as the first parameter; it will start at 0
   *  and be incremented after each invocation.
  **/
  function times(iterator, context) {
    $R(0, this, true).each(iterator, context);
    return this;
  }

  /**
   *  Number#toPaddedString(length[, radix]) -> String
   *
   *  Converts the number into a string padded with 0s so that the string's length
   *  is at least equal to `length`.
   *  Takes an optional `radix` argument which specifies the base to use for conversion.
  **/
  function toPaddedString(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
  }

  /** related to: Object.toJSON
   *  Number#toJSON() -> String
   *
   *  Returns a JSON string representation of the number.
  **/
  function toJSON() {
    return isFinite(this) ? this.toString() : 'null';
  }

  /**
   *  Number#abs() -> Number
   *
   *  Returns the absolute value of the number. Convenience method that simply
   *  calls `Math.abs` on this instance and returns the result.
  **/
  function abs() {
    return Math.abs(this);
  }

  /**
   *  Number#round() -> Number
   *
   *  Rounds the number to the nearest integer. Convenience method that simply
   *  calls `Math.round` on this instance and returns the result.
  **/
  function round() {
    return Math.round(this);
  }

  /**
   *  Number#ceil() -> Number
   *
   *  Returns the smallest integer greater than or equal to the number.
   *  Convenience method that simply calls `Math.ceil` on this instance and
   *  returns the result.
  **/
  function ceil() {
    return Math.ceil(this);
  }

  /**
   *  Number#floor() -> Number
   *
   *  Returns the largest integer less than or equal to the number.
   *  Convenience method that simply calls `Math.floor` on this instance and
   *  returns the result.
  **/
  function floor() {
    return Math.floor(this);
  }

  return {
    toColorPart:    toColorPart,
    succ:           succ,
    times:          times,
    toPaddedString: toPaddedString,
    toJSON:         toJSON,
    abs:            abs,
    round:          round,
    ceil:           ceil,
    floor:          floor
  };
})());
<commit_msg>doc: Fleshed out Number#times.<commit_after>/** section: Language
 * class Number
 *
 *  Extensions to the built-in `Number` object.
 *
 *  Prototype extends native JavaScript numbers in order to provide:
 *
 *  * [[ObjectRange]] compatibility, through [[Number#succ]].
 *  * Numerical loops with [[Number#times]].
 *  * Simple utility methods such as [[Number#toColorPart]] and
 *    [[Number#toPaddedString]].
 *  * Instance-method aliases of many functions in the `Math` namespace.
 *
**/
Object.extend(Number.prototype, (function() {
  /**
   *  Number#toColorPart() -> String
   *
   *  Produces a 2-digit hexadecimal representation of the number
   *  (which is therefore assumed to be in the [0..255] range).
   *  Useful for composing CSS color strings.
  **/
  function toColorPart() {
    return this.toPaddedString(2, 16);
  }

  /**
   *  Number#succ() -> Number
   *
   *  Returns the successor of the current Number, as defined by current + 1.
   *  Used to make numbers compatible with ObjectRange.
  **/
  function succ() {
    return this + 1;
  }

  /**
   *  Number#times(iterator[,context]) -> Number
   *  - iterator (Function): An iterator function to call.
   *  - context (Object): An optional context (`this` value) to use when
   *    calling `iterator`.
   *
   *  Calls `iterator` the specified number of times, passing in a number as
   *  the first parameter. The number will be 0 on first call, 1 on second
   *  call, etc. `times` returns the number instance it was called on.
   *
   *  ### Example
   *
   *      (3).times(alert);
   *      // -> Alerts "0", then "1", then "2"; returns 3
   *
   *      var obj = {count: 0, total: 0};
   *      function add(addend) {
   *        ++this.count;
   *        this.total += addend;
   *      }
   *      (4).times(add, obj);
   *      // -> 4
   *      obj.count;
   *      // -> 4
   *      obj.total;
   *      // -> 6 (e.g., 0 + 1 + 2 + 3)
  **/
  function times(iterator, context) {
    $R(0, this, true).each(iterator, context);
    return this;
  }

  /**
   *  Number#toPaddedString(length[, radix]) -> String
   *
   *  Converts the number into a string padded with 0s so that the string's length
   *  is at least equal to `length`.
   *  Takes an optional `radix` argument which specifies the base to use for conversion.
  **/
  function toPaddedString(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
  }

  /** related to: Object.toJSON
   *  Number#toJSON() -> String
   *
   *  Returns a JSON string representation of the number.
  **/
  function toJSON() {
    return isFinite(this) ? this.toString() : 'null';
  }

  /**
   *  Number#abs() -> Number
   *
   *  Returns the absolute value of the number. Convenience method that simply
   *  calls `Math.abs` on this instance and returns the result.
  **/
  function abs() {
    return Math.abs(this);
  }

  /**
   *  Number#round() -> Number
   *
   *  Rounds the number to the nearest integer. Convenience method that simply
   *  calls `Math.round` on this instance and returns the result.
  **/
  function round() {
    return Math.round(this);
  }

  /**
   *  Number#ceil() -> Number
   *
   *  Returns the smallest integer greater than or equal to the number.
   *  Convenience method that simply calls `Math.ceil` on this instance and
   *  returns the result.
  **/
  function ceil() {
    return Math.ceil(this);
  }

  /**
   *  Number#floor() -> Number
   *
   *  Returns the largest integer less than or equal to the number.
   *  Convenience method that simply calls `Math.floor` on this instance and
   *  returns the result.
  **/
  function floor() {
    return Math.floor(this);
  }

  return {
    toColorPart:    toColorPart,
    succ:           succ,
    times:          times,
    toPaddedString: toPaddedString,
    toJSON:         toJSON,
    abs:            abs,
    round:          round,
    ceil:           ceil,
    floor:          floor
  };
})());
<|endoftext|>


<commit_before>/**
 * @fileOverview
 * Copyright (c) 2012 Adam Ranfelt
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * trigger, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 * OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Input Module Definition
 * @author Adam Ranfelt <adamRenny@gmail.com>
 * @version 1.2
 */
define([
    'jquery',
    'layer/Events'
], function(
    $,
    Events
) {
    'use strict';

    /**
     * Namespace ID
     *
     * @type {number}
     * @private
     * @since 1.2
     */
    var namespaceId = 0;

    /**
     * Namespace string
     *
     * @type {string}
     * @constant
     * @since 1.2
     */
    var NAMESPACE = '.input';

    /**
     * Calculate position offset of container
     *
     * @private
     * @param {HTMLElement} container
     * @param {object} containerOffset Object to set top and left offset values to
     * @return {object}
     */
    var getOffset = function(container, containerOffset) {
        var offset = container.getBoundingClientRect();
        var clientTop  = document.clientTop || document.body.clientTop || 0;
        var clientLeft = document.clientLeft || document.body.clientLeft || 0;
        var scrollTop  = window.pageYOffset || document.scrollTop || 0;
       	var scrollLeft = window.pageXOffset || document.scrollLeft || 0;
        var top  = offset.top  + scrollTop  - clientTop;
        var left = offset.left + scrollLeft - clientLeft;

        containerOffset.top = top;
        containerOffset.left = left;
    };

    /**
     * Mouse Event to represent the current mouse state
     *
     * @name Mouse
     * @class Mouse state that represents the current mouse state
     * @constructor
     * @since 1.0
     */
    var Mouse = function() {
        /**
         * X Position of the Mouse
         *
         * @default 0
         * @name Mouse#x
         * @type {number}
         * @since 1.0
         */
        this.x = 0;

        /**
         * Y Position of the Mouse
         *
         * @default 0
         * @name Mouse#y
         * @type {number}
         * @since 1.0
         */
        this.y = 0;
    };

    /**
     * Input Controller Constructor
     *
     * Controller to manage all UI inputs from a specific container
     * All hit positions are normalized to the container's origin
     * Enabled after initialization
     * TODO: Handle touch events
     * TODO: Handle mouseleave
     * TODO: Handle mouseover/mouseout
     *
     * @name Input
     * @class Input controller to listen to UI Events
     * @constructor
     *
     * @param {HTMLElement} container Container to listen from for the input controller
     * @since 1.0
     */
    var Input = function(container) {
        this.init(container);
    };

    /**
     * Initializes the input by attaching to the container
     * Only propagates content from the input if the input is active
     *
     * @throws {ArgumentsError} If container is undefined or null
     *
     * @param {HTMLElement} container Container to listen from for the input controller
     * @returns {Input}
     * @since 1.0
     */
    Input.prototype.init = function(container) {
        if (container === undefined || container === null) {
            throw new Error('ArgumentsError: container not defined for Input');
        }

        /**
         * Unique namespace
         *
         * @name Input#namespace
         * @type {string}
         * @since 1.2
         */
        this.namespace = NAMESPACE + (namespaceId++);

        /**
         * HTML Container for the input
         *
         * @name Input#container
         * @type {HTMLElement}
         * @since 1.0
         */
        this.container = container;

        /**
         * Mouse state of the input
         *
         * @name Input#mouse
         * @type {Mouse}
         * @since 1.0
         */
        this.mouse = new Mouse();

        /**
         * Enabled state flag for the input
         *
         * @default false
         * @name Input#enabled
         * @type {boolean}
         * @since 1.0
         */
        this.enabled = false;

        /**
         * Active state flag for the input
         * Active state listens for when the mouse enters to begin listening for input
         *
         * @default false
         * @name Input#enabled
         * @type {boolean}
         * @since 1.1.1
         */
        this.isActive = false;

        /**
         * Container position offset on page
         *
         * @name Input#containerOffset
         * @type {object}
         */
        this.containerOffset = { top: 0, left: 0 };

        return this.setupHandlers().activate().enable();
    };

    /**
     * Binds all the handlers for all the events that are handled
     *
     * @returns {Input}
     * @since 1.1
     */
    Input.prototype.setupHandlers = function() {
        /**
         * Bound onMove Handler
         *
         * @private
         * @name Input#onMoveHandler
         * @type {function}
         * @since 1.0
         */
        this.onMoveHandler = this.onMove.bind(this);

        /**
         * Bound onDown Handler
         *
         * @private
         * @name Input#onDownHandler
         * @type {function}
         * @since 1.0
         */
        this.onDownHandler = this.onDown.bind(this);

        /**
         * Bound onUp Handler
         *
         * @private
         * @name Input#onUpHandler
         * @type {function}
         * @since 1.0
         */
        this.onUpHandler = this.onUp.bind(this);

        /**
         * Bound onClick Handler
         *
         * @private
         * @name Input#onClickHandler
         * @type {function}
         * @since 1.0
         */
        this.onClickHandler = this.onClick.bind(this);

        /**
         * Bound onEnter Handler
         *
         * @private
         * @name Input#onEnterHandler
         * @type {function}
         * @since 1.1.1
         */
        this.onEnterHandler = this.onEnter.bind(this);

        /**
         * Bound onExit Handler
         *
         * @private
         * @name Input#onExitHandler
         * @type {function}
         * @since 1.1.1
         */
        this.onExitHandler = this.onExit.bind(this);

        return this;
    };

    /**
     * Attaches the input to the container to listen for entry and exiting
     * Enables the container only if entered
     *
     * @returns {Input}
     * @since 1.1.1
     */
    Input.prototype.activate = function() {
        if (this.isActive) {
            return this;
        }

        this.isActive = true;

        var $container = $(this.container);

        $container.on('mouseover touchstart', this.onEnterHandler);
        $container.on('mouseout touchend', this.onExitHandler);

        return this;
    };

    /**
     * Detaches the input to the container to stop listening for entry and exiting
     *
     * @returns {Input}
     * @since 1.1.1
     */
    Input.prototype.deactivate = function() {
        if (!this.isActive) {
            return this;
        }

        this.isActive = false;

        var $container = $(this.container);

        $container.off('mouseover touchstart', this.onEnterHandler);
        $container.off('mouseout touchend', this.onExitHandler);

        return this;
    };

    /**
     * Enables the Input controller by attaching to the container
     * Enables only if necessary
     *
     * @returns {Input}
     * @since 1.0
     */
    Input.prototype.enable = function() {
        if (this.enabled) {
            return this;
        }

        this.enabled = true;

        var $container = $(this.container);

        $container.on('mousemove touchmove', this.onMoveHandler);
        $container.on('mouseup touchend', this.onUpHandler);
        $container.on('mousedown touchstart', this.onDownHandler);
        $container.on('click', this.onClickHandler);

        return this;
    };

    /**
     * Disables the Input controller by attaching to the container
     * Disables only if necessary
     *
     * @returns {Input}
     * @since 1.0
     */
    Input.prototype.disable = function() {
        if (!this.enabled) {
            return this;
        }

        this.enabled = false;

        var $container = $(this.container);

        $container.off('mousemove touchmove', this.onMoveHandler);
        $container.off('mouseup touchend', this.onUpHandler);
        $container.off('mousedown touchstart', this.onDownHandler);
        $container.off('click', this.onClickHandler);

        return this;
    };

    /**
     * Get unique namespace
     *
     * @return {string}
     * @since 1.2
     */
    Input.prototype.getNamespace = function() {
        return this.namespace;
    };

    /**
     * onMove Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Move Event
     * @since 1.0
     */
    Input.prototype.onMove = function(event) {
        if (event.originalEvent.touches) {
            this.mouse.x = event.originalEvent.touches[0].pageX - this.containerOffset.left;
            this.mouse.y = event.originalEvent.touches[0].pageY - this.containerOffset.top;
            // Prevent body from scrolling
            event.preventDefault();
        } else {
            this.mouse.x = event.offsetX;
            this.mouse.y = event.offsetY;
        }

        Events.trigger(Input.MOUSE_MOVE + this.namespace, this.mouse);
    };

    /**
     * onUp Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Up Event
     * @since 1.0
     */
    Input.prototype.onUp = function(event) {
        if (event.originalEvent.touches) {
            this.mouse.x = 0;
            this.mouse.y = 0;
        } else {
            this.mouse.x = event.offsetX;
            this.mouse.y = event.offsetY;
        }

        Events.trigger(Input.MOUSE_UP + this.namespace, this.mouse);
    };

    /**
     * onDown Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Down Event
     * @since 1.0
     */
    Input.prototype.onDown = function(event) {
        if (event.originalEvent.touches) {
            getOffset(this.container, this.containerOffset);
            this.mouse.x = event.originalEvent.touches[0].pageX - this.containerOffset.left;
            this.mouse.y = event.originalEvent.touches[0].pageY - this.containerOffset.top;
        } else {
            this.mouse.x = event.offsetX;
            this.mouse.y = event.offsetY;
        }

        Events.trigger(Input.MOUSE_DOWN + this.namespace, this.mouse);
    };

    /**
     * onClick Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Click Event
     * @since 1.0
     */
    Input.prototype.onClick = function(event) {
        this.mouse.x = event.offsetX;
        this.mouse.y = event.offsetY;

        Events.trigger(Input.CLICK + this.namespace, this.mouse);
    };

    /**
     * onEnter Handler
     * Enables the input on enter
     *
     * @param {jQuery.Event} event Mouse Click Event
     * @since 1.1.1
     */
    Input.prototype.onEnter = function(event) {
        this.enable();
    };

    /**
     * onExit Handler
     * Disables the input on exit
     *
     * @param {jQuery.Event} event Mouse Click Event
     * @since 1.1.1
     */
    Input.prototype.onExit = function(event) {
        this.disable();
    };

    /**
     * Input Mousemove Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.MOUSE_MOVE = 'input/mousemove';

    /**
     * Input Mouseup Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.MOUSE_UP = 'input/mouseup';

    /**
     * Input Mousedown Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.MOUSE_DOWN = 'input/mousedown';

    /**
     * Input Click Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.CLICK = 'input/mouseclick';

    return Input;
});<commit_msg>Create DOCUMENT, WINDOW, and BODY constants. JSDoc updates - include @since<commit_after>/**
 * @fileOverview
 * Copyright (c) 2012 Adam Ranfelt
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * trigger, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 * OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Input Module Definition
 * @author Adam Ranfelt <adamRenny@gmail.com>
 * @version 1.3
 */
define([
    'jquery',
    'layer/Events'
], function(
    $,
    Events
) {
    'use strict';

    /**
     * Namespace ID
     *
     * @type {number}
     * @private
     * @since 1.2
     */
    var namespaceId = 0;

    /**
     * Namespace string
     *
     * @type {string}
     * @constant
     * @since 1.2
     */
    var NAMESPACE = '.input';

    /**
     * Page document object
     *
     * @type {HTMLDocument}
     * @constant
     * @since 1.3
     */
    var DOCUMENT = document;

    /**
     * Page window object
     *
     * @type {window}
     * @constant
     * @since 1.3
     */
    var WINDOW = window;

    /**
     * Page body element
     *
     * @type {HTMLElement}
     * @constant
     * @since 1.3
     */
    var BODY = DOCUMENT.body;

    /**
     * Calculate position offset of container
     *
     * @param {HTMLElement} container
     * @param {object} containerOffset Object to set top and left offset values to
     * @return {object}
     * @private
     * @since 1.3
     */
    var getOffset = function(container, containerOffset) {
        var offset = container.getBoundingClientRect();

        var clientTop  = DOCUMENT.clientTop || BODY.clientTop || 0;
        var clientLeft = DOCUMENT.clientLeft || BODY.clientLeft || 0;

        var scrollTop  = WINDOW.pageYOffset || DOCUMENT.scrollTop || 0;
       	var scrollLeft = WINDOW.pageXOffset || DOCUMENT.scrollLeft || 0;

        containerOffset.top = offset.top + scrollTop - clientTop;
        containerOffset.left = offset.left + scrollLeft - clientLeft;
    };

    /**
     * Mouse Event to represent the current mouse state
     *
     * @name Mouse
     * @class Mouse state that represents the current mouse state
     * @constructor
     * @since 1.0
     */
    var Mouse = function() {
        /**
         * X Position of the Mouse
         *
         * @default 0
         * @name Mouse#x
         * @type {number}
         * @since 1.0
         */
        this.x = 0;

        /**
         * Y Position of the Mouse
         *
         * @default 0
         * @name Mouse#y
         * @type {number}
         * @since 1.0
         */
        this.y = 0;
    };

    /**
     * Input Controller Constructor
     *
     * Controller to manage all UI inputs from a specific container
     * All hit positions are normalized to the container's origin
     * Enabled after initialization
     * TODO: Handle mouseleave
     *
     * @name Input
     * @class Input controller to listen to UI Events
     * @constructor
     *
     * @param {HTMLElement} container Container to listen from for the input controller
     * @since 1.0
     */
    var Input = function(container) {
        this.init(container);
    };

    /**
     * Initializes the input by attaching to the container
     * Only propagates content from the input if the input is active
     *
     * @throws {ArgumentsError} If container is undefined or null
     *
     * @param {HTMLElement} container Container to listen from for the input controller
     * @returns {Input}
     * @since 1.0
     */
    Input.prototype.init = function(container) {
        if (container === undefined || container === null) {
            throw new Error('ArgumentsError: container not defined for Input');
        }

        /**
         * Unique namespace
         *
         * @name Input#namespace
         * @type {string}
         * @since 1.2
         */
        this.namespace = NAMESPACE + (namespaceId++);

        /**
         * HTML Container for the input
         *
         * @name Input#container
         * @type {HTMLElement}
         * @since 1.0
         */
        this.container = container;

        /**
         * Mouse state of the input
         *
         * @name Input#mouse
         * @type {Mouse}
         * @since 1.0
         */
        this.mouse = new Mouse();

        /**
         * Enabled state flag for the input
         *
         * @default false
         * @name Input#enabled
         * @type {boolean}
         * @since 1.0
         */
        this.enabled = false;

        /**
         * Active state flag for the input
         * Active state listens for when the mouse enters to begin listening for input
         *
         * @default false
         * @name Input#enabled
         * @type {boolean}
         * @since 1.1.1
         */
        this.isActive = false;

        /**
         * Container position offset on page
         *
         * @name Input#containerOffset
         * @type {object}
         * @since 1.3
         */
        this.containerOffset = { top: 0, left: 0 };

        return this.setupHandlers().activate().enable();
    };

    /**
     * Binds all the handlers for all the events that are handled
     *
     * @returns {Input}
     * @since 1.1
     */
    Input.prototype.setupHandlers = function() {
        /**
         * Bound onMove Handler
         *
         * @private
         * @name Input#onMoveHandler
         * @type {function}
         * @since 1.0
         */
        this.onMoveHandler = this.onMove.bind(this);

        /**
         * Bound onDown Handler
         *
         * @private
         * @name Input#onDownHandler
         * @type {function}
         * @since 1.0
         */
        this.onDownHandler = this.onDown.bind(this);

        /**
         * Bound onUp Handler
         *
         * @private
         * @name Input#onUpHandler
         * @type {function}
         * @since 1.0
         */
        this.onUpHandler = this.onUp.bind(this);

        /**
         * Bound onClick Handler
         *
         * @private
         * @name Input#onClickHandler
         * @type {function}
         * @since 1.0
         */
        this.onClickHandler = this.onClick.bind(this);

        /**
         * Bound onEnter Handler
         *
         * @private
         * @name Input#onEnterHandler
         * @type {function}
         * @since 1.1.1
         */
        this.onEnterHandler = this.onEnter.bind(this);

        /**
         * Bound onExit Handler
         *
         * @private
         * @name Input#onExitHandler
         * @type {function}
         * @since 1.1.1
         */
        this.onExitHandler = this.onExit.bind(this);

        return this;
    };

    /**
     * Attaches the input to the container to listen for entry and exiting
     * Enables the container only if entered
     *
     * @returns {Input}
     * @since 1.1.1
     */
    Input.prototype.activate = function() {
        if (this.isActive) {
            return this;
        }

        this.isActive = true;

        var $container = $(this.container);

        $container.on('mouseover touchstart', this.onEnterHandler);
        $container.on('mouseout touchend', this.onExitHandler);

        return this;
    };

    /**
     * Detaches the input to the container to stop listening for entry and exiting
     *
     * @returns {Input}
     * @since 1.1.1
     */
    Input.prototype.deactivate = function() {
        if (!this.isActive) {
            return this;
        }

        this.isActive = false;

        var $container = $(this.container);

        $container.off('mouseover touchstart', this.onEnterHandler);
        $container.off('mouseout touchend', this.onExitHandler);

        return this;
    };

    /**
     * Enables the Input controller by attaching to the container
     * Enables only if necessary
     *
     * @returns {Input}
     * @since 1.0
     */
    Input.prototype.enable = function() {
        if (this.enabled) {
            return this;
        }

        this.enabled = true;

        var $container = $(this.container);

        $container.on('mousemove touchmove', this.onMoveHandler);
        $container.on('mouseup touchend', this.onUpHandler);
        $container.on('mousedown touchstart', this.onDownHandler);
        $container.on('click', this.onClickHandler);

        return this;
    };

    /**
     * Disables the Input controller by attaching to the container
     * Disables only if necessary
     *
     * @returns {Input}
     * @since 1.0
     */
    Input.prototype.disable = function() {
        if (!this.enabled) {
            return this;
        }

        this.enabled = false;

        var $container = $(this.container);

        $container.off('mousemove touchmove', this.onMoveHandler);
        $container.off('mouseup touchend', this.onUpHandler);
        $container.off('mousedown touchstart', this.onDownHandler);
        $container.off('click', this.onClickHandler);

        return this;
    };

    /**
     * Get unique namespace
     *
     * @return {string}
     * @since 1.2
     */
    Input.prototype.getNamespace = function() {
        return this.namespace;
    };

    /**
     * onMove Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Move Event
     * @since 1.0
     */
    Input.prototype.onMove = function(event) {
        if (event.originalEvent.touches) {
            this.mouse.x = event.originalEvent.touches[0].pageX - this.containerOffset.left;
            this.mouse.y = event.originalEvent.touches[0].pageY - this.containerOffset.top;
            // Prevent body from scrolling
            event.preventDefault();
        } else {
            this.mouse.x = event.offsetX;
            this.mouse.y = event.offsetY;
        }

        Events.trigger(Input.MOUSE_MOVE + this.namespace, this.mouse);
    };

    /**
     * onUp Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Up Event
     * @since 1.0
     */
    Input.prototype.onUp = function(event) {
        if (event.originalEvent.touches) {
            this.mouse.x = 0;
            this.mouse.y = 0;
        } else {
            this.mouse.x = event.offsetX;
            this.mouse.y = event.offsetY;
        }

        Events.trigger(Input.MOUSE_UP + this.namespace, this.mouse);
    };

    /**
     * onDown Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Down Event
     * @since 1.0
     */
    Input.prototype.onDown = function(event) {
        if (event.originalEvent.touches) {
            getOffset(this.container, this.containerOffset);
            this.mouse.x = event.originalEvent.touches[0].pageX - this.containerOffset.left;
            this.mouse.y = event.originalEvent.touches[0].pageY - this.containerOffset.top;
        } else {
            this.mouse.x = event.offsetX;
            this.mouse.y = event.offsetY;
        }

        Events.trigger(Input.MOUSE_DOWN + this.namespace, this.mouse);
    };

    /**
     * onClick Handler
     * Sets up the mouse state
     *
     * @param {jQuery.Event} event Mouse Click Event
     * @since 1.0
     */
    Input.prototype.onClick = function(event) {
        this.mouse.x = event.offsetX;
        this.mouse.y = event.offsetY;

        Events.trigger(Input.CLICK + this.namespace, this.mouse);
    };

    /**
     * onEnter Handler
     * Enables the input on enter
     *
     * @param {jQuery.Event} event Mouse Click Event
     * @since 1.1.1
     */
    Input.prototype.onEnter = function(event) {
        this.enable();
    };

    /**
     * onExit Handler
     * Disables the input on exit
     *
     * @param {jQuery.Event} event Mouse Click Event
     * @since 1.1.1
     */
    Input.prototype.onExit = function(event) {
        this.disable();
    };

    /**
     * Input Mousemove Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.MOUSE_MOVE = 'input/mousemove';

    /**
     * Input Mouseup Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.MOUSE_UP = 'input/mouseup';

    /**
     * Input Mousedown Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.MOUSE_DOWN = 'input/mousedown';

    /**
     * Input Click Events event name
     * Includes a layer-js namespace
     * Supplies the mouse object and the containing element
     *
     * @type {string}
     * @constant
     * @since 1.0
     */
    Input.CLICK = 'input/mouseclick';

    return Input;
});<|endoftext|>


<commit_before>const Discord = require("discord.js");
const client = new Discord.Client();
// Load configs
var cr = require("./config.json");
client.package = require("./package.json");
client.defaultPrefix = cr.prefix;
client.botOwnerID = cr.ownerID;

// Configure mongoose, load models used in this script
const mongoose = require("mongoose");
mongoose.Promise = global.Promise;
const Guild = require("./models/Guild");
mongoose.connect(cr.db_endpoint);
const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error"));

// Log into Discord *after* db connection established
db.once("open", function() {
	client.db = db;
	client.login(cr.token);
	console.log("Connected to db.");
});

// Load commands.
// TODO: Recursively search commands directory
client.commands = new Map();
client.once("ready", () => {
	const dir = "./commands/";
	const fs = require("fs");

	fs.readdir(dir, (err, files) => {
		if(err){
			console.log(dir);
			console.log(err);
			process.exit(0);
		}
		else{
			for(let i = 0; i < files.length; i++){
				let fileName = files[i];
				let mod = require(`./commands/${/(.*)\.js/.exec(fileName)[1]}`);
				let cmd = new mod(client);
				console.log(`Loaded command ${cmd.name}`);
				client.commands.set(cmd.name, cmd);
			}
		}
	});
	console.log(`Ready to begin! Serving in ${client.guilds.size} servers.`);
	client.user.setGame(`DM "help" for assistance! | Version ${client.package.version}`);
});

client.on("disconnect", () => {
	console.log("Disconnected.");
	process.exit(0);
});

client.on("error", (error) => {
	console.log("Error event:");
	console.log(error);
});

client.on("guildCreate", (guild) => {
	let toSend = [
		`Hi! Thank you for inviting me to ${guild.name}. Here are a few tips to get started.\n`,
		"My default prefix is `!`. What this means is every command starts with the `!` character; for example, !help or !spell.",
		"If you'd like to change my prefix for your server, use the `prefix` command. For example:",
		"!prefix $",
		"would change the prefix to `$`, so future commands should be executed like so: $help, $spell, $creature, etc.\n",
		"Also, in case anything goes awry, you can always execute my commands by mentioning me instead of using a prefix. Examples:",
		`${client.user} help`,
		`${client.user} prefix !`,
		`${client.user} spell dancing lights\n`,
		"If you'd like to execute commands here in a DM with me, please don't use a prefix at all.",
		"If you require more support, please feel free to ask about anything on my help server.",
		"https://discord.gg/KWsvFGG"
	];
	guild.owner.sendMessage(toSend);
});

client.on("message", async (msg) => {
	if(msg.author.bot){	// Don't respond to bots
		return;
	}

	let prefix;	// Determine prefix
	if(msg.guild){
		prefix = await client.fetchPrefix(msg.guild.id);
	}
	else{
		prefix = "";
	}

	let offset;	// Number of characters to ignore (prefix length)
	if(msg.content.startsWith(prefix)){
		offset = prefix.length;
	}
	else if(msg.content.startsWith(client.user.toString())){
		offset = client.user.toString().length + 1;
	}
	else{
		return;
	}

	let commandString = msg.content.substring(offset).split(" ")[0].toLowerCase();
	let command = client.commands.get(commandString);
	if(!command){
		return;
	}
	try{
		let pattern = new RegExp(`${command.name}([\s\S]*)`, "i");
		let args = pattern.exec(msg.content.substring(offset + commandString))[1].trim();
		if(args){
			args = args.split(" ");
		}
		if(command){
			let hasPerm = await command.checkPermission(msg.member || msg.author);
			if(!hasPerm){
				return msg.reply("you don't have permission to execute that command, or this command can only be executed in a Guild channel.");
			}
			command.execute(msg, args);
		}
	}
	catch(err){
		console.log("Error onMessage:");
		console.log(err);
	}
});

client.fetchPrefix = async function(id){
	if(client.db){
		let guild = await Guild.findOne({id: id});
		if(guild){
			return guild.prefix || client.defaultPrefix;
		}
		else{
			await new Guild({id: id, prefix: client.defaultPrefix, elevatedRoles: []}).save();
			return client.defaultPrefix;
		}
	}
};

client.fetchElevatedRoleIDs = async function(id){
	if(client.db){
		let guild = await Guild.findOne({id: id});
		if(guild){
			return guild.elevatedRoles;
		}
		else{
			return [];
		}
	}
};
<commit_msg>Why did we ever use regex for this?<commit_after>const Discord = require("discord.js");
const client = new Discord.Client();
// Load configs
var cr = require("./config.json");
client.package = require("./package.json");
client.defaultPrefix = cr.prefix;
client.botOwnerID = cr.ownerID;

// Configure mongoose, load models used in this script
const mongoose = require("mongoose");
mongoose.Promise = global.Promise;
const Guild = require("./models/Guild");
mongoose.connect(cr.db_endpoint);
const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error"));

// Log into Discord *after* db connection established
db.once("open", function() {
	client.db = db;
	client.login(cr.token);
	console.log("Connected to db.");
});

// Load commands.
// TODO: Recursively search commands directory
client.commands = new Map();
client.once("ready", () => {
	const dir = "./commands/";
	const fs = require("fs");

	fs.readdir(dir, (err, files) => {
		if(err){
			console.log(dir);
			console.log(err);
			process.exit(0);
		}
		else{
			for(let i = 0; i < files.length; i++){
				let fileName = files[i];
				let mod = require(`./commands/${/(.*)\.js/.exec(fileName)[1]}`);
				let cmd = new mod(client);
				console.log(`Loaded command ${cmd.name}`);
				client.commands.set(cmd.name, cmd);
			}
		}
	});
	console.log(`Ready to begin! Serving in ${client.guilds.size} servers.`);
	client.user.setGame(`DM "help" for assistance! | Version ${client.package.version}`);
});

client.on("disconnect", () => {
	console.log("Disconnected.");
	process.exit(0);
});

client.on("error", (error) => {
	console.log("Error event:");
	console.log(error);
});

client.on("guildCreate", (guild) => {
	let toSend = [
		`Hi! Thank you for inviting me to ${guild.name}. Here are a few tips to get started.\n`,
		"My default prefix is `!`. What this means is every command starts with the `!` character; for example, !help or !spell.",
		"If you'd like to change my prefix for your server, use the `prefix` command. For example:",
		"!prefix $",
		"would change the prefix to `$`, so future commands should be executed like so: $help, $spell, $creature, etc.\n",
		"Also, in case anything goes awry, you can always execute my commands by mentioning me instead of using a prefix. Examples:",
		`${client.user} help`,
		`${client.user} prefix !`,
		`${client.user} spell dancing lights\n`,
		"If you'd like to execute commands here in a DM with me, please don't use a prefix at all.",
		"If you require more support, please feel free to ask about anything on my help server.",
		"https://discord.gg/KWsvFGG"
	];
	guild.owner.sendMessage(toSend);
});

client.on("message", async (msg) => {
	if(msg.author.bot){	// Don't respond to bots
		return;
	}

	let prefix;	// Determine prefix
	if(msg.guild){
		prefix = await client.fetchPrefix(msg.guild.id);
	}
	else{
		prefix = "";
	}

	let offset;	// Number of characters to ignore (prefix length)
	if(msg.content.startsWith(prefix)){
		offset = prefix.length;
	}
	else if(msg.content.startsWith(client.user.toString())){
		offset = client.user.toString().length + 1;
	}
	else{
		return;
	}

	let commandString = msg.content.substring(offset).split(" ")[0].toLowerCase();
	let command = client.commands.get(commandString);
	if(!command){
		return;
	}
	try{
		let args = msg.content.substring(offset + commandString.length).trim();
		if(args){
			args = args.split(" ");
		}
		if(command){
			let hasPerm = await command.checkPermission(msg.member || msg.author);
			if(!hasPerm){
				return msg.reply("you don't have permission to execute that command, or this command can only be executed in a Guild channel.");
			}
			command.execute(msg, args);
		}
	}
	catch(err){
		console.log("Error onMessage:");
		console.log(err);
	}
});

client.fetchPrefix = async function(id){
	if(client.db){
		let guild = await Guild.findOne({id: id});
		if(guild){
			return guild.prefix || client.defaultPrefix;
		}
		else{
			await new Guild({id: id, prefix: client.defaultPrefix, elevatedRoles: []}).save();
			return client.defaultPrefix;
		}
	}
};

client.fetchElevatedRoleIDs = async function(id){
	if(client.db){
		let guild = await Guild.findOne({id: id});
		if(guild){
			return guild.elevatedRoles;
		}
		else{
			return [];
		}
	}
};
<|endoftext|>


<commit_before>export default [
  {id: 23, name: 'Frog in a Jar', image: 'https://render.guildwars2.com/file/0B26F0BB696D5628214C1C72B3C8C4F8E44FC3C0/455960.png', description: 'Feline Familiar near the Raw Candy Corn node.'},
  {id: 24, name: 'Thaw Elixir', image: 'https://wiki.guildwars2.com/images/f/f3/Cold_Resistance.png', description: 'Snow Leopard Cub that follows you around the instance.'},
  {id: 25, name: 'Bowl of Poultry and Leek Soup', image: 'https://render.guildwars2.com/file/EA0CFEFCE029FB3009256B2D91F90A5B0F47AC0C/219452.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 16, name: 'Slice of Rainbow Cake', image: 'https://render.guildwars2.com/file/D16A0A243F911A3F3EA733973D670B034D619B4A/63075.png', description: 'Black cat that fights other cats.'},
  {id: 14, name: 'Vanilla Bean', image: 'https://render.guildwars2.com/file/0B2624A031FBF37DECBA167B5C057EDFC76FA3DD/63148.png', description: 'Black cat that fights other cats with a Juvenile Frog.'},
  {id: 5, name: 'Plate of Fire Flank Steak', image: 'https://render.guildwars2.com/file/7D2FDB50466F561234CA3EDB49FFD6594132A65B/433655.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 6, name: 'Bowl of Prickly Pear Sorbet', image: 'https://render.guildwars2.com/file/7803EC07586759FA5C0965626CC1D91FFCBE7D09/831455.png', description: 'Black cat playing with a snowball.'},
  {id: 7, name: 'Bowl of Ginger-Lime Ice Cream', image: 'https://render.guildwars2.com/file/652698EC983C6ABE9A726A456E59A2EC53BD5F7A/526282.png', description: 'Black cat playing with a snowball.'},
  {id: 22, name: 'Ghost Pepper', image: 'https://render.guildwars2.com/file/01051F0458C052BF08916A555273FF6145592FE6/219488.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 21, name: 'Plate of Fire Flank Steak', image: 'https://render.guildwars2.com/file/7D2FDB50466F561234CA3EDB49FFD6594132A65B/433655.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 4, name: 'Spicier Flank Steak', image: 'https://render.guildwars2.com/file/061F31FF3D322771E93608A44050C64258B7B113/433623.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 11, name: 'Slab of Poultry Meat', image: 'https://render.guildwars2.com/file/B53CEC437833F87E27B11A2006DD3F4B085A80A9/66874.png', description: 'White kitten that only appears if the instance is entered during night.'},
  {id: 10, name: 'Slab of Poultry Meat', image: 'https://render.guildwars2.com/file/B53CEC437833F87E27B11A2006DD3F4B085A80A9/66874.png', description: 'Black kitten that only appears if the instance is entered during day.'},
  {id: 28, name: 'Super-Hot Saffron-Scented Poultry Soup', image: 'https://render.guildwars2.com/file/3A1F2D36366D0F7B2FC7B09819AD2BCCD168792D/219408.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 26, name: 'Bowl of Poultry and Winter Vegetable Soup', image: 'https://render.guildwars2.com/file/0BA8692C4178DE520C1ED3641AB097A076F4E43B/433635.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 18, name: 'Carrot', image: 'https://render.guildwars2.com/file/F06472A03B49AA6C9256195FC43B49BEA26595D0/62859.png', description: 'Black cat that fights other cats.'},
  {id: 32, name: 'Strawberry Ghost', image: 'https://render.guildwars2.com/file/9CC15FAAFFC41D0C950E4CE60D09A975EC6295B3/499406.png', description: 'Light blue Ghostly Cat.'},
  {id: 29, name: 'Bowl of Bloodstone Goulash', image: 'https://render.guildwars2.com/file/EB933E073AEDC9A36BE4F96548C85BDB0D933B4F/223237.png', description: 'Lady Wisteria Whiskington near the Bloodstone Crystals'},
  {id: 2, name: 'Grilled Poultry', image: 'https://render.guildwars2.com/file/9DC8E3F35925F5622D04CF3E01C9019CC9B6A3F8/63294.png', description: 'Grey cat by the entrance to the instance.'},
  {id: 3, name: 'Spicy Flank Steak', image: 'https://render.guildwars2.com/file/276D5B6C55460C25F50FC5ABFA2114C0753C023C/63253.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 1, name: 'Slab of Poultry Meat', image: 'https://render.guildwars2.com/file/B53CEC437833F87E27B11A2006DD3F4B085A80A9/66874.png', description: 'Grey cat by the entrance to the instance.'},
  {id: 8, name: 'Bowl of Saffron-Mango Ice Cream', image: 'https://render.guildwars2.com/file/F4C1777F7B256FF774512B045C79D86BC948166C/526279.png', description: 'Black cat playing with a snowball.'},
  {id: 9, name: 'Bowl of Peach Raspberry Swirl Ice Cream', image: 'https://render.guildwars2.com/file/6BC431C33C77A0AFF3A091274753B39F65A06465/526280.png', description: 'Black cat playing with a snowball.'},
  {id: 15, name: 'Bowl of Curry Mussel Soup', image: 'https://render.guildwars2.com/file/2D630D4F5B6D74974F6280007136B9650B80F45F/1201839.png', description: 'Black cat that fights other cats.'},
  {id: 17, name: 'Flask of Pumpkin Oil', image: 'https://render.guildwars2.com/file/E55A03C70E26E2540C32926596F252B1D5B3FEF7/888375.png', description: 'Black cat that fights other cats.'},
  {id: 19, name: 'Harpy Feathers', image: 'https://render.guildwars2.com/file/D7A8443608F4C4FD501B25BD0D0E794097B19BAE/66833.png', description: 'Black cat that fights other cats.'},
  {id: 13, name: 'Tonic', image: 'https://render.guildwars2.com/file/C6A3FFF06BB4D50050D3B1FE75E3AACBFA0F8009/63129.png', description: 'Black cat that fights other cats.'},
  {id: 12, name: 'Cheeseburger', image: 'https://render.guildwars2.com/file/3C97F8B12EF607320D4EDBCF51AEFFD36726D217/63297.png', description: 'Black cat that fights other cats.'},
  {id: 27, name: 'Bowl of Lemongrass Poultry Soup', image: 'https://render.guildwars2.com/file/802BBD3174CBA5F017CE294907DDC558713078C9/433668.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 20, name: 'Grumble Cake', image: 'https://render.guildwars2.com/file/2603D225A7B05FCA96EF31E94468EB03F9C9C945/223215.png', description: 'Black cat that fights other cats.'},
  {id: 33, name: 'Bee Dog', image: 'https://render.guildwars2.com/file/68A863124F2A07707F43371C3427220309D14AD1/561875.png', description: 'Scottish Fold without tail with a blue Bauble necklace and blue cubes aura.'},
  {id: 35, name: 'Simon', image: 'https://render.guildwars2.com/file/EFB10E0748A8E82B176BD1AFFBF5E2B4C72D06CD/1465514.png', description: 'Simon, the celestial cat.'},
  {id: 36, name: 'Blue Catmander', image: 'https://render.guildwars2.com/file/EB593444A3ED065F7BE3EC71713CF80D145EABCB/455858.png', description: 'Blue Catmander'},
  {id: 37, name: 'Yellow Catmander', image: 'https://render.guildwars2.com/file/0CCFE15267089D364873A4FDD14AC2FDDC1D2039/1423817.png', description: 'Yellow Catmander'}
]
<commit_msg>Add holographic kitten to the list of cats<commit_after>export default [
  {id: 1, name: 'Slab of Poultry Meat', image: 'https://render.guildwars2.com/file/B53CEC437833F87E27B11A2006DD3F4B085A80A9/66874.png', description: 'Grey cat by the entrance to the instance.'},
  {id: 2, name: 'Grilled Poultry', image: 'https://render.guildwars2.com/file/9DC8E3F35925F5622D04CF3E01C9019CC9B6A3F8/63294.png', description: 'Grey cat by the entrance to the instance.'},
  {id: 3, name: 'Spicy Flank Steak', image: 'https://render.guildwars2.com/file/276D5B6C55460C25F50FC5ABFA2114C0753C023C/63253.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 4, name: 'Spicier Flank Steak', image: 'https://render.guildwars2.com/file/061F31FF3D322771E93608A44050C64258B7B113/433623.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 5, name: 'Plate of Fire Flank Steak', image: 'https://render.guildwars2.com/file/7D2FDB50466F561234CA3EDB49FFD6594132A65B/433655.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 6, name: 'Bowl of Prickly Pear Sorbet', image: 'https://render.guildwars2.com/file/7803EC07586759FA5C0965626CC1D91FFCBE7D09/831455.png', description: 'Black cat playing with a snowball.'},
  {id: 7, name: 'Bowl of Ginger-Lime Ice Cream', image: 'https://render.guildwars2.com/file/652698EC983C6ABE9A726A456E59A2EC53BD5F7A/526282.png', description: 'Black cat playing with a snowball.'},
  {id: 8, name: 'Bowl of Saffron-Mango Ice Cream', image: 'https://render.guildwars2.com/file/F4C1777F7B256FF774512B045C79D86BC948166C/526279.png', description: 'Black cat playing with a snowball.'},
  {id: 9, name: 'Bowl of Peach Raspberry Swirl Ice Cream', image: 'https://render.guildwars2.com/file/6BC431C33C77A0AFF3A091274753B39F65A06465/526280.png', description: 'Black cat playing with a snowball.'},
  {id: 10, name: 'Slab of Poultry Meat', image: 'https://render.guildwars2.com/file/B53CEC437833F87E27B11A2006DD3F4B085A80A9/66874.png', description: 'Black kitten that only appears if the instance is entered during day.'},
  {id: 11, name: 'Slab of Poultry Meat', image: 'https://render.guildwars2.com/file/B53CEC437833F87E27B11A2006DD3F4B085A80A9/66874.png', description: 'White kitten that only appears if the instance is entered during night.'},
  {id: 12, name: 'Cheeseburger', image: 'https://render.guildwars2.com/file/3C97F8B12EF607320D4EDBCF51AEFFD36726D217/63297.png', description: 'Black cat that fights other cats.'},
  {id: 13, name: 'Tonic', image: 'https://render.guildwars2.com/file/C6A3FFF06BB4D50050D3B1FE75E3AACBFA0F8009/63129.png', description: 'Black cat that fights other cats.'},
  {id: 14, name: 'Vanilla Bean', image: 'https://render.guildwars2.com/file/0B2624A031FBF37DECBA167B5C057EDFC76FA3DD/63148.png', description: 'Black cat that fights other cats with a Juvenile Frog.'},
  {id: 15, name: 'Bowl of Curry Mussel Soup', image: 'https://render.guildwars2.com/file/2D630D4F5B6D74974F6280007136B9650B80F45F/1201839.png', description: 'Black cat that fights other cats.'},
  {id: 16, name: 'Slice of Rainbow Cake', image: 'https://render.guildwars2.com/file/D16A0A243F911A3F3EA733973D670B034D619B4A/63075.png', description: 'Black cat that fights other cats.'},
  {id: 17, name: 'Flask of Pumpkin Oil', image: 'https://render.guildwars2.com/file/E55A03C70E26E2540C32926596F252B1D5B3FEF7/888375.png', description: 'Black cat that fights other cats.'},
  {id: 18, name: 'Carrot', image: 'https://render.guildwars2.com/file/F06472A03B49AA6C9256195FC43B49BEA26595D0/62859.png', description: 'Black cat that fights other cats.'},
  {id: 19, name: 'Harpy Feathers', image: 'https://render.guildwars2.com/file/D7A8443608F4C4FD501B25BD0D0E794097B19BAE/66833.png', description: 'Black cat that fights other cats.'},
  {id: 20, name: 'Grumble Cake', image: 'https://render.guildwars2.com/file/2603D225A7B05FCA96EF31E94468EB03F9C9C945/223215.png', description: 'Black cat that fights other cats.'},
  {id: 21, name: 'Plate of Fire Flank Steak', image: 'https://render.guildwars2.com/file/7D2FDB50466F561234CA3EDB49FFD6594132A65B/433655.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 22, name: 'Ghost Pepper', image: 'https://render.guildwars2.com/file/01051F0458C052BF08916A555273FF6145592FE6/219488.png', description: 'Orange cat near the harvesting nodes.'},
  {id: 23, name: 'Frog in a Jar', image: 'https://render.guildwars2.com/file/0B26F0BB696D5628214C1C72B3C8C4F8E44FC3C0/455960.png', description: 'Feline Familiar near the Raw Candy Corn node.'},
  {id: 24, name: 'Thaw Elixir', image: 'https://wiki.guildwars2.com/images/f/f3/Cold_Resistance.png', description: 'Snow Leopard Cub that follows you around the instance.'},
  {id: 25, name: 'Bowl of Poultry and Leek Soup', image: 'https://render.guildwars2.com/file/EA0CFEFCE029FB3009256B2D91F90A5B0F47AC0C/219452.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 26, name: 'Bowl of Poultry and Winter Vegetable Soup', image: 'https://render.guildwars2.com/file/0BA8692C4178DE520C1ED3641AB097A076F4E43B/433635.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 27, name: 'Bowl of Lemongrass Poultry Soup', image: 'https://render.guildwars2.com/file/802BBD3174CBA5F017CE294907DDC558713078C9/433668.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 28, name: 'Super-Hot Saffron-Scented Poultry Soup', image: 'https://render.guildwars2.com/file/3A1F2D36366D0F7B2FC7B09819AD2BCCD168792D/219408.png', description: 'Orange cat by a Pot of Cat-Made Soup.'},
  {id: 29, name: 'Bowl of Bloodstone Goulash', image: 'https://render.guildwars2.com/file/EB933E073AEDC9A36BE4F96548C85BDB0D933B4F/223237.png', description: 'Lady Wisteria Whiskington near the Bloodstone Crystals'},
  {id: 32, name: 'Strawberry Ghost', image: 'https://render.guildwars2.com/file/9CC15FAAFFC41D0C950E4CE60D09A975EC6295B3/499406.png', description: 'Light blue Ghostly Cat.'},
  {id: 33, name: 'Bee Dog', image: 'https://render.guildwars2.com/file/68A863124F2A07707F43371C3427220309D14AD1/561875.png', description: 'Scottish Fold without tail with a blue Bauble necklace and blue cubes aura.'},
  {id: 34, name: 'Holographic Kitten', image: 'https://render.guildwars2.com/file/63A3D5923EBEDB7FABB4CB09065ED63A4B21C639/1759288.png', description: 'Holographic Kitten'},
  {id: 35, name: 'Simon', image: 'https://render.guildwars2.com/file/EFB10E0748A8E82B176BD1AFFBF5E2B4C72D06CD/1465514.png', description: 'Simon, the celestial cat.'},
  {id: 36, name: 'Blue Catmander', image: 'https://render.guildwars2.com/file/EB593444A3ED065F7BE3EC71713CF80D145EABCB/455858.png', description: 'Blue Catmander'},
  {id: 37, name: 'Yellow Catmander', image: 'https://render.guildwars2.com/file/0CCFE15267089D364873A4FDD14AC2FDDC1D2039/1423817.png', description: 'Yellow Catmander'}
]
<|endoftext|>


<commit_before>import pify from 'pify'
import { localRequire } from './utils'

export default {
  name: 'less',
  test: /\.less$/,
  async process({ code }) {
    const less = localRequire('less')

    const { css, map } = await pify(less.render.bind(less))(code, {
      sourceMap: this.sourceMap && {}
    })

    return {
      code: css,
      map
    }
  }
}
<commit_msg>fix: pass filename to less (#74)<commit_after>import pify from 'pify'
import { localRequire } from './utils'

export default {
  name: 'less',
  test: /\.less$/,
  async process({ code }) {
    const less = localRequire('less')

    const { css, map } = await pify(less.render.bind(less))(code, {
      sourceMap: this.sourceMap && {},
      filename: this.id
    })

    return {
      code: css,
      map
    }
  }
}
<|endoftext|>


<commit_before>/**
 * @requires javelin-install
 *           javelin-stratcom
 *           javelin-util
 *           javelin-behavior
 *           javelin-json
 * @provides javelin-request
 * @javelin
 */

/**
 * Make basic AJAX XMLHTTPRequests.
 *
 * @group workflow
 */
JX.install('Request', {
  construct : function(uri, handler) {
    this.setURI(uri);
    if (handler) {
      this.listen('done', handler);
    }
  },

  events : ['start', 'open', 'send', 'done', 'error', 'finally'],

  members : {

    _xhrkey : null,
    _transport : null,
    _sent : false,
    _finished : false,
    _block : null,
    _data : null,

    getTransport : function() {
      var xport = this._transport;
      if (!xport) {
        try {
          try {
            xport = new XMLHttpRequest();
          } catch (x) {
            xport = new ActiveXObject("Msxml2.XMLHTTP");
          }
        } catch (x) {
          xport = new ActiveXObject("Microsoft.XMLHTTP");
        }
        this._transport = xport;
      }
      return xport;
    },

    send : function() {
      if (this._sent || this._finished) {
        if (__DEV__) {
          if (this._sent) {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send a Request that has already been sent.');
          }
          if (this._finished) {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send a Request that has finished or aborted.');
          }
        }
        return;
      }

      // Fire the "start" event before doing anything. A listener may
      // perform pre-processing or validation on this request
      this.invoke('start', this);
      if (this._finished) {
        return;
      }

      var xport = this.getTransport();
      xport.onreadystatechange = JX.bind(this, this._onreadystatechange);

      var list_of_pairs = this._data || [];
      list_of_pairs.push(['__ajax__', true]);

      this._block = JX.Stratcom.allocateMetadataBlock();
      list_of_pairs.push(['__metablock__', this._block]);

      var q = (this.getDataSerializer() ||
               JX.Request.defaultDataSerializer)(list_of_pairs);
      var uri = this.getURI();
      var method = this.getMethod().toUpperCase();

      if (method == 'GET') {
        uri += ((uri.indexOf('?') === -1) ? '?' : '&') + q;
      }

      if (this.getTimeout()) {
        this._timer = setTimeout(
          JX.bind(
            this,
            this._fail,
            JX.Request.ERROR_TIMEOUT),
          this.getTimeout());
      }

      xport.open(method, uri, true);

      // Must happen after xport.open so that listeners can modify the transport
      // Some transport properties can only be set after the transport is open
      this.invoke('open', this);
      if (this._finished) {
        return;
      }

      if (__DEV__) {
        if (this.getFile()) {
          if (method != 'POST') {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send a file over GET. You must use POST.');
          }
          if (this._data) {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send data and a file. You can not send both ' +
              'at once.');
          }
        }
      }

      this.invoke('send', this);
      if (this._finished) {
        return;
      }

      if (method == 'POST') {
        if (this.getFile()) {
          xport.send(this.getFile());
        } else {
          xport.setRequestHeader(
            'Content-Type',
            'application/x-www-form-urlencoded');
          xport.send(q);
        }
      } else {
        xport.send(null);
      }

      this._sent = true;
    },

    abort : function() {
      this._cleanup();
    },

    _onreadystatechange : function() {
      var xport = this.getTransport();
      var response;
      try {
        if (this._finished) {
          return;
        }
        if (xport.readyState != 4) {
          return;
        }
        // XHR requests to 'file:///' domains return 0 for success, which is why
        // we treat it as a good result in addition to HTTP 2XX responses.
        if (xport.status !== 0 && (xport.status < 200 || xport.status >= 300)) {
          this._fail();
          return;
        }

        if (__DEV__) {
          if (!xport.responseText.length) {
            JX.$E(
              'JX.Request("'+this.getURI()+'", ...): '+
              'server returned an empty response.');
          }
          if (xport.responseText.indexOf('for (;;);') != 0) {
            JX.$E(
              'JX.Request("'+this.getURI()+'", ...): '+
              'server returned an invalid response.');
          }
          if (xport.responseText == 'for (;;);') {
            JX.$E(
              'JX.Request("'+this.getURI()+'", ...): '+
              'server returned an empty response.');
          }
        }

        var text = xport.responseText.substring('for (;;);'.length);
        response = JX.JSON.parse(text);
        if (!response) {
          JX.$E(
            'JX.Request("'+this.getURI()+'", ...): '+
            'server returned an invalid response.');
        }
      } catch (exception) {

        if (__DEV__) {
          JX.log(
            'JX.Request("'+this.getURI()+'", ...): '+
            'caught exception processing response: '+exception);
        }
        this._fail();
        return;
      }

      try {
        if (response.error) {
          this._fail(response.error);
        } else {
          JX.Stratcom.mergeData(
            this._block,
            response.javelin_metadata || {});
          this._done(response);
          JX.initBehaviors(response.javelin_behaviors || {});
        }
      } catch (exception) {
        //  In Firefox+Firebug, at least, something eats these. :/
        setTimeout(function() {
          throw exception;
        }, 0);
      }
    },

    _fail : function(error) {
      this._cleanup();

      this.invoke('error', error, this);
      this.invoke('finally');
    },

    _done : function(response) {
      this._cleanup();

      if (response.onload) {
        for (var ii = 0; ii < response.onload.length; ii++) {
          (new Function(response.onload[ii]))();
        }
      }

      this.invoke('done', this.getRaw() ? response : response.payload, this);
      this.invoke('finally');
    },

    _cleanup : function() {
      this._finished = true;
      clearTimeout(this._timer);
      this._timer = null;

      // Should not abort the transport request if it has already completed
      // Otherwise, we may see an "HTTP request aborted" error in the console
      // despite it possibly having succeeded.
      if (this._transport && this._transport.readyState != 4) {
        this._transport.abort();
      }
    },

    setData : function(dictionary) {
      this._data = null;
      dictionary && this.addData(dictionary);
      return this;
    },

    addData : function(dictionary) {
      if (!this._data) {
        this._data = [];
      }
      for (var k in dictionary) {
        this._data.push([k, dictionary[k]]);
      }
      return this;
    },

    setDataWithListOfPairs : function(list_of_pairs) {
      this._data = list_of_pairs;
      return this;
    }

  },

  statics : {
    ERROR_TIMEOUT : -9000,
    defaultDataSerializer : function(list_of_pairs) {
      var uri = [];
      for (var ii = 0; ii < list_of_pairs.length; ii++) {
        var pair = list_of_pairs[ii];
        var name = encodeURIComponent(pair[0]);
        var value = encodeURIComponent(pair[1]);
        uri.push(name + '=' + value);
      }
      return uri.join('&');
    }
  },

  properties : {
    URI : null,
    dataSerializer : null,
    /**
     * Configure which HTTP method to use for the request. Permissible values
     * are "POST" (default) or "GET".
     *
     * @param string HTTP method, one of "POST" or "GET".
     */
    method : 'POST',
    file : null,
    raw : false,

    /**
     * Configure a timeout, in milliseconds. If the request has not resolved
     * (either with success or with an error) within the provided timeframe,
     * it will automatically fail with error JX.Request.ERROR_TIMEOUT.
     *
     * @param int Timeout, in milliseconds (e.g. 3000 = 3 seconds).
     */
    timeout : null
  }

});
<commit_msg>[jx] request nit<commit_after>/**
 * @requires javelin-install
 *           javelin-stratcom
 *           javelin-util
 *           javelin-behavior
 *           javelin-json
 * @provides javelin-request
 * @javelin
 */

/**
 * Make basic AJAX XMLHTTPRequests.
 *
 * @group workflow
 */
JX.install('Request', {
  construct : function(uri, handler) {
    this.setURI(uri);
    if (handler) {
      this.listen('done', handler);
    }
  },

  events : ['start', 'open', 'send', 'done', 'error', 'finally'],

  members : {

    _xhrkey : null,
    _transport : null,
    _sent : false,
    _finished : false,
    _block : null,
    _data : null,

    getTransport : function() {
      var xport = this._transport;
      if (!xport) {
        try {
          try {
            xport = new XMLHttpRequest();
          } catch (x) {
            xport = new ActiveXObject("Msxml2.XMLHTTP");
          }
        } catch (x) {
          xport = new ActiveXObject("Microsoft.XMLHTTP");
        }
        this._transport = xport;
      }
      return xport;
    },

    send : function() {
      if (this._sent || this._finished) {
        if (__DEV__) {
          if (this._sent) {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send a Request that has already been sent.');
          }
          if (this._finished) {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send a Request that has finished or aborted.');
          }
        }
        return;
      }

      // Fire the "start" event before doing anything. A listener may
      // perform pre-processing or validation on this request
      this.invoke('start', this);
      if (this._finished) {
        return;
      }

      var xport = this.getTransport();
      xport.onreadystatechange = JX.bind(this, this._onreadystatechange);

      var list_of_pairs = this._data || [];
      list_of_pairs.push(['__ajax__', true]);

      this._block = JX.Stratcom.allocateMetadataBlock();
      list_of_pairs.push(['__metablock__', this._block]);

      var q = (this.getDataSerializer() ||
               JX.Request.defaultDataSerializer)(list_of_pairs);
      var uri = this.getURI();
      var method = this.getMethod().toUpperCase();

      if (method == 'GET') {
        uri += ((uri.indexOf('?') === -1) ? '?' : '&') + q;
      }

      if (this.getTimeout()) {
        this._timer = setTimeout(
          JX.bind(
            this,
            this._fail,
            JX.Request.ERROR_TIMEOUT),
          this.getTimeout());
      }

      xport.open(method, uri, true);

      // Must happen after xport.open so that listeners can modify the transport
      // Some transport properties can only be set after the transport is open
      this.invoke('open', this);
      if (this._finished) {
        return;
      }

      if (__DEV__) {
        if (this.getFile()) {
          if (method != 'POST') {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send a file over GET. You must use POST.');
          }
          if (this._data) {
            JX.$E(
              'JX.Request.send(): ' +
              'attempting to send data and a file. You can not send both ' +
              'at once.');
          }
        }
      }

      this.invoke('send', this);
      if (this._finished) {
        return;
      }

      if (method == 'POST') {
        if (this.getFile()) {
          xport.send(this.getFile());
        } else {
          xport.setRequestHeader(
            'Content-Type',
            'application/x-www-form-urlencoded');
          xport.send(q);
        }
      } else {
        xport.send(null);
      }

      this._sent = true;
    },

    abort : function() {
      this._cleanup();
    },

    _onreadystatechange : function() {
      var xport = this.getTransport();
      var response;
      try {
        if (this._finished) {
          return;
        }
        if (xport.readyState != 4) {
          return;
        }
        // XHR requests to 'file:///' domains return 0 for success, which is why
        // we treat it as a good result in addition to HTTP 2XX responses.
        if (xport.status !== 0 && (xport.status < 200 || xport.status >= 300)) {
          this._fail();
          return;
        }

        if (__DEV__) {
          if (!xport.responseText.length) {
            JX.$E(
              'JX.Request("'+this.getURI()+'", ...): '+
              'server returned an empty response.');
          }
          if (xport.responseText.indexOf('for (;;);') != 0) {
            JX.$E(
              'JX.Request("'+this.getURI()+'", ...): '+
              'server returned an invalid response.');
          }
          if (xport.responseText == 'for (;;);') {
            JX.$E(
              'JX.Request("'+this.getURI()+'", ...): '+
              'server returned an empty response.');
          }
        }

        var text = xport.responseText.substring('for (;;);'.length);
        response = JX.JSON.parse(text);
        if (!response) {
          JX.$E(
            'JX.Request("'+this.getURI()+'", ...): '+
            'server returned an invalid response.');
        }
      } catch (exception) {

        if (__DEV__) {
          JX.log(
            'JX.Request("'+this.getURI()+'", ...): '+
            'caught exception processing response: '+exception);
        }
        this._fail();
        return;
      }

      try {
        if (response.error) {
          this._fail(response.error);
        } else {
          JX.Stratcom.mergeData(
            this._block,
            response.javelin_metadata || {});
          this._done(response);
          JX.initBehaviors(response.javelin_behaviors || {});
        }
      } catch (exception) {
        //  In Firefox+Firebug, at least, something eats these. :/
        setTimeout(function() {
          throw exception;
        }, 0);
      }
    },

    _fail : function(error) {
      this._cleanup();

      this.invoke('error', error, this);
      this.invoke('finally');
    },

    _done : function(response) {
      this._cleanup();

      if (response.onload) {
        for (var ii = 0; ii < response.onload.length; ii++) {
          (new Function(response.onload[ii]))();
        }
      }

      this.invoke('done', this.getRaw() ? response : response.payload, this);
      this.invoke('finally');
    },

    _cleanup : function() {
      this._finished = true;
      clearTimeout(this._timer);
      this._timer = null;

      // Should not abort the transport request if it has already completed
      // Otherwise, we may see an "HTTP request aborted" error in the console
      // despite it possibly having succeeded.
      if (this._transport && this._transport.readyState != 4) {
        this._transport.abort();
      }
    },

    setData : function(dictionary) {
      this._data = null;
      this.addData(dictionary);
      return this;
    },

    addData : function(dictionary) {
      if (!this._data) {
        this._data = [];
      }
      for (var k in dictionary) {
        this._data.push([k, dictionary[k]]);
      }
      return this;
    },

    setDataWithListOfPairs : function(list_of_pairs) {
      this._data = list_of_pairs;
      return this;
    }

  },

  statics : {
    ERROR_TIMEOUT : -9000,
    defaultDataSerializer : function(list_of_pairs) {
      var uri = [];
      for (var ii = 0; ii < list_of_pairs.length; ii++) {
        var pair = list_of_pairs[ii];
        var name = encodeURIComponent(pair[0]);
        var value = encodeURIComponent(pair[1]);
        uri.push(name + '=' + value);
      }
      return uri.join('&');
    }
  },

  properties : {
    URI : null,
    dataSerializer : null,
    /**
     * Configure which HTTP method to use for the request. Permissible values
     * are "POST" (default) or "GET".
     *
     * @param string HTTP method, one of "POST" or "GET".
     */
    method : 'POST',
    file : null,
    raw : false,

    /**
     * Configure a timeout, in milliseconds. If the request has not resolved
     * (either with success or with an error) within the provided timeframe,
     * it will automatically fail with error JX.Request.ERROR_TIMEOUT.
     *
     * @param int Timeout, in milliseconds (e.g. 3000 = 3 seconds).
     */
    timeout : null
  }

});
<|endoftext|>


<commit_before>import api from 'jspm/api';
import whacko from 'whacko';
import glob from 'glob';
import fs from 'fs';
import url from 'url';
import path from 'path';

var pluginName = 'view';

function bundleJS(moduleExpression, outfile, options) {
  api.bundle(moduleExpression, outfile, options);
}

export default function bundle(config) {

  var loader = api.Builder().loader;
  var baseURL = loader.baseURL;
  var paths = loader.paths;

  var jsConfig = config.js;
  var templateConfig = config.template;

  Object.keys(jsConfig)
    .forEach(function(key) {
      var cfg = jsConfig[key];
      var outfile = key + '.js';
      var moduleExpr = cfg.modules.join(' + ');
      var opt = cfg.options;

      bundleJS(moduleExpr, outfile, opt);
    });

  Object.keys(templateConfig)
    .forEach(function(key) {
      var cfg = templateConfig[key];
      var outfile = key + '.html';
      var pattern = cfg.pattern;
      var options = cfg.options;

      bundleTemplate(pattern, outfile, options, baseURL, paths);
    });
}

function bundleTemplate(pattern, outfile, options, baseURL, paths) {
  var templates = [];

  glob
    .sync(pattern, {})
    .forEach(function(file) {
      var content = fs.readFileSync(file, {
        encoding: 'utf8'
      });
      var $ = whacko.load(content);
      var tid = getTemplateId(file, baseURL, paths);

      $('template').attr('id', tid);
      var template = $.html('template');
      templates.push(template);
    });

  fs.writeFileSync(outfile, templates.join('\n'));

  if (options.inject) {
    injectLink(outfile, baseURL);
  }
}

function injectLink(outfile, baseURL) {
  var bu = baseURL.replace(/^file:/, '') + path.sep;
  var content = fs.readFileSync(bu + 'index.html', {
    encoding: 'utf8'
  });

  var $ = whacko.load(content);

  $('head').append('<link aurlia-view-bundle rel="import" href="./' + outfile + '">');
}

function getTemplateId(file, baseURL, paths) {
  var bu = baseURL.replace(/\\/g, '/') + '/';
  var address = bu + file;

  return getModuleName(address, bu, paths);
}

function getModuleName(address, baseURL, paths) {
  var pathMatch, curMatchLength, curPath, wIndex, pathMatchLength = 0;

  if (pluginName) {
    var extension = address.split('/').pop();
    extension = extension.substr(extension.lastIndexOf('.'));
    if (extension != address && extension != '.js')
      address = address.substr(0, address.length - extension.length) + '.js';
  }

  for (var p in paths) {

    curPath = decodeURI(url.resolve(encodeURI(baseURL), paths[p].replace(/\\/g, '/')));
    wIndex = curPath.indexOf('*');

    if (wIndex === -1) {
      if (address === curPath) {
        curMatchLength = curPath.split('/').length;
        if (curMatchLength > pathMatchLength) {
          pathMatch = p;
          pathMatchLength = curMatchLength;
        }
      }
    } else {
      if (address.substr(0, wIndex) === curPath.substr(0, wIndex) && address.substr(address.length - curPath.length + wIndex + 1) === curPath.substr(wIndex + 1)) {
        curMatchLength = curPath.split('/').length;
        if (curMatchLength > pathMatchLength) {
          pathMatch = p.replace('*', address.substr(wIndex, address.length - curPath.length + 1));
          pathMatchLength = curMatchLength;
        }
      }
    }
  }

  if (!pathMatch)
    throw "Unable to calculate path for " + address;

  if (pluginName)
    pathMatch += extension + '!' + (pluginName == extension ? '' : pluginName);

  return pathMatch;
}
<commit_msg>fix(view bundle): View bundling doesn’t take into account system.js baseURL #103<commit_after>import api from 'jspm/api';
import whacko from 'whacko';
import glob from 'glob';
import fs from 'fs';
import url from 'url';
import path from 'path';

var pluginName = 'view';

function bundleJS(moduleExpression, outfile, options) {
  api.bundle(moduleExpression, outfile, options);
}

export default function bundle(config) {

  var loader = api.Builder().loader;
  var baseURL = loader.baseURL;
  var paths = loader.paths;

  var jsConfig = config.js;
  var templateConfig = config.template;

  Object.keys(jsConfig)
    .forEach(function(key) {
      var cfg = jsConfig[key];
      var outfile = key + '.js';
      var moduleExpr = cfg.modules.join(' + ');
      var opt = cfg.options;

      bundleJS(moduleExpr, outfile, opt);
    });

  Object.keys(templateConfig)
    .forEach(function(key) {
      var cfg = templateConfig[key];
      var outfile = key + '.html';
      var pattern = cfg.pattern;
      var options = cfg.options;

      bundleTemplate(pattern, outfile, options, baseURL, paths);
    });
}

function bundleTemplate(pattern, outfile, options, baseURL, paths) {
  var templates = [];
  var cwd = baseURL.replace(/^file:/, '');

  glob
    .sync(pattern, {cwd: cwd})
    .forEach(function(file) {

      file = path.resolve(cwd, file);
      console.log(file);

      var content = fs.readFileSync(file, {
        encoding: 'utf8'
      });
      var $ = whacko.load(content);
      var tid = getTemplateId(file, baseURL, paths);

      $('template').attr('id', tid);
      var template = $.html('template');
      templates.push(template);
    });

  fs.writeFileSync(outfile, templates.join('\n'));

  if (options.inject) {
    injectLink(outfile, baseURL);
  }
}

function injectLink(outfile, baseURL) {
  var bu = baseURL.replace(/^file:/, '') + path.sep;
  var content = fs.readFileSync(bu + 'index.html', {
    encoding: 'utf8'
  });

  var $ = whacko.load(content);

  $('head').append('<link aurlia-view-bundle rel="import" href="./' + outfile + '">');
}

function getTemplateId(file, baseURL, paths) {
  var bu = baseURL.replace(/\\/g, '/') + '/';
   var address = 'file:' +  file.replace(/\\/g, '/');
  return getModuleName(address, bu, paths);
}

function getModuleName(address, baseURL, paths) {
  var pathMatch, curMatchLength, curPath, wIndex, pathMatchLength = 0;

  if (pluginName) {
    var extension = address.split('/').pop();
    extension = extension.substr(extension.lastIndexOf('.'));
    if (extension != address && extension != '.js')
      address = address.substr(0, address.length - extension.length) + '.js';
  }

  for (var p in paths) {

    curPath = decodeURI(url.resolve(encodeURI(baseURL), paths[p].replace(/\\/g, '/')));
    wIndex = curPath.indexOf('*');

    if (wIndex === -1) {
      if (address === curPath) {
        curMatchLength = curPath.split('/').length;
        if (curMatchLength > pathMatchLength) {
          pathMatch = p;
          pathMatchLength = curMatchLength;
        }
      }
    } else {
      if (address.substr(0, wIndex) === curPath.substr(0, wIndex)
          && address.substr(address.length - curPath.length + wIndex + 1) === curPath.substr(wIndex + 1)) {
        curMatchLength = curPath.split('/').length;
        if (curMatchLength > pathMatchLength) {
          pathMatch = p.replace('*', address.substr(wIndex, address.length - curPath.length + 1));
          pathMatchLength = curMatchLength;
        }
      }
    }
  }

  if (!pathMatch)
    throw "Unable to calculate path for " + address;

  if (pluginName)
    pathMatch += extension + '!' + (pluginName == extension ? '' : pluginName);

  return pathMatch;
}
<|endoftext|>