object[property]
- *
- * @param {Object} newValue The new value of object[property]
- */
- setValue: function(newValue) {
- this.object[this.property] = newValue;
- if (this.__onChange) {
- this.__onChange.call(this, newValue);
- }
- this.updateDisplay();
- return this;
- },
-
- /**
- * Gets the value of object[property]
- *
- * @returns {Object} The current value of object[property]
- */
- getValue: function() {
- return this.object[this.property];
- },
-
- /**
- * Refreshes the visual display of a Controller in order to keep sync
- * with the object's current value.
- * @returns {dat.controllers.Controller} this
- */
- updateDisplay: function() {
- return this;
- },
-
- /**
- * @returns {Boolean} true if the value has deviated from initialValue
- */
- isModified: function() {
- return this.initialValue !== this.getValue()
- }
+ get: function() {
+ if (this.__state.space === 'RGB') {
+ return this.__state[component];
}
- );
+ recalculateRGB(this, component, componentHexIndex);
- return Controller;
+ return this.__state[component];
+ },
-})(dat.utils.common);
+ set: function(v) {
+ if (this.__state.space !== 'RGB') {
+ recalculateRGB(this, component, componentHexIndex);
+ this.__state.space = 'RGB';
+ }
-dat.dom.dom = (function (common) {
+ this.__state[component] = v;
- var EVENT_MAP = {
- 'HTMLEvents': ['change'],
- 'MouseEvents': ['click','mousemove','mousedown','mouseup', 'mouseover'],
- 'KeyboardEvents': ['keydown']
- };
+ }
- var EVENT_MAP_INV = {};
- common.each(EVENT_MAP, function(v, k) {
- common.each(v, function(e) {
- EVENT_MAP_INV[e] = k;
- });
});
- var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/;
+}
- function cssValueToPixels(val) {
+function defineHSVComponent(target, component) {
- if (val === '0' || common.isUndefined(val)) return 0;
+ Object.defineProperty(target, component, {
- var match = val.match(CSS_VALUE_PIXELS);
+ get: function() {
+
+ if (this.__state.space === 'HSV')
+ return this.__state[component];
+
+ recalculateHSV(this);
+
+ return this.__state[component];
+
+ },
+
+ set: function(v) {
+
+ if (this.__state.space !== 'HSV') {
+ recalculateHSV(this);
+ this.__state.space = 'HSV';
+ }
+
+ this.__state[component] = v;
- if (!common.isNull(match)) {
- return parseFloat(match[1]);
}
- // TODO ...ems? %?
+ });
- return 0;
+}
+
+function recalculateRGB(color, component, componentHexIndex) {
+
+ if (color.__state.space === 'HEX') {
+
+ color.__state[component] = math.component_from_hex(color.__state.hex, componentHexIndex);
+
+ } else if (color.__state.space === 'HSV') {
+
+ common.extend(color.__state, math.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v));
+
+ } else {
+
+ throw 'Corrupted color state';
}
- /**
- * @namespace
- * @member dat.dom
- */
- var dom = {
+}
- /**
- *
- * @param elem
- * @param selectable
- */
- makeSelectable: function(elem, selectable) {
+function recalculateHSV(color) {
- if (elem === undefined || elem.style === undefined) return;
+ var result = math.rgb_to_hsv(color.r, color.g, color.b);
- elem.onselectstart = selectable ? function() {
- return false;
- } : function() {
- };
+ common.extend(color.__state, {
+ s: result.s,
+ v: result.v
+ });
- elem.style.MozUserSelect = selectable ? 'auto' : 'none';
- elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none';
- elem.unselectable = selectable ? 'on' : 'off';
-
- },
-
- /**
- *
- * @param elem
- * @param horizontal
- * @param vertical
- */
- makeFullscreen: function(elem, horizontal, vertical) {
-
- if (common.isUndefined(horizontal)) horizontal = true;
- if (common.isUndefined(vertical)) vertical = true;
-
- elem.style.position = 'absolute';
-
- if (horizontal) {
- elem.style.left = 0;
- elem.style.right = 0;
- }
- if (vertical) {
- elem.style.top = 0;
- elem.style.bottom = 0;
- }
-
- },
-
- /**
- *
- * @param elem
- * @param eventType
- * @param params
- */
- fakeEvent: function(elem, eventType, params, aux) {
- params = params || {};
- var className = EVENT_MAP_INV[eventType];
- if (!className) {
- throw new Error('Event type ' + eventType + ' not supported.');
- }
- var evt = document.createEvent(className);
- switch (className) {
- case 'MouseEvents':
- var clientX = params.x || params.clientX || 0;
- var clientY = params.y || params.clientY || 0;
- evt.initMouseEvent(eventType, params.bubbles || false,
- params.cancelable || true, window, params.clickCount || 1,
- 0, //screen X
- 0, //screen Y
- clientX, //client X
- clientY, //client Y
- false, false, false, false, 0, null);
- break;
- case 'KeyboardEvents':
- var init = evt.initKeyboardEvent || evt.initKeyEvent; // webkit || moz
- common.defaults(params, {
- cancelable: true,
- ctrlKey: false,
- altKey: false,
- shiftKey: false,
- metaKey: false,
- keyCode: undefined,
- charCode: undefined
- });
- init(eventType, params.bubbles || false,
- params.cancelable, window,
- params.ctrlKey, params.altKey,
- params.shiftKey, params.metaKey,
- params.keyCode, params.charCode);
- break;
- default:
- evt.initEvent(eventType, params.bubbles || false,
- params.cancelable || true);
- break;
- }
- common.defaults(evt, aux);
- elem.dispatchEvent(evt);
- },
-
- /**
- *
- * @param elem
- * @param event
- * @param func
- * @param bool
- */
- bind: function(elem, event, func, bool) {
- bool = bool || false;
- if (elem.addEventListener)
- elem.addEventListener(event, func, bool);
- else if (elem.attachEvent)
- elem.attachEvent('on' + event, func);
- return dom;
- },
-
- /**
- *
- * @param elem
- * @param event
- * @param func
- * @param bool
- */
- unbind: function(elem, event, func, bool) {
- bool = bool || false;
- if (elem.removeEventListener)
- elem.removeEventListener(event, func, bool);
- else if (elem.detachEvent)
- elem.detachEvent('on' + event, func);
- return dom;
- },
-
- /**
- *
- * @param elem
- * @param className
- */
- addClass: function(elem, className) {
- if (elem.className === undefined) {
- elem.className = className;
- } else if (elem.className !== className) {
- var classes = elem.className.split(/ +/);
- if (classes.indexOf(className) == -1) {
- classes.push(className);
- elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, '');
- }
- }
- return dom;
- },
-
- /**
- *
- * @param elem
- * @param className
- */
- removeClass: function(elem, className) {
- if (className) {
- if (elem.className === undefined) {
- // elem.className = className;
- } else if (elem.className === className) {
- elem.removeAttribute('class');
- } else {
- var classes = elem.className.split(/ +/);
- var index = classes.indexOf(className);
- if (index != -1) {
- classes.splice(index, 1);
- elem.className = classes.join(' ');
- }
- }
- } else {
- elem.className = undefined;
- }
- return dom;
- },
-
- hasClass: function(elem, className) {
- return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false;
- },
-
- /**
- *
- * @param elem
- */
- getWidth: function(elem) {
-
- var style = getComputedStyle(elem);
-
- return cssValueToPixels(style['border-left-width']) +
- cssValueToPixels(style['border-right-width']) +
- cssValueToPixels(style['padding-left']) +
- cssValueToPixels(style['padding-right']) +
- cssValueToPixels(style['width']);
- },
-
- /**
- *
- * @param elem
- */
- getHeight: function(elem) {
-
- var style = getComputedStyle(elem);
-
- return cssValueToPixels(style['border-top-width']) +
- cssValueToPixels(style['border-bottom-width']) +
- cssValueToPixels(style['padding-top']) +
- cssValueToPixels(style['padding-bottom']) +
- cssValueToPixels(style['height']);
- },
-
- /**
- *
- * @param elem
- */
- getOffset: function(elem) {
- var offset = {left: 0, top:0};
- if (elem.offsetParent) {
- do {
- offset.left += elem.offsetLeft;
- offset.top += elem.offsetTop;
- } while (elem = elem.offsetParent);
- }
- return offset;
- },
-
- // http://stackoverflow.com/posts/2684561/revisions
- /**
- *
- * @param elem
- */
- isActive: function(elem) {
- return elem === document.activeElement && ( elem.type || elem.href );
- }
-
- };
-
- return dom;
-
-})(dat.utils.common);
-
-
-dat.controllers.OptionController = (function (Controller, dom, common) {
-
- /**
- * @class Provides a select input to alter the property of an object, using a
- * list of accepted values.
- *
- * @extends dat.controllers.Controller
- *
- * @param {Object} object The object to be manipulated
- * @param {string} property The name of the property to be manipulated
- * @param {Object|string[]} options A map of labels to acceptable values, or
- * a list of acceptable string values.
- *
- * @member dat.controllers
- */
- var OptionController = function(object, property, options) {
-
- OptionController.superclass.call(this, object, property);
-
- var _this = this;
-
- /**
- * The drop down menu
- * @ignore
- */
- this.__select = document.createElement('select');
-
- if (common.isArray(options)) {
- var map = {};
- common.each(options, function(element) {
- map[element] = element;
- });
- options = map;
- }
-
- common.each(options, function(value, key) {
-
- var opt = document.createElement('option');
- opt.innerHTML = key;
- opt.setAttribute('value', value);
- _this.__select.appendChild(opt);
-
- });
-
- // Acknowledge original value
- this.updateDisplay();
-
- dom.bind(this.__select, 'change', function() {
- var desiredValue = this.options[this.selectedIndex].value;
- _this.setValue(desiredValue);
- });
-
- this.domElement.appendChild(this.__select);
-
- };
-
- OptionController.superclass = Controller;
-
- common.extend(
-
- OptionController.prototype,
- Controller.prototype,
-
- {
-
- setValue: function(v) {
- var toReturn = OptionController.superclass.prototype.setValue.call(this, v);
- if (this.__onFinishChange) {
- this.__onFinishChange.call(this, this.getValue());
- }
- return toReturn;
- },
-
- updateDisplay: function() {
- this.__select.value = this.getValue();
- return OptionController.superclass.prototype.updateDisplay.call(this);
- }
-
- }
-
- );
-
- return OptionController;
-
-})(dat.controllers.Controller,
-dat.dom.dom,
-dat.utils.common);
-
-
-dat.controllers.NumberController = (function (Controller, common) {
-
- /**
- * @class Represents a given property of an object that is a number.
- *
- * @extends dat.controllers.Controller
- *
- * @param {Object} object The object to be manipulated
- * @param {string} property The name of the property to be manipulated
- * @param {Object} [params] Optional parameters
- * @param {Number} [params.min] Minimum allowed value
- * @param {Number} [params.max] Maximum allowed value
- * @param {Number} [params.step] Increment by which to change value
- *
- * @member dat.controllers
- */
- var NumberController = function(object, property, params) {
-
- NumberController.superclass.call(this, object, property);
-
- params = params || {};
-
- this.__min = params.min;
- this.__max = params.max;
- this.__step = params.step;
-
- if (common.isUndefined(this.__step)) {
-
- if (this.initialValue == 0) {
- this.__impliedStep = 1; // What are we, psychics?
- } else {
- // Hey Doug, check this out.
- this.__impliedStep = Math.pow(10, Math.floor(Math.log(this.initialValue)/Math.LN10))/10;
- }
-
- } else {
-
- this.__impliedStep = this.__step;
-
- }
-
- this.__precision = numDecimals(this.__impliedStep);
-
-
- };
-
- NumberController.superclass = Controller;
-
- common.extend(
-
- NumberController.prototype,
- Controller.prototype,
-
- /** @lends dat.controllers.NumberController.prototype */
- {
-
- setValue: function(v) {
-
- if (this.__min !== undefined && v < this.__min) {
- v = this.__min;
- } else if (this.__max !== undefined && v > this.__max) {
- v = this.__max;
- }
-
- if (this.__step !== undefined && v % this.__step != 0) {
- v = Math.round(v / this.__step) * this.__step;
- }
-
- return NumberController.superclass.prototype.setValue.call(this, v);
-
- },
-
- /**
- * Specify a minimum value for object[property]
.
- *
- * @param {Number} minValue The minimum value for
- * object[property]
- * @returns {dat.controllers.NumberController} this
- */
- min: function(v) {
- this.__min = v;
- return this;
- },
-
- /**
- * Specify a maximum value for object[property]
.
- *
- * @param {Number} maxValue The maximum value for
- * object[property]
- * @returns {dat.controllers.NumberController} this
- */
- max: function(v) {
- this.__max = v;
- return this;
- },
-
- /**
- * Specify a step value that dat.controllers.NumberController
- * increments by.
- *
- * @param {Number} stepValue The step value for
- * dat.controllers.NumberController
- * @default if minimum and maximum specified increment is 1% of the
- * difference otherwise stepValue is 1
- * @returns {dat.controllers.NumberController} this
- */
- step: function(v) {
- this.__step = v;
- this.__impliedStep = v;
- this.__precision = numDecimals(v);
- return this;
- }
-
- }
-
- );
-
- function numDecimals(x) {
- x = x.toString();
- if (x.indexOf('.') > -1) {
- return x.length - x.indexOf('.') - 1;
- } else {
- return 0;
- }
+ if (!common.isNaN(result.h)) {
+ color.__state.h = result.h;
+ } else if (common.isUndefined(color.__state.h)) {
+ color.__state.h = 0;
}
- return NumberController;
-
-})(dat.controllers.Controller,
-dat.utils.common);
-
-
-dat.controllers.NumberControllerBox = (function (NumberController, dom, common) {
-
- /**
- * @class Represents a given property of an object that is a number and
- * provides an input element with which to manipulate it.
- *
- * @extends dat.controllers.Controller
- * @extends dat.controllers.NumberController
- *
- * @param {Object} object The object to be manipulated
- * @param {string} property The name of the property to be manipulated
- * @param {Object} [params] Optional parameters
- * @param {Number} [params.min] Minimum allowed value
- * @param {Number} [params.max] Maximum allowed value
- * @param {Number} [params.step] Increment by which to change value
- *
- * @member dat.controllers
- */
- var NumberControllerBox = function(object, property, params) {
-
- this.__truncationSuspended = false;
-
- NumberControllerBox.superclass.call(this, object, property, params);
-
- var _this = this;
-
- /**
- * {Number} Previous mouse y position
- * @ignore
- */
- var prev_y;
-
- this.__input = document.createElement('input');
- this.__input.setAttribute('type', 'text');
-
- // Makes it so manually specified values are not truncated.
-
- dom.bind(this.__input, 'change', onChange);
- dom.bind(this.__input, 'blur', onBlur);
- dom.bind(this.__input, 'mousedown', onMouseDown);
- dom.bind(this.__input, 'keydown', function(e) {
-
- // When pressing entire, you can be as precise as you want.
- if (e.keyCode === 13) {
- _this.__truncationSuspended = true;
- this.blur();
- _this.__truncationSuspended = false;
- }
-
- });
-
- function onChange() {
- var attempted = parseFloat(_this.__input.value);
- if (!common.isNaN(attempted)) _this.setValue(attempted);
- }
-
- function onBlur() {
- onChange();
- if (_this.__onFinishChange) {
- _this.__onFinishChange.call(_this, _this.getValue());
- }
- }
-
- function onMouseDown(e) {
- dom.bind(window, 'mousemove', onMouseDrag);
- dom.bind(window, 'mouseup', onMouseUp);
- prev_y = e.clientY;
- }
-
- function onMouseDrag(e) {
-
- var diff = prev_y - e.clientY;
- _this.setValue(_this.getValue() + diff * _this.__impliedStep);
-
- prev_y = e.clientY;
-
- }
-
- function onMouseUp() {
- dom.unbind(window, 'mousemove', onMouseDrag);
- dom.unbind(window, 'mouseup', onMouseUp);
- }
-
- this.updateDisplay();
-
- this.domElement.appendChild(this.__input);
-
- };
-
- NumberControllerBox.superclass = NumberController;
-
- common.extend(
-
- NumberControllerBox.prototype,
- NumberController.prototype,
-
- {
-
- updateDisplay: function() {
-
- this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision);
- return NumberControllerBox.superclass.prototype.updateDisplay.call(this);
- }
-
- }
-
- );
-
- function roundToDecimal(value, decimals) {
- var tenTo = Math.pow(10, decimals);
- return Math.round(value * tenTo) / tenTo;
- }
-
- return NumberControllerBox;
-
-})(dat.controllers.NumberController,
-dat.dom.dom,
-dat.utils.common);
-
-
-dat.controllers.NumberControllerSlider = (function (NumberController, dom, css, common, styleSheet) {
-
- /**
- * @class Represents a given property of an object that is a number, contains
- * a minimum and maximum, and provides a slider element with which to
- * manipulate it. It should be noted that the slider element is made up of
- * <div>
tags, not the html5
- * <slider>
element.
- *
- * @extends dat.controllers.Controller
- * @extends dat.controllers.NumberController
- *
- * @param {Object} object The object to be manipulated
- * @param {string} property The name of the property to be manipulated
- * @param {Number} minValue Minimum allowed value
- * @param {Number} maxValue Maximum allowed value
- * @param {Number} stepValue Increment by which to change value
- *
- * @member dat.controllers
- */
- var NumberControllerSlider = function(object, property, min, max, step) {
-
- NumberControllerSlider.superclass.call(this, object, property, { min: min, max: max, step: step });
-
- var _this = this;
-
- this.__background = document.createElement('div');
- this.__foreground = document.createElement('div');
-
-
-
- dom.bind(this.__background, 'mousedown', onMouseDown);
-
- dom.addClass(this.__background, 'slider');
- dom.addClass(this.__foreground, 'slider-fg');
-
- function onMouseDown(e) {
-
- dom.bind(window, 'mousemove', onMouseDrag);
- dom.bind(window, 'mouseup', onMouseUp);
-
- onMouseDrag(e);
- }
-
- function onMouseDrag(e) {
-
- e.preventDefault();
-
- var offset = dom.getOffset(_this.__background);
- var width = dom.getWidth(_this.__background);
-
- _this.setValue(
- map(e.clientX, offset.left, offset.left + width, _this.__min, _this.__max)
- );
-
- return false;
-
- }
-
- function onMouseUp() {
- dom.unbind(window, 'mousemove', onMouseDrag);
- dom.unbind(window, 'mouseup', onMouseUp);
- if (_this.__onFinishChange) {
- _this.__onFinishChange.call(_this, _this.getValue());
- }
- }
-
- this.updateDisplay();
-
- this.__background.appendChild(this.__foreground);
- this.domElement.appendChild(this.__background);
-
- };
-
- NumberControllerSlider.superclass = NumberController;
-
- /**
- * Injects default stylesheet for slider elements.
- */
- NumberControllerSlider.useDefaultStyles = function() {
- css.inject(styleSheet);
- };
-
- common.extend(
-
- NumberControllerSlider.prototype,
- NumberController.prototype,
-
- {
-
- updateDisplay: function() {
- var pct = (this.getValue() - this.__min)/(this.__max - this.__min);
- this.__foreground.style.width = pct*100+'%';
- return NumberControllerSlider.superclass.prototype.updateDisplay.call(this);
- }
-
- }
-
-
-
- );
-
- function map(v, i1, i2, o1, o2) {
- return o1 + (o2 - o1) * ((v - i1) / (i2 - i1));
- }
-
- return NumberControllerSlider;
-
-})(dat.controllers.NumberController,
-dat.dom.dom,
-dat.utils.css,
-dat.utils.common,
-"/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}");
-
-
-dat.controllers.FunctionController = (function (Controller, dom, common) {
-
- /**
- * @class Provides a GUI interface to fire a specified method, a property of an object.
- *
- * @extends dat.controllers.Controller
- *
- * @param {Object} object The object to be manipulated
- * @param {string} property The name of the property to be manipulated
- *
- * @member dat.controllers
- */
- var FunctionController = function(object, property, text) {
-
- FunctionController.superclass.call(this, object, property);
-
- var _this = this;
-
- this.__button = document.createElement('div');
- this.__button.innerHTML = text === undefined ? 'Fire' : text;
- dom.bind(this.__button, 'click', function(e) {
- e.preventDefault();
- _this.fire();
- return false;
- });
-
- dom.addClass(this.__button, 'button');
-
- this.domElement.appendChild(this.__button);
-
-
- };
-
- FunctionController.superclass = Controller;
-
- common.extend(
-
- FunctionController.prototype,
- Controller.prototype,
- {
-
- fire: function() {
- if (this.__onChange) {
- this.__onChange.call(this);
- }
- this.getValue().call(this.object);
- if (this.__onFinishChange) {
- this.__onFinishChange.call(this, this.getValue());
- }
- }
- }
-
- );
-
- return FunctionController;
-
-})(dat.controllers.Controller,
-dat.dom.dom,
-dat.utils.common);
-
-
-dat.controllers.BooleanController = (function (Controller, dom, common) {
-
- /**
- * @class Provides a checkbox input to alter the boolean property of an object.
- * @extends dat.controllers.Controller
- *
- * @param {Object} object The object to be manipulated
- * @param {string} property The name of the property to be manipulated
- *
- * @member dat.controllers
- */
- var BooleanController = function(object, property) {
-
- BooleanController.superclass.call(this, object, property);
-
- var _this = this;
- this.__prev = this.getValue();
-
- this.__checkbox = document.createElement('input');
- this.__checkbox.setAttribute('type', 'checkbox');
-
-
- dom.bind(this.__checkbox, 'change', onChange, false);
-
- this.domElement.appendChild(this.__checkbox);
-
- // Match original value
- this.updateDisplay();
-
- function onChange() {
- _this.setValue(!_this.__prev);
- }
-
- };
-
- BooleanController.superclass = Controller;
-
- common.extend(
-
- BooleanController.prototype,
- Controller.prototype,
-
- {
-
- setValue: function(v) {
- var toReturn = BooleanController.superclass.prototype.setValue.call(this, v);
- if (this.__onFinishChange) {
- this.__onFinishChange.call(this, this.getValue());
- }
- this.__prev = this.getValue();
- return toReturn;
- },
-
- updateDisplay: function() {
-
- if (this.getValue() === true) {
- this.__checkbox.setAttribute('checked', 'checked');
- this.__checkbox.checked = true;
- } else {
- this.__checkbox.checked = false;
- }
-
- return BooleanController.superclass.prototype.updateDisplay.call(this);
-
- }
-
-
- }
-
- );
-
- return BooleanController;
-
-})(dat.controllers.Controller,
-dat.dom.dom,
-dat.utils.common);
-
-
-dat.color.toString = (function (common) {
-
- return function(color) {
-
- if (color.a == 1 || common.isUndefined(color.a)) {
-
- var s = color.hex.toString(16);
- while (s.length < 6) {
- s = '0' + s;
- }
-
- return '#' + s;
-
- } else {
-
- return 'rgba(' + Math.round(color.r) + ',' + Math.round(color.g) + ',' + Math.round(color.b) + ',' + color.a + ')';
-
- }
-
- }
-
-})(dat.utils.common);
-
-
-dat.color.interpret = (function (toString, common) {
+}
+
+},{"../utils/common.js":18,"./interpret.js":2,"./math.js":3,"./toString.js":4}],2:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+module.exports = createInterpert();
+
+function createInterpert() {
+ var common = require('../utils/common.js');
+ var toString = require('./toString.js');
var result, toReturn;
@@ -1525,11 +522,1858 @@ dat.color.interpret = (function (toString, common) {
return interpret;
-})(dat.color.toString,
-dat.utils.common);
+}
+
+},{"../utils/common.js":18,"./toString.js":4}],3:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+module.exports = math();
+
+function math() {
+
+ var tmpComponent;
+
+ return {
+
+ hsv_to_rgb: function(h, s, v) {
+
+ var hi = Math.floor(h / 60) % 6;
+
+ var f = h / 60 - Math.floor(h / 60);
+ var p = v * (1.0 - s);
+ var q = v * (1.0 - (f * s));
+ var t = v * (1.0 - ((1.0 - f) * s));
+ var c = [
+ [v, t, p],
+ [q, v, p],
+ [p, v, t],
+ [p, q, v],
+ [t, p, v],
+ [v, p, q]
+ ][hi];
+
+ return {
+ r: c[0] * 255,
+ g: c[1] * 255,
+ b: c[2] * 255
+ };
+
+ },
+
+ rgb_to_hsv: function(r, g, b) {
+
+ var min = Math.min(r, g, b),
+ max = Math.max(r, g, b),
+ delta = max - min,
+ h, s;
+
+ if (max != 0) {
+ s = delta / max;
+ } else {
+ return {
+ h: NaN,
+ s: 0,
+ v: 0
+ };
+ }
+
+ if (r == max) {
+ h = (g - b) / delta;
+ } else if (g == max) {
+ h = 2 + (b - r) / delta;
+ } else {
+ h = 4 + (r - g) / delta;
+ }
+ h /= 6;
+ if (h < 0) {
+ h += 1;
+ }
+
+ return {
+ h: h * 360,
+ s: s,
+ v: max / 255
+ };
+ },
+
+ rgb_to_hex: function(r, g, b) {
+ var hex = this.hex_with_component(0, 2, r);
+ hex = this.hex_with_component(hex, 1, g);
+ hex = this.hex_with_component(hex, 0, b);
+ return hex;
+ },
+
+ component_from_hex: function(hex, componentIndex) {
+ return (hex >> (componentIndex * 8)) & 0xFF;
+ },
+
+ hex_with_component: function(hex, componentIndex, value) {
+ return value << (tmpComponent = componentIndex * 8) | (hex & ~(0xFF << tmpComponent));
+ }
+
+ };
+}
+
+},{}],4:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var common = require('../utils/common.js');
+
+module.exports = toString;
+
+function toString(color) {
+
+ if (color.a == 1 || common.isUndefined(color.a)) {
+
+ var s = color.hex.toString(16);
+ while (s.length < 6) {
+ s = '0' + s;
+ }
+
+ return '#' + s;
+
+ } else {
+
+ return 'rgba(' + Math.round(color.r) + ',' + Math.round(color.g) + ',' + Math.round(color.b) + ',' + color.a + ')';
+
+ }
+
+}
+
+},{"../utils/common.js":18}],5:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var Controller = require('./Controller.js');
+var common = require('../utils/common.js');
+var dom = require('../dom/dom.js');
+
+module.exports = BooleanController;
+
+/**
+ * @class Provides a checkbox input to alter the boolean property of an object.
+ * @extends dat.controllers.Controller
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ *
+ * @member dat.controllers
+ */
+function BooleanController(object, property) {
+
+ BooleanController.superclass.call(this, object, property);
+
+ var _this = this;
+ this.__prev = this.getValue();
+
+ this.__checkbox = document.createElement('input');
+ this.__checkbox.setAttribute('type', 'checkbox');
-dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, controllerFactory, Controller, BooleanController, FunctionController, NumberControllerBox, NumberControllerSlider, OptionController, ColorController, requestAnimationFrame, CenteredDiv, dom, common) {
+ dom.bind(this.__checkbox, 'change', onChange, false);
+
+ this.domElement.appendChild(this.__checkbox);
+
+ // Match original value
+ this.updateDisplay();
+
+ function onChange() {
+ _this.setValue(!_this.__prev);
+ }
+
+}
+
+BooleanController.superclass = Controller;
+
+common.extend(
+
+ BooleanController.prototype,
+ Controller.prototype,
+
+ {
+
+ setValue: function(v) {
+ var toReturn = BooleanController.superclass.prototype.setValue.call(this, v);
+ if (this.__onFinishChange) {
+ this.__onFinishChange.call(this, this.getValue());
+ }
+ this.__prev = this.getValue();
+ return toReturn;
+ },
+
+ updateDisplay: function() {
+
+ if (this.getValue() === true) {
+ this.__checkbox.setAttribute('checked', 'checked');
+ this.__checkbox.checked = true;
+ } else {
+ this.__checkbox.checked = false;
+ }
+
+ return BooleanController.superclass.prototype.updateDisplay.call(this);
+
+ }
+
+
+ }
+
+);
+
+},{"../dom/dom.js":16,"../utils/common.js":18,"./Controller.js":7}],6:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var Controller = require('./Controller.js');
+var common = require('../utils/common.js');
+var dom = require('../dom/dom.js');
+var Color = require('../color/Color.js');
+var interpret = require('../color/interpret.js');
+
+module.exports = ColorController;
+
+function ColorController(object, property) {
+
+ ColorController.superclass.call(this, object, property);
+
+ this.__color = new Color(this.getValue());
+ this.__temp = new Color(0);
+
+ var _this = this;
+
+ this.domElement = document.createElement('div');
+
+ dom.makeSelectable(this.domElement, false);
+
+ this.__selector = document.createElement('div');
+ this.__selector.className = 'selector';
+
+ this.__saturation_field = document.createElement('div');
+ this.__saturation_field.className = 'saturation-field';
+
+ this.__field_knob = document.createElement('div');
+ this.__field_knob.className = 'field-knob';
+ this.__field_knob_border = '2px solid ';
+
+ this.__hue_knob = document.createElement('div');
+ this.__hue_knob.className = 'hue-knob';
+
+ this.__hue_field = document.createElement('div');
+ this.__hue_field.className = 'hue-field';
+
+ this.__input = document.createElement('input');
+ this.__input.type = 'text';
+ this.__input_textShadow = '0 1px 1px ';
+
+ dom.bind(this.__input, 'keydown', function(e) {
+ if (e.keyCode === 13) { // on enter
+ onBlur.call(this);
+ }
+ });
+
+ dom.bind(this.__input, 'blur', onBlur);
+
+ dom.bind(this.__selector, 'mousedown', function(e) {
+
+ dom
+ .addClass(this, 'drag')
+ .bind(window, 'mouseup', function(e) {
+ dom.removeClass(_this.__selector, 'drag');
+ });
+
+ });
+
+ var value_field = document.createElement('div');
+
+ common.extend(this.__selector.style, {
+ width: '122px',
+ height: '102px',
+ padding: '3px',
+ backgroundColor: '#222',
+ boxShadow: '0px 1px 3px rgba(0,0,0,0.3)'
+ });
+
+ common.extend(this.__field_knob.style, {
+ position: 'absolute',
+ width: '12px',
+ height: '12px',
+ border: this.__field_knob_border + (this.__color.v < .5 ? '#fff' : '#000'),
+ boxShadow: '0px 1px 3px rgba(0,0,0,0.5)',
+ borderRadius: '12px',
+ zIndex: 1
+ });
+
+ common.extend(this.__hue_knob.style, {
+ position: 'absolute',
+ width: '15px',
+ height: '2px',
+ borderRight: '4px solid #fff',
+ zIndex: 1
+ });
+
+ common.extend(this.__saturation_field.style, {
+ width: '100px',
+ height: '100px',
+ border: '1px solid #555',
+ marginRight: '3px',
+ display: 'inline-block',
+ cursor: 'pointer'
+ });
+
+ common.extend(value_field.style, {
+ width: '100%',
+ height: '100%',
+ background: 'none'
+ });
+
+ linearGradient(value_field, 'top', 'rgba(0,0,0,0)', '#000');
+
+ common.extend(this.__hue_field.style, {
+ width: '15px',
+ height: '100px',
+ display: 'inline-block',
+ border: '1px solid #555',
+ cursor: 'ns-resize'
+ });
+
+ hueGradient(this.__hue_field);
+
+ common.extend(this.__input.style, {
+ outline: 'none',
+ // width: '120px',
+ textAlign: 'center',
+ // padding: '4px',
+ // marginBottom: '6px',
+ color: '#fff',
+ border: 0,
+ fontWeight: 'bold',
+ textShadow: this.__input_textShadow + 'rgba(0,0,0,0.7)'
+ });
+
+ dom.bind(this.__saturation_field, 'mousedown', fieldDown);
+ dom.bind(this.__field_knob, 'mousedown', fieldDown);
+
+ dom.bind(this.__hue_field, 'mousedown', function(e) {
+ setH(e);
+ dom.bind(window, 'mousemove', setH);
+ dom.bind(window, 'mouseup', unbindH);
+ });
+
+ function fieldDown(e) {
+ setSV(e);
+ // document.body.style.cursor = 'none';
+ dom.bind(window, 'mousemove', setSV);
+ dom.bind(window, 'mouseup', unbindSV);
+ }
+
+ function unbindSV() {
+ dom.unbind(window, 'mousemove', setSV);
+ dom.unbind(window, 'mouseup', unbindSV);
+ // document.body.style.cursor = 'default';
+ }
+
+ function onBlur() {
+ var i = interpret(this.value);
+ if (i !== false) {
+ _this.__color.__state = i;
+ _this.setValue(_this.__color.toOriginal());
+ } else {
+ this.value = _this.__color.toString();
+ }
+ }
+
+ function unbindH() {
+ dom.unbind(window, 'mousemove', setH);
+ dom.unbind(window, 'mouseup', unbindH);
+ }
+
+ this.__saturation_field.appendChild(value_field);
+ this.__selector.appendChild(this.__field_knob);
+ this.__selector.appendChild(this.__saturation_field);
+ this.__selector.appendChild(this.__hue_field);
+ this.__hue_field.appendChild(this.__hue_knob);
+
+ this.domElement.appendChild(this.__input);
+ this.domElement.appendChild(this.__selector);
+
+ this.updateDisplay();
+
+ function setSV(e) {
+
+ e.preventDefault();
+
+ var w = dom.getWidth(_this.__saturation_field);
+ var o = dom.getOffset(_this.__saturation_field);
+ var s = (e.clientX - o.left + document.body.scrollLeft) / w;
+ var v = 1 - (e.clientY - o.top + document.body.scrollTop) / w;
+
+ if (v > 1) v = 1;
+ else if (v < 0) v = 0;
+
+ if (s > 1) s = 1;
+ else if (s < 0) s = 0;
+
+ _this.__color.v = v;
+ _this.__color.s = s;
+
+ _this.setValue(_this.__color.toOriginal());
+
+
+ return false;
+
+ }
+
+ function setH(e) {
+
+ e.preventDefault();
+
+ var s = dom.getHeight(_this.__hue_field);
+ var o = dom.getOffset(_this.__hue_field);
+ var h = 1 - (e.clientY - o.top + document.body.scrollTop) / s;
+
+ if (h > 1) h = 1;
+ else if (h < 0) h = 0;
+
+ _this.__color.h = h * 360;
+
+ _this.setValue(_this.__color.toOriginal());
+
+ return false;
+
+ }
+
+};
+
+ColorController.superclass = Controller;
+
+common.extend(
+
+ ColorController.prototype,
+ Controller.prototype,
+
+ {
+
+ updateDisplay: function() {
+
+ var i = interpret(this.getValue());
+
+ if (i !== false) {
+
+ var mismatch = false;
+
+ // Check for mismatch on the interpreted value.
+
+ common.each(Color.COMPONENTS, function(component) {
+ if (!common.isUndefined(i[component]) &&
+ !common.isUndefined(this.__color.__state[component]) &&
+ i[component] !== this.__color.__state[component]) {
+ mismatch = true;
+ return {}; // break
+ }
+ }, this);
+
+ // If nothing diverges, we keep our previous values
+ // for statefulness, otherwise we recalculate fresh
+ if (mismatch) {
+ common.extend(this.__color.__state, i);
+ }
+
+ }
+
+ common.extend(this.__temp.__state, this.__color.__state);
+
+ this.__temp.a = 1;
+
+ var flip = (this.__color.v < .5 || this.__color.s > .5) ? 255 : 0;
+ var _flip = 255 - flip;
+
+ common.extend(this.__field_knob.style, {
+ marginLeft: 100 * this.__color.s - 7 + 'px',
+ marginTop: 100 * (1 - this.__color.v) - 7 + 'px',
+ backgroundColor: this.__temp.toString(),
+ border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')'
+ });
+
+ this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'
+
+ this.__temp.s = 1;
+ this.__temp.v = 1;
+
+ linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toString());
+
+ common.extend(this.__input.style, {
+ backgroundColor: this.__input.value = this.__color.toString(),
+ color: 'rgb(' + flip + ',' + flip + ',' + flip + ')',
+ textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)'
+ });
+
+ }
+
+ }
+
+);
+
+var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', ''];
+
+function linearGradient(elem, x, a, b) {
+ elem.style.background = '';
+ common.each(vendors, function(vendor) {
+ elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); ';
+ });
+}
+
+function hueGradient(elem) {
+ elem.style.background = '';
+ elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'
+ elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'
+ elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'
+ elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'
+ elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'
+}
+
+},{"../color/Color.js":1,"../color/interpret.js":2,"../dom/dom.js":16,"../utils/common.js":18,"./Controller.js":7}],7:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var common = require('../utils/common.js');
+module.exports = Controller;
+
+/**
+ * @class An "abstract" class that represents a given property of an object.
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ *
+ * @member dat.controllers
+ */
+function Controller(object, property) {
+
+ this.initialValue = object[property];
+
+ /**
+ * Those who extend this class will put their DOM elements in here.
+ * @type {DOMElement}
+ */
+ this.domElement = document.createElement('div');
+
+ /**
+ * The object to manipulate
+ * @type {Object}
+ */
+ this.object = object;
+
+ /**
+ * The name of the property to manipulate
+ * @type {String}
+ */
+ this.property = property;
+
+ /**
+ * The function to be called on change.
+ * @type {Function}
+ * @ignore
+ */
+ this.__onChange = undefined;
+
+ /**
+ * The function to be called on finishing change.
+ * @type {Function}
+ * @ignore
+ */
+ this.__onFinishChange = undefined;
+
+}
+
+common.extend(
+
+ Controller.prototype,
+
+ /** @lends dat.controllers.Controller.prototype */
+ {
+
+ /**
+ * Specify that a function fire every time someone changes the value with
+ * this Controller.
+ *
+ * @param {Function} fnc This function will be called whenever the value
+ * is modified via this Controller.
+ * @returns {dat.controllers.Controller} this
+ */
+ onChange: function(fnc) {
+ this.__onChange = fnc;
+ return this;
+ },
+
+ /**
+ * Specify that a function fire every time someone "finishes" changing
+ * the value wih this Controller. Useful for values that change
+ * incrementally like numbers or strings.
+ *
+ * @param {Function} fnc This function will be called whenever
+ * someone "finishes" changing the value via this Controller.
+ * @returns {dat.controllers.Controller} this
+ */
+ onFinishChange: function(fnc) {
+ this.__onFinishChange = fnc;
+ return this;
+ },
+
+ /**
+ * Change the value of object[property]
+ *
+ * @param {Object} newValue The new value of object[property]
+ */
+ setValue: function(newValue) {
+ this.object[this.property] = newValue;
+ if (this.__onChange) {
+ this.__onChange.call(this, newValue);
+ }
+ this.updateDisplay();
+ return this;
+ },
+
+ /**
+ * Gets the value of object[property]
+ *
+ * @returns {Object} The current value of object[property]
+ */
+ getValue: function() {
+ return this.object[this.property];
+ },
+
+ /**
+ * Refreshes the visual display of a Controller in order to keep sync
+ * with the object's current value.
+ * @returns {dat.controllers.Controller} this
+ */
+ updateDisplay: function() {
+ return this;
+ },
+
+ /**
+ * @returns {Boolean} true if the value has deviated from initialValue
+ */
+ isModified: function() {
+ return this.initialValue !== this.getValue();
+ }
+
+ }
+
+);
+
+},{"../utils/common.js":18}],8:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var Controller = require('./Controller.js');
+var common = require('../utils/common.js');
+var dom = require('../dom/dom.js');
+
+module.exports = FunctionController;
+
+/**
+ * @class Provides a GUI interface to fire a specified method, a property of an object.
+ *
+ * @extends dat.controllers.Controller
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ *
+ * @member dat.controllers
+ */
+function FunctionController(object, property, text) {
+
+ FunctionController.superclass.call(this, object, property);
+
+ var _this = this;
+
+ this.__button = document.createElement('div');
+ this.__button.innerHTML = text === undefined ? 'Fire' : text;
+ dom.bind(this.__button, 'click', function(e) {
+ e.preventDefault();
+ _this.fire();
+ return false;
+ });
+
+ dom.addClass(this.__button, 'button');
+
+ this.domElement.appendChild(this.__button);
+
+}
+
+FunctionController.superclass = Controller;
+
+common.extend(
+
+ FunctionController.prototype,
+ Controller.prototype, {
+
+ fire: function() {
+ if (this.__onChange) {
+ this.__onChange.call(this);
+ }
+ this.getValue().call(this.object);
+ if (this.__onFinishChange) {
+ this.__onFinishChange.call(this, this.getValue());
+ }
+ }
+ }
+
+);
+
+},{"../dom/dom.js":16,"../utils/common.js":18,"./Controller.js":7}],9:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var Controller = require('./Controller.js');
+var common = require('../utils/common.js');
+module.exports = NumberController;
+
+/**
+ * @class Represents a given property of an object that is a number.
+ *
+ * @extends dat.controllers.Controller
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ * @param {Object} [params] Optional parameters
+ * @param {Number} [params.min] Minimum allowed value
+ * @param {Number} [params.max] Maximum allowed value
+ * @param {Number} [params.step] Increment by which to change value
+ *
+ * @member dat.controllers
+ */
+function NumberController(object, property, params) {
+
+ NumberController.superclass.call(this, object, property);
+
+ params = params || {};
+
+ this.__min = params.min;
+ this.__max = params.max;
+ this.__step = params.step;
+
+ if (common.isUndefined(this.__step)) {
+
+ if (this.initialValue == 0) {
+ this.__impliedStep = 1; // What are we, psychics?
+ } else {
+ // Hey Doug, check this out.
+ this.__impliedStep = Math.pow(10, Math.floor(Math.log(this.initialValue) / Math.LN10)) / 10;
+ }
+
+ } else {
+
+ this.__impliedStep = this.__step;
+
+ }
+
+ this.__precision = numDecimals(this.__impliedStep);
+
+
+}
+
+NumberController.superclass = Controller;
+
+common.extend(
+
+ NumberController.prototype,
+ Controller.prototype,
+
+ /** @lends dat.controllers.NumberController.prototype */
+ {
+
+ setValue: function(v) {
+
+ if (this.__min !== undefined && v < this.__min) {
+ v = this.__min;
+ } else if (this.__max !== undefined && v > this.__max) {
+ v = this.__max;
+ }
+
+ if (this.__step !== undefined && v % this.__step != 0) {
+ v = Math.round(v / this.__step) * this.__step;
+ }
+
+ return NumberController.superclass.prototype.setValue.call(this, v);
+
+ },
+
+ /**
+ * Specify a minimum value for object[property]
.
+ *
+ * @param {Number} minValue The minimum value for
+ * object[property]
+ * @returns {dat.controllers.NumberController} this
+ */
+ min: function(v) {
+ this.__min = v;
+ return this;
+ },
+
+ /**
+ * Specify a maximum value for object[property]
.
+ *
+ * @param {Number} maxValue The maximum value for
+ * object[property]
+ * @returns {dat.controllers.NumberController} this
+ */
+ max: function(v) {
+ this.__max = v;
+ return this;
+ },
+
+ /**
+ * Specify a step value that dat.controllers.NumberController
+ * increments by.
+ *
+ * @param {Number} stepValue The step value for
+ * dat.controllers.NumberController
+ * @default if minimum and maximum specified increment is 1% of the
+ * difference otherwise stepValue is 1
+ * @returns {dat.controllers.NumberController} this
+ */
+ step: function(v) {
+ this.__step = v;
+ this.__impliedStep = v;
+ this.__precision = numDecimals(v);
+ return this;
+ }
+
+ }
+
+);
+
+function numDecimals(x) {
+ x = x.toString();
+ if (x.indexOf('.') > -1) {
+ return x.length - x.indexOf('.') - 1;
+ } else {
+ return 0;
+ }
+}
+
+},{"../utils/common.js":18,"./Controller.js":7}],10:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var NumberController = require('./NumberController.js');
+var common = require('../utils/common.js');
+var dom = require('../dom/dom.js');
+
+module.exports = NumberControllerBox;
+
+/**
+ * @class Represents a given property of an object that is a number and
+ * provides an input element with which to manipulate it.
+ *
+ * @extends dat.controllers.Controller
+ * @extends dat.controllers.NumberController
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ * @param {Object} [params] Optional parameters
+ * @param {Number} [params.min] Minimum allowed value
+ * @param {Number} [params.max] Maximum allowed value
+ * @param {Number} [params.step] Increment by which to change value
+ *
+ * @member dat.controllers
+ */
+function NumberControllerBox(object, property, params) {
+
+ this.__truncationSuspended = false;
+
+ NumberControllerBox.superclass.call(this, object, property, params);
+
+ var _this = this;
+
+ /**
+ * {Number} Previous mouse y position
+ * @ignore
+ */
+ var prev_y;
+
+ this.__input = document.createElement('input');
+ this.__input.setAttribute('type', 'text');
+
+ // Makes it so manually specified values are not truncated.
+
+ dom.bind(this.__input, 'change', onChange);
+ dom.bind(this.__input, 'blur', onBlur);
+ dom.bind(this.__input, 'mousedown', onMouseDown);
+ dom.bind(this.__input, 'keydown', function(e) {
+
+ // When pressing entire, you can be as precise as you want.
+ if (e.keyCode === 13) {
+ _this.__truncationSuspended = true;
+ this.blur();
+ _this.__truncationSuspended = false;
+ }
+
+ });
+
+ function onChange() {
+ var attempted = parseFloat(_this.__input.value);
+ if (!common.isNaN(attempted)) _this.setValue(attempted);
+ }
+
+ function onBlur() {
+ onChange();
+ if (_this.__onFinishChange) {
+ _this.__onFinishChange.call(_this, _this.getValue());
+ }
+ }
+
+ function onMouseDown(e) {
+ dom.bind(window, 'mousemove', onMouseDrag);
+ dom.bind(window, 'mouseup', onMouseUp);
+ prev_y = e.clientY;
+ }
+
+ function onMouseDrag(e) {
+
+ var diff = prev_y - e.clientY;
+ _this.setValue(_this.getValue() + diff * _this.__impliedStep);
+
+ prev_y = e.clientY;
+
+ }
+
+ function onMouseUp() {
+ dom.unbind(window, 'mousemove', onMouseDrag);
+ dom.unbind(window, 'mouseup', onMouseUp);
+ }
+
+ this.updateDisplay();
+
+ this.domElement.appendChild(this.__input);
+
+}
+
+NumberControllerBox.superclass = NumberController;
+
+common.extend(
+
+ NumberControllerBox.prototype,
+ NumberController.prototype,
+
+ {
+
+ updateDisplay: function() {
+
+ this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision);
+ return NumberControllerBox.superclass.prototype.updateDisplay.call(this);
+ }
+
+ }
+
+);
+
+function roundToDecimal(value, decimals) {
+ var tenTo = Math.pow(10, decimals);
+ return Math.round(value * tenTo) / tenTo;
+}
+
+},{"../dom/dom.js":16,"../utils/common.js":18,"./NumberController.js":9}],11:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var NumberController = require('./NumberController.js');
+var common = require('../utils/common.js');
+var dom = require('../dom/dom.js');
+var css = require('../utils/css.js');
+
+var styleSheet = "/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}";
+module.exports = NumberControllerSlider;
+
+/**
+ * @class Represents a given property of an object that is a number, contains
+ * a minimum and maximum, and provides a slider element with which to
+ * manipulate it. It should be noted that the slider element is made up of
+ * <div>
tags, not the html5
+ * <slider>
element.
+ *
+ * @extends dat.controllers.Controller
+ * @extends dat.controllers.NumberController
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ * @param {Number} minValue Minimum allowed value
+ * @param {Number} maxValue Maximum allowed value
+ * @param {Number} stepValue Increment by which to change value
+ *
+ * @member dat.controllers
+ */
+function NumberControllerSlider(object, property, min, max, step) {
+
+ NumberControllerSlider.superclass.call(this, object, property, {
+ min: min,
+ max: max,
+ step: step
+ });
+
+ var _this = this;
+
+ this.__background = document.createElement('div');
+ this.__foreground = document.createElement('div');
+
+
+
+ dom.bind(this.__background, 'mousedown', onMouseDown);
+
+ dom.addClass(this.__background, 'slider');
+ dom.addClass(this.__foreground, 'slider-fg');
+
+ function onMouseDown(e) {
+
+ dom.bind(window, 'mousemove', onMouseDrag);
+ dom.bind(window, 'mouseup', onMouseUp);
+
+ onMouseDrag(e);
+ }
+
+ function onMouseDrag(e) {
+
+ e.preventDefault();
+
+ var offset = dom.getOffset(_this.__background);
+ var width = dom.getWidth(_this.__background);
+
+ _this.setValue(
+ map(e.clientX, offset.left, offset.left + width, _this.__min, _this.__max)
+ );
+
+ return false;
+
+ }
+
+ function onMouseUp() {
+ dom.unbind(window, 'mousemove', onMouseDrag);
+ dom.unbind(window, 'mouseup', onMouseUp);
+ if (_this.__onFinishChange) {
+ _this.__onFinishChange.call(_this, _this.getValue());
+ }
+ }
+
+ this.updateDisplay();
+
+ this.__background.appendChild(this.__foreground);
+ this.domElement.appendChild(this.__background);
+
+}
+
+NumberControllerSlider.superclass = NumberController;
+
+/**
+ * Injects default stylesheet for slider elements.
+ */
+NumberControllerSlider.useDefaultStyles = function() {
+ css.inject(styleSheet);
+};
+
+common.extend(
+
+ NumberControllerSlider.prototype,
+ NumberController.prototype,
+
+ {
+
+ updateDisplay: function() {
+ var pct = (this.getValue() - this.__min) / (this.__max - this.__min);
+ this.__foreground.style.width = pct * 100 + '%';
+ return NumberControllerSlider.superclass.prototype.updateDisplay.call(this);
+ }
+
+ }
+
+
+
+);
+
+function map(v, i1, i2, o1, o2) {
+ return o1 + (o2 - o1) * ((v - i1) / (i2 - i1));
+}
+
+},{"../dom/dom.js":16,"../utils/common.js":18,"../utils/css.js":19,"./NumberController.js":9}],12:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var Controller = require('./Controller.js');
+var dom = require('../dom/dom.js');
+var common = require('../utils/common.js');
+
+module.exports = OptionController;
+
+/**
+ * @class Provides a select input to alter the property of an object, using a
+ * list of accepted values.
+ *
+ * @extends dat.controllers.Controller
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ * @param {Object|string[]} options A map of labels to acceptable values, or
+ * a list of acceptable string values.
+ *
+ * @member dat.controllers
+ */
+function OptionController(object, property, options) {
+
+ OptionController.superclass.call(this, object, property);
+
+ var _this = this;
+
+ /**
+ * The drop down menu
+ * @ignore
+ */
+ this.__select = document.createElement('select');
+
+ if (common.isArray(options)) {
+ var map = {};
+ common.each(options, function(element) {
+ map[element] = element;
+ });
+ options = map;
+ }
+
+ common.each(options, function(value, key) {
+
+ var opt = document.createElement('option');
+ opt.innerHTML = key;
+ opt.setAttribute('value', value);
+ _this.__select.appendChild(opt);
+
+ });
+
+ // Acknowledge original value
+ this.updateDisplay();
+
+ dom.bind(this.__select, 'change', function() {
+ var desiredValue = this.options[this.selectedIndex].value;
+ _this.setValue(desiredValue);
+ });
+
+ this.domElement.appendChild(this.__select);
+
+}
+
+OptionController.superclass = Controller;
+
+common.extend(
+
+ OptionController.prototype,
+ Controller.prototype,
+
+ {
+
+ setValue: function(v) {
+ var toReturn = OptionController.superclass.prototype.setValue.call(this, v);
+ if (this.__onFinishChange) {
+ this.__onFinishChange.call(this, this.getValue());
+ }
+ return toReturn;
+ },
+
+ updateDisplay: function() {
+ this.__select.value = this.getValue();
+ return OptionController.superclass.prototype.updateDisplay.call(this);
+ }
+
+ }
+
+);
+
+},{"../dom/dom.js":16,"../utils/common.js":18,"./Controller.js":7}],13:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var Controller = require('./Controller.js');
+var dom = require('../dom/dom.js');
+var common = require('../utils/common.js');
+
+module.exports = StringController;
+
+/**
+ * @class Provides a text input to alter the string property of an object.
+ *
+ * @extends dat.controllers.Controller
+ *
+ * @param {Object} object The object to be manipulated
+ * @param {string} property The name of the property to be manipulated
+ *
+ * @member dat.controllers
+ */
+function StringController(object, property) {
+
+ StringController.superclass.call(this, object, property);
+
+ var _this = this;
+
+ this.__input = document.createElement('input');
+ this.__input.setAttribute('type', 'text');
+
+ dom.bind(this.__input, 'keyup', onChange);
+ dom.bind(this.__input, 'change', onChange);
+ dom.bind(this.__input, 'blur', onBlur);
+ dom.bind(this.__input, 'keydown', function(e) {
+ if (e.keyCode === 13) {
+ this.blur();
+ }
+ });
+
+
+ function onChange() {
+ _this.setValue(_this.__input.value);
+ }
+
+ function onBlur() {
+ if (_this.__onFinishChange) {
+ _this.__onFinishChange.call(_this, _this.getValue());
+ }
+ }
+
+ this.updateDisplay();
+
+ this.domElement.appendChild(this.__input);
+
+};
+
+StringController.superclass = Controller;
+
+common.extend(
+
+ StringController.prototype,
+ Controller.prototype,
+
+ {
+
+ updateDisplay: function() {
+ // Stops the caret from moving on account of:
+ // keyup -> setValue -> updateDisplay
+ if (!dom.isActive(this.__input)) {
+ this.__input.value = this.getValue();
+ }
+ return StringController.superclass.prototype.updateDisplay.call(this);
+ }
+
+ }
+
+);
+
+},{"../dom/dom.js":16,"../utils/common.js":18,"./Controller.js":7}],14:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+var OptionController = require('./OptionController.js');
+var NumberControllerBox = require('./NumberControllerBox.js');
+var NumberControllerSlider = require('./NumberControllerSlider.js');
+var StringController = require('./StringController.js');
+var FunctionController = require('./FunctionController.js');
+var BooleanController = require('./BooleanController.js');
+var common = require('../utils/common.js');
+
+module.exports = factory;
+
+function factory(object, property) {
+
+ var initialValue = object[property];
+
+ // Providing options?
+ if (common.isArray(arguments[2]) || common.isObject(arguments[2])) {
+ return new OptionController(object, property, arguments[2]);
+ }
+
+ // Providing a map?
+
+ if (common.isNumber(initialValue)) {
+
+ if (common.isNumber(arguments[2]) && common.isNumber(arguments[3])) {
+
+ // Has min and max.
+ return new NumberControllerSlider(object, property, arguments[2], arguments[3]);
+
+ } else {
+
+ return new NumberControllerBox(object, property, {
+ min: arguments[2],
+ max: arguments[3]
+ });
+
+ }
+
+ }
+
+ if (common.isString(initialValue)) {
+ return new StringController(object, property);
+ }
+
+ if (common.isFunction(initialValue)) {
+ return new FunctionController(object, property, '');
+ }
+
+ if (common.isBoolean(initialValue)) {
+ return new BooleanController(object, property);
+ }
+
+}
+
+},{"../utils/common.js":18,"./BooleanController.js":5,"./FunctionController.js":8,"./NumberControllerBox.js":10,"./NumberControllerSlider.js":11,"./OptionController.js":12,"./StringController.js":13}],15:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var common = require('../utils/common.js');
+var dom = require('./dom.js');
+
+module.exports = CenteredDiv;
+
+function CenteredDiv() {
+
+ this.backgroundElement = document.createElement('div');
+ common.extend(this.backgroundElement.style, {
+ backgroundColor: 'rgba(0,0,0,0.8)',
+ top: 0,
+ left: 0,
+ display: 'none',
+ zIndex: '1000',
+ opacity: 0,
+ WebkitTransition: 'opacity 0.2s linear',
+ transition: 'opacity 0.2s linear'
+ });
+
+ dom.makeFullscreen(this.backgroundElement);
+ this.backgroundElement.style.position = 'fixed';
+
+ this.domElement = document.createElement('div');
+ common.extend(this.domElement.style, {
+ position: 'fixed',
+ display: 'none',
+ zIndex: '1001',
+ opacity: 0,
+ WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear',
+ transition: 'transform 0.2s ease-out, opacity 0.2s linear'
+ });
+
+
+ document.body.appendChild(this.backgroundElement);
+ document.body.appendChild(this.domElement);
+
+ var _this = this;
+ dom.bind(this.backgroundElement, 'click', function() {
+ _this.hide();
+ });
+
+
+};
+
+CenteredDiv.prototype.show = function() {
+
+ var _this = this;
+
+ this.backgroundElement.style.display = 'block';
+
+ this.domElement.style.display = 'block';
+ this.domElement.style.opacity = 0;
+ // this.domElement.style.top = '52%';
+ this.domElement.style.webkitTransform = 'scale(1.1)';
+
+ this.layout();
+
+ common.defer(function() {
+ _this.backgroundElement.style.opacity = 1;
+ _this.domElement.style.opacity = 1;
+ _this.domElement.style.webkitTransform = 'scale(1)';
+ });
+
+};
+
+CenteredDiv.prototype.hide = function() {
+
+ var _this = this;
+
+ var hide = function() {
+
+ _this.domElement.style.display = 'none';
+ _this.backgroundElement.style.display = 'none';
+
+ dom.unbind(_this.domElement, 'webkitTransitionEnd', hide);
+ dom.unbind(_this.domElement, 'transitionend', hide);
+ dom.unbind(_this.domElement, 'oTransitionEnd', hide);
+
+ };
+
+ dom.bind(this.domElement, 'webkitTransitionEnd', hide);
+ dom.bind(this.domElement, 'transitionend', hide);
+ dom.bind(this.domElement, 'oTransitionEnd', hide);
+
+ this.backgroundElement.style.opacity = 0;
+ // this.domElement.style.top = '48%';
+ this.domElement.style.opacity = 0;
+ this.domElement.style.webkitTransform = 'scale(1.1)';
+
+};
+
+CenteredDiv.prototype.layout = function() {
+ this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px';
+ this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px';
+};
+
+function lockScroll(e) {
+ console.log(e);
+}
+
+},{"../utils/common.js":18,"./dom.js":16}],16:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var common = require('../utils/common.js');
+
+var EVENT_MAP = {
+ 'HTMLEvents': ['change'],
+ 'MouseEvents': ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'],
+ 'KeyboardEvents': ['keydown']
+};
+
+var EVENT_MAP_INV = {};
+common.each(EVENT_MAP, function(v, k) {
+ common.each(v, function(e) {
+ EVENT_MAP_INV[e] = k;
+ });
+});
+
+var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/;
+
+function cssValueToPixels(val) {
+
+ if (val === '0' || common.isUndefined(val)) return 0;
+
+ var match = val.match(CSS_VALUE_PIXELS);
+
+ if (!common.isNull(match)) {
+ return parseFloat(match[1]);
+ }
+
+ // TODO ...ems? %?
+
+ return 0;
+
+}
+
+/**
+ * @namespace
+ * @member dat.dom
+ */
+var dom = {
+
+ /**
+ *
+ * @param elem
+ * @param selectable
+ */
+ makeSelectable: function(elem, selectable) {
+
+ if (elem === undefined || elem.style === undefined) return;
+
+ elem.onselectstart = selectable ? function() {
+ return false;
+ } : function() {};
+
+ elem.style.MozUserSelect = selectable ? 'auto' : 'none';
+ elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none';
+ elem.unselectable = selectable ? 'on' : 'off';
+
+ },
+
+ /**
+ *
+ * @param elem
+ * @param horizontal
+ * @param vertical
+ */
+ makeFullscreen: function(elem, horizontal, vertical) {
+
+ if (common.isUndefined(horizontal)) horizontal = true;
+ if (common.isUndefined(vertical)) vertical = true;
+
+ elem.style.position = 'absolute';
+
+ if (horizontal) {
+ elem.style.left = 0;
+ elem.style.right = 0;
+ }
+ if (vertical) {
+ elem.style.top = 0;
+ elem.style.bottom = 0;
+ }
+
+ },
+
+ /**
+ *
+ * @param elem
+ * @param eventType
+ * @param params
+ */
+ fakeEvent: function(elem, eventType, params, aux) {
+ params = params || {};
+ var className = EVENT_MAP_INV[eventType];
+ if (!className) {
+ throw new Error('Event type ' + eventType + ' not supported.');
+ }
+ var evt = document.createEvent(className);
+ switch (className) {
+ case 'MouseEvents':
+ var clientX = params.x || params.clientX || 0;
+ var clientY = params.y || params.clientY || 0;
+ evt.initMouseEvent(eventType, params.bubbles || false,
+ params.cancelable || true, window, params.clickCount || 1,
+ 0, //screen X
+ 0, //screen Y
+ clientX, //client X
+ clientY, //client Y
+ false, false, false, false, 0, null);
+ break;
+ case 'KeyboardEvents':
+ var init = evt.initKeyboardEvent || evt.initKeyEvent; // webkit || moz
+ common.defaults(params, {
+ cancelable: true,
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false,
+ keyCode: undefined,
+ charCode: undefined
+ });
+ init(eventType, params.bubbles || false,
+ params.cancelable, window,
+ params.ctrlKey, params.altKey,
+ params.shiftKey, params.metaKey,
+ params.keyCode, params.charCode);
+ break;
+ default:
+ evt.initEvent(eventType, params.bubbles || false,
+ params.cancelable || true);
+ break;
+ }
+ common.defaults(evt, aux);
+ elem.dispatchEvent(evt);
+ },
+
+ /**
+ *
+ * @param elem
+ * @param event
+ * @param func
+ * @param bool
+ */
+ bind: function(elem, event, func, bool) {
+ bool = bool || false;
+ if (elem.addEventListener)
+ elem.addEventListener(event, func, bool);
+ else if (elem.attachEvent)
+ elem.attachEvent('on' + event, func);
+ return dom;
+ },
+
+ /**
+ *
+ * @param elem
+ * @param event
+ * @param func
+ * @param bool
+ */
+ unbind: function(elem, event, func, bool) {
+ bool = bool || false;
+ if (elem.removeEventListener)
+ elem.removeEventListener(event, func, bool);
+ else if (elem.detachEvent)
+ elem.detachEvent('on' + event, func);
+ return dom;
+ },
+
+ /**
+ *
+ * @param elem
+ * @param className
+ */
+ addClass: function(elem, className) {
+ if (elem.className === undefined) {
+ elem.className = className;
+ } else if (elem.className !== className) {
+ var classes = elem.className.split(/ +/);
+ if (classes.indexOf(className) == -1) {
+ classes.push(className);
+ elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, '');
+ }
+ }
+ return dom;
+ },
+
+ /**
+ *
+ * @param elem
+ * @param className
+ */
+ removeClass: function(elem, className) {
+ if (className) {
+ if (elem.className === undefined) {
+ // elem.className = className;
+ } else if (elem.className === className) {
+ elem.removeAttribute('class');
+ } else {
+ var classes = elem.className.split(/ +/);
+ var index = classes.indexOf(className);
+ if (index != -1) {
+ classes.splice(index, 1);
+ elem.className = classes.join(' ');
+ }
+ }
+ } else {
+ elem.className = undefined;
+ }
+ return dom;
+ },
+
+ hasClass: function(elem, className) {
+ return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false;
+ },
+
+ /**
+ *
+ * @param elem
+ */
+ getWidth: function(elem) {
+
+ var style = getComputedStyle(elem);
+
+ return cssValueToPixels(style['border-left-width']) +
+ cssValueToPixels(style['border-right-width']) +
+ cssValueToPixels(style['padding-left']) +
+ cssValueToPixels(style['padding-right']) +
+ cssValueToPixels(style['width']);
+ },
+
+ /**
+ *
+ * @param elem
+ */
+ getHeight: function(elem) {
+
+ var style = getComputedStyle(elem);
+
+ return cssValueToPixels(style['border-top-width']) +
+ cssValueToPixels(style['border-bottom-width']) +
+ cssValueToPixels(style['padding-top']) +
+ cssValueToPixels(style['padding-bottom']) +
+ cssValueToPixels(style['height']);
+ },
+
+ /**
+ *
+ * @param elem
+ */
+ getOffset: function(elem) {
+ var offset = {
+ left: 0,
+ top: 0
+ };
+ if (elem.offsetParent) {
+ do {
+ offset.left += elem.offsetLeft;
+ offset.top += elem.offsetTop;
+ } while (elem = elem.offsetParent);
+ }
+ return offset;
+ },
+
+ // http://stackoverflow.com/posts/2684561/revisions
+ /**
+ *
+ * @param elem
+ */
+ isActive: function(elem) {
+ return elem === document.activeElement && (elem.type || elem.href);
+ }
+
+};
+
+module.exports = dom;
+
+},{"../utils/common.js":18}],17:[function(require,module,exports){
+/**
+ * dat-gui JavaScript Controller Library
+ * http://code.google.com/p/dat-gui
+ *
+ * Copyright 2011 Data Arts Team, Google Creative Lab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+var css = require('../utils/css.js');
+
+var saveDialogueContents = "GUI
's constructor:\n\n \n\n localStorage
on exit.\n\n localStorage
will\n override those passed to dat.GUI
's constructor. This makes it\n easier to work incrementally, but localStorage
is fragile,\n and your friends may not see the same values you do.\n \n GUI
- * @type dat.gui.GUI
- */
- parent: {
- get: function() {
- return params.parent;
+ /**
+ * The parent GUI
+ * @type dat.gui.GUI
+ */
+ parent: {
+ get: function() {
+ return params.parent;
+ }
+ },
+
+ scrollable: {
+ get: function() {
+ return params.scrollable;
+ }
+ },
+
+ /**
+ * Handles GUI
's element placement for you
+ * @type Boolean
+ */
+ autoPlace: {
+ get: function() {
+ return params.autoPlace;
+ }
+ },
+
+ /**
+ * The identifier for a set of saved values
+ * @type String
+ */
+ preset: {
+
+ get: function() {
+ if (_this.parent) {
+ return _this.getRoot().preset;
+ } else {
+ return params.load.preset;
}
},
- scrollable: {
- get: function() {
- return params.scrollable;
+ set: function(v) {
+ if (_this.parent) {
+ _this.getRoot().preset = v;
+ } else {
+ params.load.preset = v;
}
- },
-
- /**
- * Handles GUI
's element placement for you
- * @type Boolean
- */
- autoPlace: {
- get: function() {
- return params.autoPlace;
- }
- },
-
- /**
- * The identifier for a set of saved values
- * @type String
- */
- preset: {
-
- get: function() {
- if (_this.parent) {
- return _this.getRoot().preset;
- } else {
- return params.load.preset;
- }
- },
-
- set: function(v) {
- if (_this.parent) {
- _this.getRoot().preset = v;
- } else {
- params.load.preset = v;
- }
- setPresetSelectIndex(this);
- _this.revert();
- }
-
- },
-
- /**
- * The width of GUI
element
- * @type Number
- */
- width: {
- get: function() {
- return params.width;
- },
- set: function(v) {
- params.width = v;
- setWidth(_this, v);
- }
- },
-
- /**
- * The name of GUI
. Used for folders. i.e
- * a folder's name
- * @type String
- */
- name: {
- get: function() {
- return params.name;
- },
- set: function(v) {
- // TODO Check for collisions among sibling folders
- params.name = v;
- if (title_row_name) {
- title_row_name.innerHTML = params.name;
- }
- }
- },
-
- /**
- * Whether the GUI
is collapsed or not
- * @type Boolean
- */
- closed: {
- get: function() {
- return params.closed;
- },
- set: function(v) {
- params.closed = v;
- if (params.closed) {
- dom.addClass(_this.__ul, GUI.CLASS_CLOSED);
- } else {
- dom.removeClass(_this.__ul, GUI.CLASS_CLOSED);
- }
- // For browsers that aren't going to respect the CSS transition,
- // Lets just check our height against the window height right off
- // the bat.
- this.onResize();
-
- if (_this.__closeButton) {
- _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED;
- }
- }
- },
-
- /**
- * Contains all presets
- * @type Object
- */
- load: {
- get: function() {
- return params.load;
- }
- },
-
- /**
- * Determines whether or not to use localStorage as the means for
- * remember
ing
- * @type Boolean
- */
- useLocalStorage: {
-
- get: function() {
- return use_local_storage;
- },
- set: function(bool) {
- if (SUPPORTS_LOCAL_STORAGE) {
- use_local_storage = bool;
- if (bool) {
- dom.bind(window, 'unload', saveToLocalStorage);
- } else {
- dom.unbind(window, 'unload', saveToLocalStorage);
- }
- localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool);
- }
- }
-
+ setPresetSelectIndex(this);
+ _this.revert();
}
- });
+ },
+
+ /**
+ * The width of GUI
element
+ * @type Number
+ */
+ width: {
+ get: function() {
+ return params.width;
+ },
+ set: function(v) {
+ params.width = v;
+ setWidth(_this, v);
+ }
+ },
+
+ /**
+ * The name of GUI
. Used for folders. i.e
+ * a folder's name
+ * @type String
+ */
+ name: {
+ get: function() {
+ return params.name;
+ },
+ set: function(v) {
+ // TODO Check for collisions among sibling folders
+ params.name = v;
+ if (title_row_name) {
+ title_row_name.innerHTML = params.name;
+ }
+ }
+ },
+
+ /**
+ * Whether the GUI
is collapsed or not
+ * @type Boolean
+ */
+ closed: {
+ get: function() {
+ return params.closed;
+ },
+ set: function(v) {
+ params.closed = v;
+ if (params.closed) {
+ dom.addClass(_this.__ul, GUI.CLASS_CLOSED);
+ } else {
+ dom.removeClass(_this.__ul, GUI.CLASS_CLOSED);
+ }
+ // For browsers that aren't going to respect the CSS transition,
+ // Lets just check our height against the window height right off
+ // the bat.
+ this.onResize();
+
+ if (_this.__closeButton) {
+ _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED;
+ }
+ }
+ },
+
+ /**
+ * Contains all presets
+ * @type Object
+ */
+ load: {
+ get: function() {
+ return params.load;
+ }
+ },
+
+ /**
+ * Determines whether or not to use localStorage as the means for
+ * remember
ing
+ * @type Boolean
+ */
+ useLocalStorage: {
+
+ get: function() {
+ return use_local_storage;
+ },
+ set: function(bool) {
+ if (SUPPORTS_LOCAL_STORAGE) {
+ use_local_storage = bool;
+ if (bool) {
+ dom.bind(window, 'unload', saveToLocalStorage);
+ } else {
+ dom.unbind(window, 'unload', saveToLocalStorage);
+ }
+ localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool);
+ }
+ }
+
+ }
+
+ });
// Are we a root level GUI?
if (common.isUndefined(params.parent)) {
@@ -1920,10 +2766,18 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
}
- dom.bind(window, 'resize', function() { _this.onResize() });
- dom.bind(this.__ul, 'webkitTransitionEnd', function() { _this.onResize(); });
- dom.bind(this.__ul, 'transitionend', function() { _this.onResize() });
- dom.bind(this.__ul, 'oTransitionEnd', function() { _this.onResize() });
+ dom.bind(window, 'resize', function() {
+ _this.onResize()
+ });
+ dom.bind(this.__ul, 'webkitTransitionEnd', function() {
+ _this.onResize();
+ });
+ dom.bind(this.__ul, 'transitionend', function() {
+ _this.onResize()
+ });
+ dom.bind(this.__ul, 'oTransitionEnd', function() {
+ _this.onResize()
+ });
this.onResize();
@@ -1931,7 +2785,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
addResizeHandle(this);
}
- saveToLocalStorage = function () {
+ saveToLocalStorage = function() {
if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') {
localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject()));
}
@@ -1941,17 +2795,18 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
this.saveToLocalStorageIfPossible = saveToLocalStorage;
var root = _this.getRoot();
- function resetWidth() {
- var root = _this.getRoot();
- root.width += 1;
- common.defer(function() {
- root.width -= 1;
- });
- }
- if (!params.parent) {
- resetWidth();
- }
+ function resetWidth() {
+ var root = _this.getRoot();
+ root.width += 1;
+ common.defer(function() {
+ root.width -= 1;
+ });
+ }
+
+ if (!params.parent) {
+ resetWidth();
+ }
};
@@ -1980,7 +2835,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
dom.bind(window, 'keydown', function(e) {
if (document.activeElement.type !== 'text' &&
- (e.which === HIDE_KEY_CODE || e.keyCode == HIDE_KEY_CODE)) {
+ (e.which === HIDE_KEY_CODE || e.keyCode == HIDE_KEY_CODE)) {
GUI.toggleHide();
}
@@ -1988,307 +2843,308 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
common.extend(
- GUI.prototype,
+ GUI.prototype,
- /** @lends dat.gui.GUI */
- {
+ /** @lends dat.gui.GUI */
+ {
- /**
- * @param object
- * @param property
- * @returns {dat.controllers.Controller} The new controller that was added.
- * @instance
- */
- add: function(object, property) {
+ /**
+ * @param object
+ * @param property
+ * @returns {dat.controllers.Controller} The new controller that was added.
+ * @instance
+ */
+ add: function(object, property) {
- return add(
- this,
- object,
- property,
- {
- factoryArgs: Array.prototype.slice.call(arguments, 2)
- }
- );
-
- },
-
- /**
- * @param object
- * @param property
- * @returns {dat.controllers.ColorController} The new controller that was added.
- * @instance
- */
- addColor: function(object, property) {
-
- return add(
- this,
- object,
- property,
- {
- color: true
- }
- );
-
- },
-
- /**
- * @param controller
- * @instance
- */
- remove: function(controller) {
-
- // TODO listening?
- this.__ul.removeChild(controller.__li);
- this.__controllers.splice(this.__controllers.indexOf(controller), 1);
- var _this = this;
- common.defer(function() {
- _this.onResize();
- });
-
- },
-
- destroy: function() {
-
- if (this.autoPlace) {
- auto_place_container.removeChild(this.domElement);
+ return add(
+ this,
+ object,
+ property, {
+ factoryArgs: Array.prototype.slice.call(arguments, 2)
}
+ );
- },
+ },
- /**
- * @param name
- * @returns {dat.gui.GUI} The new folder.
- * @throws {Error} if this GUI already has a folder by the specified
- * name
- * @instance
- */
- addFolder: function(name) {
+ /**
+ * @param object
+ * @param property
+ * @returns {dat.controllers.ColorController} The new controller that was added.
+ * @instance
+ */
+ addColor: function(object, property) {
- // We have to prevent collisions on names in order to have a key
- // by which to remember saved values
- if (this.__folders[name] !== undefined) {
- throw new Error('You already have a folder in this GUI by the' +
- ' name "' + name + '"');
+ return add(
+ this,
+ object,
+ property, {
+ color: true
}
+ );
- var new_gui_params = { name: name, parent: this };
+ },
- // We need to pass down the autoPlace trait so that we can
- // attach event listeners to open/close folder actions to
- // ensure that a scrollbar appears if the window is too short.
- new_gui_params.autoPlace = this.autoPlace;
+ /**
+ * @param controller
+ * @instance
+ */
+ remove: function(controller) {
- // Do we have saved appearance data for this folder?
+ // TODO listening?
+ this.__ul.removeChild(controller.__li);
+ this.__controllers.splice(this.__controllers.indexOf(controller), 1);
+ var _this = this;
+ common.defer(function() {
+ _this.onResize();
+ });
- if (this.load && // Anything loaded?
- this.load.folders && // Was my parent a dead-end?
- this.load.folders[name]) { // Did daddy remember me?
+ },
- // Start me closed if I was closed
- new_gui_params.closed = this.load.folders[name].closed;
+ destroy: function() {
- // Pass down the loaded data
- new_gui_params.load = this.load.folders[name];
+ if (this.autoPlace) {
+ auto_place_container.removeChild(this.domElement);
+ }
- }
+ },
- var gui = new GUI(new_gui_params);
- this.__folders[name] = gui;
+ /**
+ * @param name
+ * @returns {dat.gui.GUI} The new folder.
+ * @throws {Error} if this GUI already has a folder by the specified
+ * name
+ * @instance
+ */
+ addFolder: function(name) {
- var li = addRow(this, gui.domElement);
- dom.addClass(li, 'folder');
- return gui;
+ // We have to prevent collisions on names in order to have a key
+ // by which to remember saved values
+ if (this.__folders[name] !== undefined) {
+ throw new Error('You already have a folder in this GUI by the' +
+ ' name "' + name + '"');
+ }
- },
+ var new_gui_params = {
+ name: name,
+ parent: this
+ };
- open: function() {
- this.closed = false;
- },
+ // We need to pass down the autoPlace trait so that we can
+ // attach event listeners to open/close folder actions to
+ // ensure that a scrollbar appears if the window is too short.
+ new_gui_params.autoPlace = this.autoPlace;
- close: function() {
- this.closed = true;
- },
+ // Do we have saved appearance data for this folder?
- onResize: function() {
+ if (this.load && // Anything loaded?
+ this.load.folders && // Was my parent a dead-end?
+ this.load.folders[name]) { // Did daddy remember me?
- var root = this.getRoot();
+ // Start me closed if I was closed
+ new_gui_params.closed = this.load.folders[name].closed;
- if (root.scrollable) {
-
- var top = dom.getOffset(root.__ul).top;
- var h = 0;
-
- common.each(root.__ul.childNodes, function(node) {
- if (! (root.autoPlace && node === root.__save_row))
- h += dom.getHeight(node);
- });
-
- if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) {
- dom.addClass(root.domElement, GUI.CLASS_TOO_TALL);
- root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px';
- } else {
- dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL);
- root.__ul.style.height = 'auto';
- }
-
- }
-
- if (root.__resize_handle) {
- common.defer(function() {
- root.__resize_handle.style.height = root.__ul.offsetHeight + 'px';
- });
- }
-
- if (root.__closeButton) {
- root.__closeButton.style.width = root.width + 'px';
- }
-
- },
-
- /**
- * Mark objects for saving. The order of these objects cannot change as
- * the GUI grows. When remembering new objects, append them to the end
- * of the list.
- *
- * @param {Object...} objects
- * @throws {Error} if not called on a top level GUI.
- * @instance
- */
- remember: function() {
-
- if (common.isUndefined(SAVE_DIALOGUE)) {
- SAVE_DIALOGUE = new CenteredDiv();
- SAVE_DIALOGUE.domElement.innerHTML = saveDialogueContents;
- }
-
- if (this.parent) {
- throw new Error("You can only call remember on a top level GUI.");
- }
-
- var _this = this;
-
- common.each(Array.prototype.slice.call(arguments), function(object) {
- if (_this.__rememberedObjects.length == 0) {
- addSaveMenu(_this);
- }
- if (_this.__rememberedObjects.indexOf(object) == -1) {
- _this.__rememberedObjects.push(object);
- }
- });
-
- if (this.autoPlace) {
- // Set save row width
- setWidth(this, this.width);
- }
-
- },
-
- /**
- * @returns {dat.gui.GUI} the topmost parent GUI of a nested GUI.
- * @instance
- */
- getRoot: function() {
- var gui = this;
- while (gui.parent) {
- gui = gui.parent;
- }
- return gui;
- },
-
- /**
- * @returns {Object} a JSON object representing the current state of
- * this GUI as well as its remembered properties.
- * @instance
- */
- getSaveObject: function() {
-
- var toReturn = this.load;
-
- toReturn.closed = this.closed;
-
- // Am I remembering any values?
- if (this.__rememberedObjects.length > 0) {
-
- toReturn.preset = this.preset;
-
- if (!toReturn.remembered) {
- toReturn.remembered = {};
- }
-
- toReturn.remembered[this.preset] = getCurrentPreset(this);
-
- }
-
- toReturn.folders = {};
- common.each(this.__folders, function(element, key) {
- toReturn.folders[key] = element.getSaveObject();
- });
-
- return toReturn;
-
- },
-
- save: function() {
-
- if (!this.load.remembered) {
- this.load.remembered = {};
- }
-
- this.load.remembered[this.preset] = getCurrentPreset(this);
- markPresetModified(this, false);
- this.saveToLocalStorageIfPossible();
-
- },
-
- saveAs: function(presetName) {
-
- if (!this.load.remembered) {
-
- // Retain default values upon first save
- this.load.remembered = {};
- this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true);
-
- }
-
- this.load.remembered[presetName] = getCurrentPreset(this);
- this.preset = presetName;
- addPresetOption(this, presetName, true);
- this.saveToLocalStorageIfPossible();
-
- },
-
- revert: function(gui) {
-
- common.each(this.__controllers, function(controller) {
- // Make revert work on Default.
- if (!this.getRoot().load.remembered) {
- controller.setValue(controller.initialValue);
- } else {
- recallSavedValue(gui || this.getRoot(), controller);
- }
- }, this);
-
- common.each(this.__folders, function(folder) {
- folder.revert(folder);
- });
-
- if (!gui) {
- markPresetModified(this.getRoot(), false);
- }
-
-
- },
-
- listen: function(controller) {
-
- var init = this.__listening.length == 0;
- this.__listening.push(controller);
- if (init) updateDisplays(this.__listening);
+ // Pass down the loaded data
+ new_gui_params.load = this.load.folders[name];
}
+ var gui = new GUI(new_gui_params);
+ this.__folders[name] = gui;
+
+ var li = addRow(this, gui.domElement);
+ dom.addClass(li, 'folder');
+ return gui;
+
+ },
+
+ open: function() {
+ this.closed = false;
+ },
+
+ close: function() {
+ this.closed = true;
+ },
+
+ onResize: function() {
+
+ var root = this.getRoot();
+
+ if (root.scrollable) {
+
+ var top = dom.getOffset(root.__ul).top;
+ var h = 0;
+
+ common.each(root.__ul.childNodes, function(node) {
+ if (!(root.autoPlace && node === root.__save_row))
+ h += dom.getHeight(node);
+ });
+
+ if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) {
+ dom.addClass(root.domElement, GUI.CLASS_TOO_TALL);
+ root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px';
+ } else {
+ dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL);
+ root.__ul.style.height = 'auto';
+ }
+
+ }
+
+ if (root.__resize_handle) {
+ common.defer(function() {
+ root.__resize_handle.style.height = root.__ul.offsetHeight + 'px';
+ });
+ }
+
+ if (root.__closeButton) {
+ root.__closeButton.style.width = root.width + 'px';
+ }
+
+ },
+
+ /**
+ * Mark objects for saving. The order of these objects cannot change as
+ * the GUI grows. When remembering new objects, append them to the end
+ * of the list.
+ *
+ * @param {Object...} objects
+ * @throws {Error} if not called on a top level GUI.
+ * @instance
+ */
+ remember: function() {
+
+ if (common.isUndefined(SAVE_DIALOGUE)) {
+ SAVE_DIALOGUE = new CenteredDiv();
+ SAVE_DIALOGUE.domElement.innerHTML = saveDialogueContents;
+ }
+
+ if (this.parent) {
+ throw new Error("You can only call remember on a top level GUI.");
+ }
+
+ var _this = this;
+
+ common.each(Array.prototype.slice.call(arguments), function(object) {
+ if (_this.__rememberedObjects.length == 0) {
+ addSaveMenu(_this);
+ }
+ if (_this.__rememberedObjects.indexOf(object) == -1) {
+ _this.__rememberedObjects.push(object);
+ }
+ });
+
+ if (this.autoPlace) {
+ // Set save row width
+ setWidth(this, this.width);
+ }
+
+ },
+
+ /**
+ * @returns {dat.gui.GUI} the topmost parent GUI of a nested GUI.
+ * @instance
+ */
+ getRoot: function() {
+ var gui = this;
+ while (gui.parent) {
+ gui = gui.parent;
+ }
+ return gui;
+ },
+
+ /**
+ * @returns {Object} a JSON object representing the current state of
+ * this GUI as well as its remembered properties.
+ * @instance
+ */
+ getSaveObject: function() {
+
+ var toReturn = this.load;
+
+ toReturn.closed = this.closed;
+
+ // Am I remembering any values?
+ if (this.__rememberedObjects.length > 0) {
+
+ toReturn.preset = this.preset;
+
+ if (!toReturn.remembered) {
+ toReturn.remembered = {};
+ }
+
+ toReturn.remembered[this.preset] = getCurrentPreset(this);
+
+ }
+
+ toReturn.folders = {};
+ common.each(this.__folders, function(element, key) {
+ toReturn.folders[key] = element.getSaveObject();
+ });
+
+ return toReturn;
+
+ },
+
+ save: function() {
+
+ if (!this.load.remembered) {
+ this.load.remembered = {};
+ }
+
+ this.load.remembered[this.preset] = getCurrentPreset(this);
+ markPresetModified(this, false);
+ this.saveToLocalStorageIfPossible();
+
+ },
+
+ saveAs: function(presetName) {
+
+ if (!this.load.remembered) {
+
+ // Retain default values upon first save
+ this.load.remembered = {};
+ this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true);
+
+ }
+
+ this.load.remembered[presetName] = getCurrentPreset(this);
+ this.preset = presetName;
+ addPresetOption(this, presetName, true);
+ this.saveToLocalStorageIfPossible();
+
+ },
+
+ revert: function(gui) {
+
+ common.each(this.__controllers, function(controller) {
+ // Make revert work on Default.
+ if (!this.getRoot().load.remembered) {
+ controller.setValue(controller.initialValue);
+ } else {
+ recallSavedValue(gui || this.getRoot(), controller);
+ }
+ }, this);
+
+ common.each(this.__folders, function(folder) {
+ folder.revert(folder);
+ });
+
+ if (!gui) {
+ markPresetModified(this.getRoot(), false);
+ }
+
+
+ },
+
+ listen: function(controller) {
+
+ var init = this.__listening.length == 0;
+ this.__listening.push(controller);
+ if (init) updateDisplays(this.__listening);
+
}
+ }
+
);
function add(gui, object, property, params) {
@@ -2305,7 +3161,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
} else {
- var factoryArgs = [object,property].concat(params.factoryArgs);
+ var factoryArgs = [object, property].concat(params.factoryArgs);
controller = controllerFactory.apply(gui, factoryArgs);
}
@@ -2371,13 +3227,12 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
controller.remove();
return add(
- gui,
- controller.object,
- controller.property,
- {
- before: controller.__li.nextElementSibling,
- factoryArgs: [common.toArray(arguments)]
- }
+ gui,
+ controller.object,
+ controller.property, {
+ before: controller.__li.nextElementSibling,
+ factoryArgs: [common.toArray(arguments)]
+ }
);
}
@@ -2386,13 +3241,12 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
controller.remove();
return add(
- gui,
- controller.object,
- controller.property,
- {
- before: controller.__li.nextElementSibling,
- factoryArgs: [options]
- }
+ gui,
+ controller.object,
+ controller.property, {
+ before: controller.__li.nextElementSibling,
+ factoryArgs: [options]
+ }
);
}
@@ -2419,8 +3273,11 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
// All sliders should be accompanied by a box.
if (controller instanceof NumberControllerSlider) {
- var box = new NumberControllerBox(controller.object, controller.property,
- { min: controller.__min, max: controller.__max, step: controller.__step });
+ var box = new NumberControllerBox(controller.object, controller.property, {
+ min: controller.__min,
+ max: controller.__max,
+ step: controller.__step
+ });
common.each(['updateDisplay', 'onChange', 'onFinishChange'], function(method) {
var pc = controller[method];
@@ -2435,8 +3292,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
dom.addClass(li, 'has-slider');
controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild);
- }
- else if (controller instanceof NumberControllerBox) {
+ } else if (controller instanceof NumberControllerBox) {
var r = function(returned) {
@@ -2446,13 +3302,12 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
// Well, then lets just replace this with a slider.
controller.remove();
return add(
- gui,
- controller.object,
- controller.property,
- {
- before: controller.__li.nextElementSibling,
- factoryArgs: [controller.__min, controller.__max, controller.__step]
- });
+ gui,
+ controller.object,
+ controller.property, {
+ before: controller.__li.nextElementSibling,
+ factoryArgs: [controller.__min, controller.__max, controller.__step]
+ });
}
@@ -2463,8 +3318,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
controller.min = common.compose(r, controller.min);
controller.max = common.compose(r, controller.max);
- }
- else if (controller instanceof BooleanController) {
+ } else if (controller instanceof BooleanController) {
dom.bind(li, 'click', function() {
dom.fakeEvent(controller.__checkbox, 'click');
@@ -2474,8 +3328,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
e.stopPropagation(); // Prevents double-toggle
})
- }
- else if (controller instanceof FunctionController) {
+ } else if (controller instanceof FunctionController) {
dom.bind(li, 'click', function() {
dom.fakeEvent(controller.__button, 'click');
@@ -2489,8 +3342,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
dom.removeClass(controller.__button, 'hover');
});
- }
- else if (controller instanceof ColorController) {
+ } else if (controller instanceof ColorController) {
dom.addClass(li, 'color');
controller.updateDisplay = common.compose(function(r) {
@@ -2525,14 +3377,14 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
// Let me fetch a map of controllers for thcommon.isObject.
var controller_map =
- root.__rememberedObjectIndecesToControllers[matched_index];
+ root.__rememberedObjectIndecesToControllers[matched_index];
// Ohp, I believe this is the first controller we've created for this
// object. Lets make the map fresh.
if (controller_map === undefined) {
controller_map = {};
root.__rememberedObjectIndecesToControllers[matched_index] =
- controller_map;
+ controller_map;
}
// Keep track of this controller
@@ -2568,7 +3420,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
if (preset[matched_index] &&
// Did we remember this particular property?
- preset[matched_index][controller.property] !== undefined) {
+ preset[matched_index][controller.property] !== undefined) {
// We did remember something for this guy ...
var value = preset[matched_index][controller.property];
@@ -2705,7 +3557,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
gui.revert();
});
-// div.appendChild(button2);
+ // div.appendChild(button2);
}
@@ -2720,7 +3572,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
height: '200px',
cursor: 'ew-resize',
position: 'absolute'
-// border: '1px solid blue'
+ // border: '1px solid blue'
});
@@ -2773,7 +3625,8 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
// set the width manually if we want it to bleed to the edge
if (gui.__save_row && gui.autoPlace) {
gui.__save_row.style.width = w + 'px';
- }if (gui.__closeButton) {
+ }
+ if (gui.__closeButton) {
gui.__closeButton.style.width = w + 'px';
}
}
@@ -2789,7 +3642,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
// The controllers I've made for thcommon.isObject by property
var controller_map =
- gui.__rememberedObjectIndecesToControllers[index];
+ gui.__rememberedObjectIndecesToControllers[index];
// Remember each value for each property
common.each(controller_map, function(controller, property) {
@@ -2825,7 +3678,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
function markPresetModified(gui, modified) {
var opt = gui.__preset_select[gui.__preset_select.selectedIndex];
-// console.log('mark', modified, opt);
+ // console.log('mark', modified, opt);
if (modified) {
opt.innerHTML = opt.value + "*";
} else {
@@ -2838,7 +3691,7 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
if (controllerArray.length != 0) {
- requestAnimationFrame(function() {
+ raf(function() {
updateDisplays(controllerArray);
});
@@ -2851,705 +3704,201 @@ dat.GUI = dat.gui.GUI = (function (css, saveDialogueContents, styleSheet, contro
}
return GUI;
+}
-})(dat.utils.css,
-"GUI
's constructor:\n\n \n\n localStorage
on exit.\n\n localStorage
will\n override those passed to dat.GUI
's constructor. This makes it\n easier to work incrementally, but localStorage
is fragile,\n and your friends may not see the same values you do.\n \n GUI
\'s constructor:\n\n \n\n localStorage
on exit.\n\n localStorage
will\n override those passed to dat.GUI
\'s constructor. This makes it\n easier to work incrementally, but localStorage
is fragile,\n and your friends may not see the same values you do.\n \n GUI
\'s constructor:\n\n \n\n localStorage
on exit.\n\n localStorage
will\n override those passed to dat.GUI
\'s constructor. This makes it\n easier to work incrementally, but localStorage
is fragile,\n and your friends may not see the same values you do.\n \n