/** * 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 */ function ___$insertStyle( css ) { if ( ! css ) { return; } if ( typeof window === 'undefined' ) { return; } var style = document.createElement( 'style' ); style.setAttribute( 'type', 'text/css' ); style.innerHTML = css; document.head.appendChild( style ); return css; } function colorToString( color, forceCSSHex ) { var colorFormat = color.__state.conversionName.toString(); var r = Math.round( color.r ); var g = Math.round( color.g ); var b = Math.round( color.b ); var a = color.a; var h = Math.round( color.h ); var s = color.s.toFixed( 1 ); var v = color.v.toFixed( 1 ); if ( forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX' ) { var str = color.hex.toString( 16 ); while ( str.length < 6 ) { str = '0' + str; } return '#' + str; } else if ( colorFormat === 'CSS_RGB' ) { return 'rgb(' + r + ',' + g + ',' + b + ')'; } else if ( colorFormat === 'CSS_RGBA' ) { return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; } else if ( colorFormat === 'HEX' ) { return '0x' + color.hex.toString( 16 ); } else if ( colorFormat === 'RGB_ARRAY' ) { return '[' + r + ',' + g + ',' + b + ']'; } else if ( colorFormat === 'RGBA_ARRAY' ) { return '[' + r + ',' + g + ',' + b + ',' + a + ']'; } else if ( colorFormat === 'RGB_OBJ' ) { return '{r:' + r + ',g:' + g + ',b:' + b + '}'; } else if ( colorFormat === 'RGBA_OBJ' ) { return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; } else if ( colorFormat === 'HSV_OBJ' ) { return '{h:' + h + ',s:' + s + ',v:' + v + '}'; } else if ( colorFormat === 'HSVA_OBJ' ) { return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; } return 'unknown format'; } var ARR_EACH = Array.prototype.forEach; var ARR_SLICE = Array.prototype.slice; var Common = { BREAK: {}, extend: function extend( target ) { this.each( ARR_SLICE.call( arguments, 1 ), function ( obj ) { var keys = this.isObject( obj ) ? Object.keys( obj ) : []; keys.forEach( function ( key ) { if ( ! this.isUndefined( obj[ key ] ) ) { target[ key ] = obj[ key ]; } }.bind( this ) ); }, this ); return target; }, defaults: function defaults( target ) { this.each( ARR_SLICE.call( arguments, 1 ), function ( obj ) { var keys = this.isObject( obj ) ? Object.keys( obj ) : []; keys.forEach( function ( key ) { if ( this.isUndefined( target[ key ] ) ) { target[ key ] = obj[ key ]; } }.bind( this ) ); }, this ); return target; }, compose: function compose() { var toCall = ARR_SLICE.call( arguments ); return function () { var args = ARR_SLICE.call( arguments ); for ( var i = toCall.length - 1; i >= 0; i -- ) { args = [ toCall[ i ].apply( this, args ) ]; } return args[ 0 ]; }; }, each: function each( obj, itr, scope ) { if ( ! obj ) { return; } if ( ARR_EACH && obj.forEach && obj.forEach === ARR_EACH ) { obj.forEach( itr, scope ); } else if ( obj.length === obj.length + 0 ) { var key = void 0; var l = void 0; for ( key = 0, l = obj.length; key < l; key ++ ) { if ( key in obj && itr.call( scope, obj[ key ], key ) === this.BREAK ) { return; } } } else { for ( var _key in obj ) { if ( itr.call( scope, obj[ _key ], _key ) === this.BREAK ) { return; } } } }, defer: function defer( fnc ) { setTimeout( fnc, 0 ); }, debounce: function debounce( func, threshold, callImmediately ) { var timeout = void 0; return function () { var obj = this; var args = arguments; function delayed() { timeout = null; if ( ! callImmediately ) func.apply( obj, args ); } var callNow = callImmediately || ! timeout; clearTimeout( timeout ); timeout = setTimeout( delayed, threshold ); if ( callNow ) { func.apply( obj, args ); } }; }, toArray: function toArray( obj ) { if ( obj.toArray ) return obj.toArray(); return ARR_SLICE.call( obj ); }, isUndefined: function isUndefined( obj ) { return obj === undefined; }, isNull: function isNull( obj ) { return obj === null; }, isNaN: function ( _isNaN ) { function isNaN() { return _isNaN.apply( this, arguments ); } isNaN.toString = function () { return _isNaN.toString(); }; return isNaN; }( function ( obj ) { return isNaN( obj ); } ), isArray: Array.isArray || function ( obj ) { return obj.constructor === Array; }, isObject: function isObject( obj ) { return obj === Object( obj ); }, isNumber: function isNumber( obj ) { return obj === obj + 0; }, isString: function isString( obj ) { return obj === obj + ''; }, isBoolean: function isBoolean( obj ) { return obj === false || obj === true; }, isFunction: function isFunction( obj ) { return obj instanceof Function; } }; var INTERPRETATIONS = [ { litmus: Common.isString, conversions: { THREE_CHAR_HEX: { read: function read( original ) { var test = original.match( /^#([A-F0-9])([A-F0-9])([A-F0-9])$/i ); if ( test === null ) { return false; } return { space: 'HEX', hex: parseInt( '0x' + test[ 1 ].toString() + test[ 1 ].toString() + test[ 2 ].toString() + test[ 2 ].toString() + test[ 3 ].toString() + test[ 3 ].toString(), 0 ) }; }, write: colorToString }, SIX_CHAR_HEX: { read: function read( original ) { var test = original.match( /^#([A-F0-9]{6})$/i ); if ( test === null ) { return false; } return { space: 'HEX', hex: parseInt( '0x' + test[ 1 ].toString(), 0 ) }; }, write: colorToString }, CSS_RGB: { read: function read( original ) { var test = original.match( /^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/ ); if ( test === null ) { return false; } return { space: 'RGB', r: parseFloat( test[ 1 ] ), g: parseFloat( test[ 2 ] ), b: parseFloat( test[ 3 ] ) }; }, write: colorToString }, CSS_RGBA: { read: function read( original ) { var test = original.match( /^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/ ); if ( test === null ) { return false; } return { space: 'RGB', r: parseFloat( test[ 1 ] ), g: parseFloat( test[ 2 ] ), b: parseFloat( test[ 3 ] ), a: parseFloat( test[ 4 ] ) }; }, write: colorToString } } }, { litmus: Common.isNumber, conversions: { HEX: { read: function read( original ) { return { space: 'HEX', hex: original, conversionName: 'HEX' }; }, write: function write( color ) { return color.hex; } } } }, { litmus: Common.isArray, conversions: { RGB_ARRAY: { read: function read( original ) { if ( original.length !== 3 ) { return false; } return { space: 'RGB', r: original[ 0 ], g: original[ 1 ], b: original[ 2 ] }; }, write: function write( color ) { return [ color.r, color.g, color.b ]; } }, RGBA_ARRAY: { read: function read( original ) { if ( original.length !== 4 ) return false; return { space: 'RGB', r: original[ 0 ], g: original[ 1 ], b: original[ 2 ], a: original[ 3 ] }; }, write: function write( color ) { return [ color.r, color.g, color.b, color.a ]; } } } }, { litmus: Common.isObject, conversions: { RGBA_OBJ: { read: function read( original ) { if ( Common.isNumber( original.r ) && Common.isNumber( original.g ) && Common.isNumber( original.b ) && Common.isNumber( original.a ) ) { return { space: 'RGB', r: original.r, g: original.g, b: original.b, a: original.a }; } return false; }, write: function write( color ) { return { r: color.r, g: color.g, b: color.b, a: color.a }; } }, RGB_OBJ: { read: function read( original ) { if ( Common.isNumber( original.r ) && Common.isNumber( original.g ) && Common.isNumber( original.b ) ) { return { space: 'RGB', r: original.r, g: original.g, b: original.b }; } return false; }, write: function write( color ) { return { r: color.r, g: color.g, b: color.b }; } }, HSVA_OBJ: { read: function read( original ) { if ( Common.isNumber( original.h ) && Common.isNumber( original.s ) && Common.isNumber( original.v ) && Common.isNumber( original.a ) ) { return { space: 'HSV', h: original.h, s: original.s, v: original.v, a: original.a }; } return false; }, write: function write( color ) { return { h: color.h, s: color.s, v: color.v, a: color.a }; } }, HSV_OBJ: { read: function read( original ) { if ( Common.isNumber( original.h ) && Common.isNumber( original.s ) && Common.isNumber( original.v ) ) { return { space: 'HSV', h: original.h, s: original.s, v: original.v }; } return false; }, write: function write( color ) { return { h: color.h, s: color.s, v: color.v }; } } } } ]; var result = void 0; var toReturn = void 0; var interpret = function interpret() { toReturn = false; var original = arguments.length > 1 ? Common.toArray( arguments ) : arguments[ 0 ]; Common.each( INTERPRETATIONS, function ( family ) { if ( family.litmus( original ) ) { Common.each( family.conversions, function ( conversion, conversionName ) { result = conversion.read( original ); if ( toReturn === false && result !== false ) { toReturn = result; result.conversionName = conversionName; result.conversion = conversion; return Common.BREAK; } } ); return Common.BREAK; } } ); return toReturn; }; var tmpComponent = void 0; var ColorMath = { hsv_to_rgb: function hsv_to_rgb( 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 rgb_to_hsv( r, g, b ) { var min = Math.min( r, g, b ); var max = Math.max( r, g, b ); var delta = max - min; var h = void 0; var s = void 0; 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 rgb_to_hex( 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 component_from_hex( hex, componentIndex ) { return hex >> componentIndex * 8 & 0xFF; }, hex_with_component: function hex_with_component( hex, componentIndex, value ) { return value << ( tmpComponent = componentIndex * 8 ) | hex & ~ ( 0xFF << tmpComponent ); } }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function ( obj ) { return typeof obj; } : function ( obj ) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function ( instance, Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError( "Cannot call a class as a function" ); } }; var createClass = function () { function defineProperties( target, props ) { for ( var i = 0; i < props.length; i ++ ) { var descriptor = props[ i ]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ( "value" in descriptor ) descriptor.writable = true; Object.defineProperty( target, descriptor.key, descriptor ); } } return function ( Constructor, protoProps, staticProps ) { if ( protoProps ) defineProperties( Constructor.prototype, protoProps ); if ( staticProps ) defineProperties( Constructor, staticProps ); return Constructor; }; }(); var get = function get( object, property, receiver ) { if ( object === null ) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor( object, property ); if ( desc === undefined ) { var parent = Object.getPrototypeOf( object ); if ( parent === null ) { return undefined; } else { return get( parent, property, receiver ); } } else if ( "value" in desc ) { return desc.value; } else { var getter = desc.get; if ( getter === undefined ) { return undefined; } return getter.call( receiver ); } }; var inherits = function ( subClass, superClass ) { if ( typeof superClass !== "function" && superClass !== null ) { throw new TypeError( "Super expression must either be null or a function, not " + typeof superClass ); } subClass.prototype = Object.create( superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } } ); if ( superClass ) Object.setPrototypeOf ? Object.setPrototypeOf( subClass, superClass ) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function ( self, call ) { if ( ! self ) { throw new ReferenceError( "this hasn't been initialised - super() hasn't been called" ); } return call && ( typeof call === "object" || typeof call === "function" ) ? call : self; }; var Color = function () { function Color() { classCallCheck( this, Color ); this.__state = interpret.apply( this, arguments ); if ( this.__state === false ) { throw new Error( 'Failed to interpret color arguments' ); } this.__state.a = this.__state.a || 1; } createClass( Color, [ { key: 'toString', value: function toString() { return colorToString( this ); } }, { key: 'toHexString', value: function toHexString() { return colorToString( this, true ); } }, { key: 'toOriginal', value: function toOriginal() { return this.__state.conversion.write( this ); } } ] ); return Color; }(); function defineRGBComponent( target, component, componentHexIndex ) { Object.defineProperty( target, component, { get: function get$$1() { if ( this.__state.space === 'RGB' ) { return this.__state[ component ]; } Color.recalculateRGB( this, component, componentHexIndex ); return this.__state[ component ]; }, set: function set$$1( v ) { if ( this.__state.space !== 'RGB' ) { Color.recalculateRGB( this, component, componentHexIndex ); this.__state.space = 'RGB'; } this.__state[ component ] = v; } } ); } function defineHSVComponent( target, component ) { Object.defineProperty( target, component, { get: function get$$1() { if ( this.__state.space === 'HSV' ) { return this.__state[ component ]; } Color.recalculateHSV( this ); return this.__state[ component ]; }, set: function set$$1( v ) { if ( this.__state.space !== 'HSV' ) { Color.recalculateHSV( this ); this.__state.space = 'HSV'; } this.__state[ component ] = v; } } ); } Color.recalculateRGB = function ( color, component, componentHexIndex ) { if ( color.__state.space === 'HEX' ) { color.__state[ component ] = ColorMath.component_from_hex( color.__state.hex, componentHexIndex ); } else if ( color.__state.space === 'HSV' ) { Common.extend( color.__state, ColorMath.hsv_to_rgb( color.__state.h, color.__state.s, color.__state.v ) ); } else { throw new Error( 'Corrupted color state' ); } }; Color.recalculateHSV = function ( color ) { var result = ColorMath.rgb_to_hsv( color.r, color.g, color.b ); Common.extend( color.__state, { s: result.s, v: result.v } ); if ( ! Common.isNaN( result.h ) ) { color.__state.h = result.h; } else if ( Common.isUndefined( color.__state.h ) ) { color.__state.h = 0; } }; Color.COMPONENTS = [ 'r', 'g', 'b', 'h', 's', 'v', 'hex', 'a' ]; defineRGBComponent( Color.prototype, 'r', 2 ); defineRGBComponent( Color.prototype, 'g', 1 ); defineRGBComponent( Color.prototype, 'b', 0 ); defineHSVComponent( Color.prototype, 'h' ); defineHSVComponent( Color.prototype, 's' ); defineHSVComponent( Color.prototype, 'v' ); Object.defineProperty( Color.prototype, 'a', { get: function get$$1() { return this.__state.a; }, set: function set$$1( v ) { this.__state.a = v; } } ); Object.defineProperty( Color.prototype, 'hex', { get: function get$$1() { if ( this.__state.space !== 'HEX' ) { this.__state.hex = ColorMath.rgb_to_hex( this.r, this.g, this.b ); this.__state.space = 'HEX'; } return this.__state.hex; }, set: function set$$1( v ) { this.__state.space = 'HEX'; this.__state.hex = v; } } ); var Controller = function () { function Controller( object, property ) { classCallCheck( this, Controller ); this.initialValue = object[ property ]; this.domElement = document.createElement( 'div' ); this.object = object; this.property = property; this.__onChange = undefined; this.__onFinishChange = undefined; } createClass( Controller, [ { key: 'onChange', value: function onChange( fnc ) { this.__onChange = fnc; return this; } }, { key: 'onFinishChange', value: function onFinishChange( fnc ) { this.__onFinishChange = fnc; return this; } }, { key: 'setValue', value: function setValue( newValue ) { this.object[ this.property ] = newValue; if ( this.__onChange ) { this.__onChange.call( this, newValue ); } this.updateDisplay(); return this; } }, { key: 'getValue', value: function getValue() { return this.object[ this.property ]; } }, { key: 'updateDisplay', value: function updateDisplay() { return this; } }, { key: 'isModified', value: function isModified() { return this.initialValue !== this.getValue(); } } ] ); return Controller; }(); 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 ] ); } return 0; } var dom = { makeSelectable: function makeSelectable( 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'; }, makeFullscreen: function makeFullscreen( elem, hor, vert ) { var vertical = vert; var horizontal = hor; 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; } }, fakeEvent: function fakeEvent( elem, eventType, pars, aux ) { var params = pars || {}; 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, 0, clientX, clientY, false, false, false, false, 0, null ); break; } case 'KeyboardEvents': { var init = evt.initKeyboardEvent || evt.initKeyEvent; 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 ); }, bind: function bind( elem, event, func, newBool ) { var bool = newBool || false; if ( elem.addEventListener ) { elem.addEventListener( event, func, bool ); } else if ( elem.attachEvent ) { elem.attachEvent( 'on' + event, func ); } return dom; }, unbind: function unbind( elem, event, func, newBool ) { var bool = newBool || false; if ( elem.removeEventListener ) { elem.removeEventListener( event, func, bool ); } else if ( elem.detachEvent ) { elem.detachEvent( 'on' + event, func ); } return dom; }, addClass: function addClass( 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; }, removeClass: function removeClass( elem, className ) { if ( className ) { 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 hasClass( elem, className ) { return new RegExp( '(?:^|\\s+)' + className + '(?:\\s+|$)' ).test( elem.className ) || false; }, getWidth: function getWidth( 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 ); }, getHeight: function getHeight( 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 ); }, getOffset: function getOffset( el ) { var elem = el; var offset = { left: 0, top: 0 }; if ( elem.offsetParent ) { do { offset.left += elem.offsetLeft; offset.top += elem.offsetTop; elem = elem.offsetParent; } while ( elem ); } return offset; }, isActive: function isActive( elem ) { return elem === document.activeElement && ( elem.type || elem.href ); } }; var BooleanController = function ( _Controller ) { inherits( BooleanController, _Controller ); function BooleanController( object, property ) { classCallCheck( this, BooleanController ); var _this2 = possibleConstructorReturn( this, ( BooleanController.__proto__ || Object.getPrototypeOf( BooleanController ) ).call( this, object, property ) ); var _this = _this2; _this2.__prev = _this2.getValue(); _this2.__checkbox = document.createElement( 'input' ); _this2.__checkbox.setAttribute( 'type', 'checkbox' ); function onChange() { _this.setValue( ! _this.__prev ); } dom.bind( _this2.__checkbox, 'change', onChange, false ); _this2.domElement.appendChild( _this2.__checkbox ); _this2.updateDisplay(); return _this2; } createClass( BooleanController, [ { key: 'setValue', value: function setValue( v ) { var toReturn = get( BooleanController.prototype.__proto__ || Object.getPrototypeOf( BooleanController.prototype ), 'setValue', this ).call( this, v ); if ( this.__onFinishChange ) { this.__onFinishChange.call( this, this.getValue() ); } this.__prev = this.getValue(); return toReturn; } }, { key: 'updateDisplay', value: function updateDisplay() { if ( this.getValue() === true ) { this.__checkbox.setAttribute( 'checked', 'checked' ); this.__checkbox.checked = true; this.__prev = true; } else { this.__checkbox.checked = false; this.__prev = false; } return get( BooleanController.prototype.__proto__ || Object.getPrototypeOf( BooleanController.prototype ), 'updateDisplay', this ).call( this ); } } ] ); return BooleanController; }( Controller ); var OptionController = function ( _Controller ) { inherits( OptionController, _Controller ); function OptionController( object, property, opts ) { classCallCheck( this, OptionController ); var _this2 = possibleConstructorReturn( this, ( OptionController.__proto__ || Object.getPrototypeOf( OptionController ) ).call( this, object, property ) ); var options = opts; var _this = _this2; _this2.__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 ); } ); _this2.updateDisplay(); dom.bind( _this2.__select, 'change', function () { var desiredValue = this.options[ this.selectedIndex ].value; _this.setValue( desiredValue ); } ); _this2.domElement.appendChild( _this2.__select ); return _this2; } createClass( OptionController, [ { key: 'setValue', value: function setValue( v ) { var toReturn = get( OptionController.prototype.__proto__ || Object.getPrototypeOf( OptionController.prototype ), 'setValue', this ).call( this, v ); if ( this.__onFinishChange ) { this.__onFinishChange.call( this, this.getValue() ); } return toReturn; } }, { key: 'updateDisplay', value: function updateDisplay() { if ( dom.isActive( this.__select ) ) return this; this.__select.value = this.getValue(); return get( OptionController.prototype.__proto__ || Object.getPrototypeOf( OptionController.prototype ), 'updateDisplay', this ).call( this ); } } ] ); return OptionController; }( Controller ); var StringController = function ( _Controller ) { inherits( StringController, _Controller ); function StringController( object, property ) { classCallCheck( this, StringController ); var _this2 = possibleConstructorReturn( this, ( StringController.__proto__ || Object.getPrototypeOf( StringController ) ).call( this, object, property ) ); var _this = _this2; function onChange() { _this.setValue( _this.__input.value ); } function onBlur() { if ( _this.__onFinishChange ) { _this.__onFinishChange.call( _this, _this.getValue() ); } } _this2.__input = document.createElement( 'input' ); _this2.__input.setAttribute( 'type', 'text' ); dom.bind( _this2.__input, 'keyup', onChange ); dom.bind( _this2.__input, 'change', onChange ); dom.bind( _this2.__input, 'blur', onBlur ); dom.bind( _this2.__input, 'keydown', function ( e ) { if ( e.keyCode === 13 ) { this.blur(); } } ); _this2.updateDisplay(); _this2.domElement.appendChild( _this2.__input ); return _this2; } createClass( StringController, [ { key: 'updateDisplay', value: function updateDisplay() { if ( ! dom.isActive( this.__input ) ) { this.__input.value = this.getValue(); } return get( StringController.prototype.__proto__ || Object.getPrototypeOf( StringController.prototype ), 'updateDisplay', this ).call( this ); } } ] ); return StringController; }( Controller ); function numDecimals( x ) { var _x = x.toString(); if ( _x.indexOf( '.' ) > - 1 ) { return _x.length - _x.indexOf( '.' ) - 1; } return 0; } var NumberController = function ( _Controller ) { inherits( NumberController, _Controller ); function NumberController( object, property, params ) { classCallCheck( this, NumberController ); var _this = possibleConstructorReturn( this, ( NumberController.__proto__ || Object.getPrototypeOf( NumberController ) ).call( this, object, property ) ); var _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; } else { _this.__impliedStep = Math.pow( 10, Math.floor( Math.log( Math.abs( _this.initialValue ) ) / Math.LN10 ) ) / 10; } } else { _this.__impliedStep = _this.__step; } _this.__precision = numDecimals( _this.__impliedStep ); return _this; } createClass( NumberController, [ { key: 'setValue', value: function setValue( v ) { var _v = 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 get( NumberController.prototype.__proto__ || Object.getPrototypeOf( NumberController.prototype ), 'setValue', this ).call( this, _v ); } }, { key: 'min', value: function min( minValue ) { this.__min = minValue; return this; } }, { key: 'max', value: function max( maxValue ) { this.__max = maxValue; return this; } }, { key: 'step', value: function step( stepValue ) { this.__step = stepValue; this.__impliedStep = stepValue; this.__precision = numDecimals( stepValue ); return this; } } ] ); return NumberController; }( Controller ); function roundToDecimal( value, decimals ) { var tenTo = Math.pow( 10, decimals ); return Math.round( value * tenTo ) / tenTo; } var NumberControllerBox = function ( _NumberController ) { inherits( NumberControllerBox, _NumberController ); function NumberControllerBox( object, property, params ) { classCallCheck( this, NumberControllerBox ); var _this2 = possibleConstructorReturn( this, ( NumberControllerBox.__proto__ || Object.getPrototypeOf( NumberControllerBox ) ).call( this, object, property, params ) ); _this2.__truncationSuspended = false; var _this = _this2; var prevY = void 0; function onChange() { var attempted = parseFloat( _this.__input.value ); if ( ! Common.isNaN( attempted ) ) { _this.setValue( attempted ); } } function onFinish() { if ( _this.__onFinishChange ) { _this.__onFinishChange.call( _this, _this.getValue() ); } } function onBlur() { onFinish(); } function onMouseDrag( e ) { var diff = prevY - e.clientY; _this.setValue( _this.getValue() + diff * _this.__impliedStep ); prevY = e.clientY; } function onMouseUp() { dom.unbind( window, 'mousemove', onMouseDrag ); dom.unbind( window, 'mouseup', onMouseUp ); onFinish(); } function onMouseDown( e ) { dom.bind( window, 'mousemove', onMouseDrag ); dom.bind( window, 'mouseup', onMouseUp ); prevY = e.clientY; } _this2.__input = document.createElement( 'input' ); _this2.__input.setAttribute( 'type', 'text' ); dom.bind( _this2.__input, 'change', onChange ); dom.bind( _this2.__input, 'blur', onBlur ); dom.bind( _this2.__input, 'mousedown', onMouseDown ); dom.bind( _this2.__input, 'keydown', function ( e ) { if ( e.keyCode === 13 ) { _this.__truncationSuspended = true; this.blur(); _this.__truncationSuspended = false; onFinish(); } } ); _this2.updateDisplay(); _this2.domElement.appendChild( _this2.__input ); return _this2; } createClass( NumberControllerBox, [ { key: 'updateDisplay', value: function updateDisplay() { this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal( this.getValue(), this.__precision ); return get( NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf( NumberControllerBox.prototype ), 'updateDisplay', this ).call( this ); } } ] ); return NumberControllerBox; }( NumberController ); function map( v, i1, i2, o1, o2 ) { return o1 + ( o2 - o1 ) * ( ( v - i1 ) / ( i2 - i1 ) ); } var NumberControllerSlider = function ( _NumberController ) { inherits( NumberControllerSlider, _NumberController ); function NumberControllerSlider( object, property, min, max, step ) { classCallCheck( this, NumberControllerSlider ); var _this2 = possibleConstructorReturn( this, ( NumberControllerSlider.__proto__ || Object.getPrototypeOf( NumberControllerSlider ) ).call( this, object, property, { min: min, max: max, step: step } ) ); var _this = _this2; _this2.__background = document.createElement( 'div' ); _this2.__foreground = document.createElement( 'div' ); dom.bind( _this2.__background, 'mousedown', onMouseDown ); dom.bind( _this2.__background, 'touchstart', onTouchStart ); dom.addClass( _this2.__background, 'slider' ); dom.addClass( _this2.__foreground, 'slider-fg' ); function onMouseDown( e ) { document.activeElement.blur(); dom.bind( window, 'mousemove', onMouseDrag ); dom.bind( window, 'mouseup', onMouseUp ); onMouseDrag( e ); } function onMouseDrag( e ) { e.preventDefault(); var bgRect = _this.__background.getBoundingClientRect(); _this.setValue( map( e.clientX, bgRect.left, bgRect.right, _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() ); } } function onTouchStart( e ) { if ( e.touches.length !== 1 ) { return; } dom.bind( window, 'touchmove', onTouchMove ); dom.bind( window, 'touchend', onTouchEnd ); onTouchMove( e ); } function onTouchMove( e ) { var clientX = e.touches[ 0 ].clientX; var bgRect = _this.__background.getBoundingClientRect(); _this.setValue( map( clientX, bgRect.left, bgRect.right, _this.__min, _this.__max ) ); } function onTouchEnd() { dom.unbind( window, 'touchmove', onTouchMove ); dom.unbind( window, 'touchend', onTouchEnd ); if ( _this.__onFinishChange ) { _this.__onFinishChange.call( _this, _this.getValue() ); } } _this2.updateDisplay(); _this2.__background.appendChild( _this2.__foreground ); _this2.domElement.appendChild( _this2.__background ); return _this2; } createClass( NumberControllerSlider, [ { key: 'updateDisplay', value: function updateDisplay() { var pct = ( this.getValue() - this.__min ) / ( this.__max - this.__min ); this.__foreground.style.width = pct * 100 + '%'; return get( NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf( NumberControllerSlider.prototype ), 'updateDisplay', this ).call( this ); } } ] ); return NumberControllerSlider; }( NumberController ); var FunctionController = function ( _Controller ) { inherits( FunctionController, _Controller ); function FunctionController( object, property, text ) { classCallCheck( this, FunctionController ); var _this2 = possibleConstructorReturn( this, ( FunctionController.__proto__ || Object.getPrototypeOf( FunctionController ) ).call( this, object, property ) ); var _this = _this2; _this2.__button = document.createElement( 'div' ); _this2.__button.innerHTML = text === undefined ? 'Fire' : text; dom.bind( _this2.__button, 'click', function ( e ) { e.preventDefault(); _this.fire(); return false; } ); dom.addClass( _this2.__button, 'button' ); _this2.domElement.appendChild( _this2.__button ); return _this2; } createClass( FunctionController, [ { key: 'fire', value: function fire() { if ( this.__onChange ) { this.__onChange.call( this ); } this.getValue().call( this.object ); if ( this.__onFinishChange ) { this.__onFinishChange.call( this, this.getValue() ); } } } ] ); return FunctionController; }( Controller ); var ColorController = function ( _Controller ) { inherits( ColorController, _Controller ); function ColorController( object, property ) { classCallCheck( this, ColorController ); var _this2 = possibleConstructorReturn( this, ( ColorController.__proto__ || Object.getPrototypeOf( ColorController ) ).call( this, object, property ) ); _this2.__color = new Color( _this2.getValue() ); _this2.__temp = new Color( 0 ); var _this = _this2; _this2.domElement = document.createElement( 'div' ); dom.makeSelectable( _this2.domElement, false ); _this2.__selector = document.createElement( 'div' ); _this2.__selector.className = 'selector'; _this2.__saturation_field = document.createElement( 'div' ); _this2.__saturation_field.className = 'saturation-field'; _this2.__field_knob = document.createElement( 'div' ); _this2.__field_knob.className = 'field-knob'; _this2.__field_knob_border = '2px solid '; _this2.__hue_knob = document.createElement( 'div' ); _this2.__hue_knob.className = 'hue-knob'; _this2.__hue_field = document.createElement( 'div' ); _this2.__hue_field.className = 'hue-field'; _this2.__input = document.createElement( 'input' ); _this2.__input.type = 'text'; _this2.__input_textShadow = '0 1px 1px '; dom.bind( _this2.__input, 'keydown', function ( e ) { if ( e.keyCode === 13 ) { onBlur.call( this ); } } ); dom.bind( _this2.__input, 'blur', onBlur ); dom.bind( _this2.__selector, 'mousedown', function () { dom.addClass( this, 'drag' ).bind( window, 'mouseup', function () { dom.removeClass( _this.__selector, 'drag' ); } ); } ); dom.bind( _this2.__selector, 'touchstart', function () { dom.addClass( this, 'drag' ).bind( window, 'touchend', function () { dom.removeClass( _this.__selector, 'drag' ); } ); } ); var valueField = document.createElement( 'div' ); Common.extend( _this2.__selector.style, { width: '122px', height: '102px', padding: '3px', backgroundColor: '#222', boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' } ); Common.extend( _this2.__field_knob.style, { position: 'absolute', width: '12px', height: '12px', border: _this2.__field_knob_border + ( _this2.__color.v < 0.5 ? '#fff' : '#000' ), boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', borderRadius: '12px', zIndex: 1 } ); Common.extend( _this2.__hue_knob.style, { position: 'absolute', width: '15px', height: '2px', borderRight: '4px solid #fff', zIndex: 1 } ); Common.extend( _this2.__saturation_field.style, { width: '100px', height: '100px', border: '1px solid #555', marginRight: '3px', display: 'inline-block', cursor: 'pointer' } ); Common.extend( valueField.style, { width: '100%', height: '100%', background: 'none' } ); linearGradient( valueField, 'top', 'rgba(0,0,0,0)', '#000' ); Common.extend( _this2.__hue_field.style, { width: '15px', height: '100px', border: '1px solid #555', cursor: 'ns-resize', position: 'absolute', top: '3px', right: '3px' } ); hueGradient( _this2.__hue_field ); Common.extend( _this2.__input.style, { outline: 'none', textAlign: 'center', color: '#fff', border: 0, fontWeight: 'bold', textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' } ); dom.bind( _this2.__saturation_field, 'mousedown', fieldDown ); dom.bind( _this2.__saturation_field, 'touchstart', fieldDown ); dom.bind( _this2.__field_knob, 'mousedown', fieldDown ); dom.bind( _this2.__field_knob, 'touchstart', fieldDown ); dom.bind( _this2.__hue_field, 'mousedown', fieldDownH ); dom.bind( _this2.__hue_field, 'touchstart', fieldDownH ); function fieldDown( e ) { setSV( e ); dom.bind( window, 'mousemove', setSV ); dom.bind( window, 'touchmove', setSV ); dom.bind( window, 'mouseup', fieldUpSV ); dom.bind( window, 'touchend', fieldUpSV ); } function fieldDownH( e ) { setH( e ); dom.bind( window, 'mousemove', setH ); dom.bind( window, 'touchmove', setH ); dom.bind( window, 'mouseup', fieldUpH ); dom.bind( window, 'touchend', fieldUpH ); } function fieldUpSV() { dom.unbind( window, 'mousemove', setSV ); dom.unbind( window, 'touchmove', setSV ); dom.unbind( window, 'mouseup', fieldUpSV ); dom.unbind( window, 'touchend', fieldUpSV ); onFinish(); } function fieldUpH() { dom.unbind( window, 'mousemove', setH ); dom.unbind( window, 'touchmove', setH ); dom.unbind( window, 'mouseup', fieldUpH ); dom.unbind( window, 'touchend', fieldUpH ); onFinish(); } 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 onFinish() { if ( _this.__onFinishChange ) { _this.__onFinishChange.call( _this, _this.__color.toOriginal() ); } } _this2.__saturation_field.appendChild( valueField ); _this2.__selector.appendChild( _this2.__field_knob ); _this2.__selector.appendChild( _this2.__saturation_field ); _this2.__selector.appendChild( _this2.__hue_field ); _this2.__hue_field.appendChild( _this2.__hue_knob ); _this2.domElement.appendChild( _this2.__input ); _this2.domElement.appendChild( _this2.__selector ); _this2.updateDisplay(); function setSV( e ) { if ( e.type.indexOf( 'touch' ) === - 1 ) { e.preventDefault(); } var fieldRect = _this.__saturation_field.getBoundingClientRect(); var _ref = e.touches && e.touches[ 0 ] || e, clientX = _ref.clientX, clientY = _ref.clientY; var s = ( clientX - fieldRect.left ) / ( fieldRect.right - fieldRect.left ); var v = 1 - ( clientY - fieldRect.top ) / ( fieldRect.bottom - fieldRect.top ); 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 ) { if ( e.type.indexOf( 'touch' ) === - 1 ) { e.preventDefault(); } var fieldRect = _this.__hue_field.getBoundingClientRect(); var _ref2 = e.touches && e.touches[ 0 ] || e, clientY = _ref2.clientY; var h = 1 - ( clientY - fieldRect.top ) / ( fieldRect.bottom - fieldRect.top ); if ( h > 1 ) { h = 1; } else if ( h < 0 ) { h = 0; } _this.__color.h = h * 360; _this.setValue( _this.__color.toOriginal() ); return false; } return _this2; } createClass( ColorController, [ { key: 'updateDisplay', value: function updateDisplay() { var i = interpret( this.getValue() ); if ( i !== false ) { var mismatch = false; 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 {}; } }, this ); 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 < 0.5 || this.__color.s > 0.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.toHexString(), 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.toHexString() ); this.__input.value = this.__color.toString(); Common.extend( this.__input.style, { backgroundColor: this.__color.toHexString(), color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' } ); } } ] ); return ColorController; }( Controller ); 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%);'; } var css = { load: function load( url, indoc ) { var doc = indoc || document; var link = doc.createElement( 'link' ); link.type = 'text/css'; link.rel = 'stylesheet'; link.href = url; doc.getElementsByTagName( 'head' )[ 0 ].appendChild( link ); }, inject: function inject( cssContent, indoc ) { var doc = indoc || document; var injected = document.createElement( 'style' ); injected.type = 'text/css'; injected.innerHTML = cssContent; var head = doc.getElementsByTagName( 'head' )[ 0 ]; try { head.appendChild( injected ); } catch ( e ) { } } }; var saveDialogContents = "
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