UNPKG

fieldkit

Version:

Basic building blocks for computational design projects. Written in CoffeeScript for browser and server environments.

316 lines (264 loc) 7.95 kB
// Generated by CoffeeScript 1.6.3 (function() { var EXObject, Mixin, clone, extend, removeElement, shuffle, util, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; util = require("util"); /* JavaScript Language Utilities ------------------------------------------------------------------------------------------ */ extend = function(obj, source) { var i, il, keys, prop, safeHasOwnProperty; if (Object.keys) { keys = Object.keys(source); i = 0; il = keys.length; while (i < il) { prop = keys[i]; Object.defineProperty(obj, prop, Object.getOwnPropertyDescriptor(source, prop)); i++; } } else { safeHasOwnProperty = {}.hasOwnProperty; for (prop in source) { if (safeHasOwnProperty.call(source, prop)) { obj[prop] = source[prop]; } } } return obj; }; /* Swappable Mixins in CoffeeScript Many thanks to Hashmal, who wrote this to start. https://gist.github.com/803816/aceed8fc57188c3a19ce2eccdb25acb64f2be94e Usage ----- class Derp extends Mixin setup: -> @googly = "eyes" derp: -> alert "Herp derp! What's with your #{ @googly }?" class Herp constructor: -> Derp::augment this herp = new Herp herp.derp() Mixin ----- Classes inheriting `Mixin` will become removable mixins, enabling you to swap them around. Limitations ----------- * When a class is augmented, all instances of that class are augmented too, and when a mixin is ejected from a class, all instances lose that mixin too. * You can't eject a mixin from an object if that mixin was added to the object's class. Eject the mixin from the class instead. */ Mixin = (function() { function Mixin() {} Mixin.prototype.augment = function(t) { var m, n; for (n in this) { m = this[n]; if (!(n === 'augment' || (this[n].prototype == null))) { t[n] = m; } } return t.setup(); }; Mixin.prototype.eject = function(mixin) { var m, n, o, p, _results; _results = []; for (n in this) { m = this[n]; _results.push(__indexOf.call((function() { var _ref, _results1; _ref = mixin.prototype; _results1 = []; for (o in _ref) { p = _ref[o]; _results1.push(p); } return _results1; })(), m) >= 0 ? delete this[n] : void 0); } return _results; }; Mixin.prototype.setup = function() {}; return Mixin; })(); /* Clones (copies) an Object using deep copying. This function supports circular references by default, but if you are certain there are no circular references in your object, you can save some CPU time by calling clone(obj, false). Caution: if `circular` is false and `parent` contains circular references, your program may enter an infinite loop and crash. @param `parent` - the object to be cloned @param `circular` - set to true if the object to be cloned may contain circular references. (optional - true by default) */ clone = function(parent, circular) { var c, child, circularParent, circularReplace, circularResolved, cloned, i, useBuffer, _clone; if (typeof circular === "undefined") { circular = true; } useBuffer = typeof Buffer !== "undefined"; i = void 0; if (circular) { _clone = function(parent, context, child, cIndex) { i = void 0; if (typeof parent === "object") { if (parent == null) { return parent; } for (i in circularParent) { if (circularParent[i] === parent) { circularReplace.push({ resolveTo: i, child: child, i: cIndex }); return null; } } circularParent[context] = parent; if (util.isArray(parent)) { child = []; for (i in parent) { child[i] = _clone(parent[i], context + "[" + i + "]", child, i); } } else if (util.isDate(parent)) { child = new Date(parent.getTime()); } else if (util.isRegExp(parent)) { child = new RegExp(parent.source); } else if (useBuffer && Buffer.isBuffer(parent)) { child = new Buffer(parent.length); parent.copy(child); } else { child = {}; child.__proto__ = parent.__proto__; for (i in parent) { child[i] = _clone(parent[i], context + "[" + i + "]", child, i); } } circularResolved[context] = child; } else { child = parent; } return child; }; circularParent = {}; circularResolved = {}; circularReplace = []; cloned = _clone(parent, "*"); for (i in circularReplace) { c = circularReplace[i]; if (c && c.child && c.i in c.child) { c.child[c.i] = circularResolved[c.resolveTo]; } } return cloned; } else { child = void 0; if (typeof parent === "object") { if (parent == null) { return parent; } if (parent.constructor.name === "Array") { child = []; for (i in parent) { child[i] = clone(parent[i], circular); } } else if (util.isDate(parent)) { child = new Date(parent.getTime()); } else if (!util.isRegExp(parent)) { child = {}; child.__proto__ = parent.__proto__; for (i in parent) { child[i] = clone(parent[i], circular); } } } else { child = parent; } return child; } }; clone.clonePrototype = function(parent) { var ctor; if (parent === null) { return null; } ctor = function() {}; ctor.prototype = parent; return new ctor(); }; /* JavaScript getter and setter support for CoffeeScript classes Ref: https://github.com/jashkenas/coffee-script/issues/1039 Note: Classes using this wont work under IE6 + IE7 Usage: class Vector3D extends EXObject constructor: (@x, @y, @z) -> @get 'x', -> @[0] @get 'y', -> @[1] @get 'z', -> @[2] @set 'x', (x) -> @[0] = x @set 'y', (y) -> @[1] = y @set 'z', (z) -> @[2] = z */ EXObject = (function() { function EXObject() {} EXObject.get = function(propertyName, func) { return Object.defineProperty(this.prototype, propertyName, { configurable: true, enumerable: true, get: func }); }; EXObject.set = function(propertyName, func) { return Object.defineProperty(this.prototype, propertyName, { configurable: true, enumerable: true, set: func }); }; return EXObject; })(); /* Array Utilities ------------------------------------------------------------------------------------------ */ removeElement = function(element, list) { var index; index = list.indexOf(element); if (index !== -1) { list.splice(index, 1); } return list; }; shuffle = function(object, rng) { var i, j, x; if (rng == null) { rng = Math; } i = object.length; while (i) { j = parseInt(rng.random() * i); x = object[--i]; object[i] = object[j]; object[j] = x; } return object; }; module.exports = { extend: extend, clone: clone, EXObject: EXObject, Mixin: Mixin, removeElement: removeElement, shuffle: shuffle }; }).call(this);