From 402093179a87f524ce4f4eaec7db2094f6a8f155 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 00:44:54 +0000 Subject: [PATCH 01/54] Removed google analytics (to avoid lag when reloading :S) Updated "pretified" code. --- index.html | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/index.html b/index.html index e08f68e..d5bb603 100644 --- a/index.html +++ b/index.html @@ -48,16 +48,6 @@ gui.add(fizzyText, "explode").setName('Explode!'); // Specify a custom name. }; - - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-20996084-1']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); @@ -81,24 +71,25 @@ window.onload = function() { var fizzyText = new FizzyText("gui-dat"); - GUI.start(); + var gui = new GUI(); + document.body.appendChild( gui.domElement ); // Text field - GUI.add(fizzyText, "message"); + gui.add(fizzyText, "message"); // Sliders with min and max - GUI.add(fizzyText, "maxSize", 0.5, 7); - GUI.add(fizzyText, "growthSpeed", 0.01, 1); - GUI.add(fizzyText, "speed", 0.1, 2); + gui.add(fizzyText, "maxSize", 0.5, 7); + gui.add(fizzyText, "growthSpeed", 0.01, 1); + gui.add(fizzyText, "speed", 0.1, 2); // Sliders with min, max and increment. - GUI.add(fizzyText, "noiseStrength", 10, 100, 5); + gui.add(fizzyText, "noiseStrength", 10, 100, 5); // Boolean checkbox - GUI.add(fizzyText, "displayOutline"); + gui.add(fizzyText, "displayOutline"); // Fires a function called "explode" - GUI.add(fizzyText, "explode").setName('Explode!'); // Specify a custom name. + gui.add(fizzyText, "explode").setName('Explode!'); // Specify a custom name. }; From d770dbb0c20e41a3ab38605d46ceff5e69696461 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 01:23:20 +0000 Subject: [PATCH 02/54] Hacked in a Controllers Watcher. It would be nice if the controllers had the last value cached so setValue will execute only if _value != value. Added a setWatched example in the demo. --- controllers/controller.js | 13 ++++++-- controllers/controller.number.js | 10 ++---- demo/demo.js | 11 +++++-- gui.js | 21 ++++++++---- index.html | 55 +++++++++++++++++--------------- 5 files changed, 65 insertions(+), 45 deletions(-) diff --git a/controllers/controller.js b/controllers/controller.js index ad90e73..ab9ae44 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -9,6 +9,15 @@ var Controller = function() { return this; } + this.setWatched = function() { + this.parent.watchController(this); + return this; + } + + this.getValue = function() { + return this.object[this.propertyName]; + } + this.setValue = function(n) { this.object[this.propertyName] = n; if (onChange != null) { @@ -17,8 +26,8 @@ var Controller = function() { return this; } - this.getValue = function() { - return this.object[this.propertyName]; + this.watchValue = function() { + this.updateValue(this.object[this.propertyName]); } this.onChange = function(fnc) { diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 80d299b..0907c1c 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -20,15 +20,9 @@ var NumberController = function() { var step = arguments[4]; if (!step) { - if (min != undefined && max != undefined) { - step = (max-min)*0.01; - } else { - step = 1; - } + step = min != undefined && max != undefined ? (max-min)*0.01: 1; } - console.log("step " + step); - var numberField = document.createElement('input'); numberField.setAttribute('id', this.propertyName); @@ -94,7 +88,7 @@ var NumberController = function() { // We don't want to be highlighting this field as we scroll. // Or any other fields in this gui for that matter ... // TODO: Make makeUselectable go through each element and child element. - _this.makeUnselectable(GUI.domElement); + _this.makeUnselectable(_this.parent.domElement); _this.makeUnselectable(numberField); py = y; diff --git a/demo/demo.js b/demo/demo.js index 9ac306c..0a4298a 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,15 +1,18 @@ function FizzyText(message) { + var that = this; + // These are the variables that we manipulate with gui-dat. // Notice they're all defined with "this". That makes them public. // Otherwise, gui-dat can't see them. - + this.growthSpeed = 0.5; // how fast do particles change size? this.maxSize = 3.2; // how big can they get? this.noiseStrength = 10; // how turbulent is the flow? this.speed = 0.4; // how fast do particles move? this.displayOutline = false; // should we draw the message as a stroke? - + this.framesRendered = 0; + // __defineGetter__ and __defineSetter__ makes JavaScript believe that // we've defined a variable 'this.message'. This way, whenever we // change the message variable, we can call some more functions. @@ -98,6 +101,8 @@ function FizzyText(message) { // Called once per frame, updates the animation. var render = function () { + that.framesRendered ++; + g.clearRect(0, 0, width, height); if (_this.displayOutline) { @@ -216,4 +221,4 @@ function FizzyText(message) { return v; } -} \ No newline at end of file +} diff --git a/gui.js b/gui.js index 96baa02..c9f1e8c 100644 --- a/gui.js +++ b/gui.js @@ -22,6 +22,13 @@ var GUI = function () { this.domElement.appendChild(controllerContainer); this.domElement.appendChild(toggleButton); + // Controllers Watcher + setInterval( function() { + for (var c in controllersWatched) { + controllersWatched[c].watchValue(); + } + }, 1000 / 60 ); + var handlerTypes = { "number": NumberController, "string": StringController, @@ -96,16 +103,16 @@ var GUI = function () { return controllerObject; + }; + + this.watchController = function(c) { + + controllersWatched.push(c); + } this.toggle = function() { - - if (open) { - this.hide(); - } else { - this.show(); - } - + open ? this.hide() : this.show(); }; this.show = function() { diff --git a/index.html b/index.html index d5bb603..ff4dbc8 100644 --- a/index.html +++ b/index.html @@ -2,8 +2,8 @@ gui-dat - - + + @@ -17,37 +17,42 @@ - - - - + + + @@ -89,7 +94,7 @@ window.onload = function() { gui.add(fizzyText, "displayOutline"); // Fires a function called "explode" - gui.add(fizzyText, "explode").setName('Explode!'); // Specify a custom name. + gui.add(fizzyText, "explode").setName("Explode!"); // Specify a custom name. }; From a3b3e38d1dfd96461ac41d4cb4ee764e6bcb7942 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 01:34:57 +0000 Subject: [PATCH 03/54] Merged with jonobr1 branch. --- README | 59 ++++++++++++++++++++++++++++++++---------------------- README.md | 44 ++++++++++++++++++++++++++++++++++++++++ index.html | 18 ++++++++++++++--- 3 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 README.md diff --git a/README b/README index 426e5b2..1f8431a 100644 --- a/README +++ b/README @@ -1,31 +1,42 @@ - var controllableObject = - { - numberProperty: 20, - anotherNumberProperty: 0, - textProperty: "a string", - booleanProperty: false, - functionProperty: function() { - alert("I am a function!"); - } - }; +# gui-dat +**gui-dat** is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly. +## Basic Usage + + ++ ui-dat will infer the type of the property you're trying to add (based on its initial value) and create the corresponding control. ++ The properties must be public, i.e. defined by `**this**.prop = value`. +## Monitor variable changes outside of the GUI +Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method + GUI.add(obj, "propName").listen(); +## Fire a function when someone uses a control + GUI.add(obj, "propName").onChange(function(n) { + alert("You changed me to " + n); + }); +Initiated by [George Michael Brower]:http://georgemichaelbrower.com/ and [Jono Brandel]:http://jonobr1.com/ of the Data Arts Team, Google Creative Lab. diff --git a/README.md b/README.md new file mode 100644 index 0000000..415cd25 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# gui-dat +**gui-dat** is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly. +## Basic Usage + + ++ ui-dat will infer the type of the property you're trying to add (based on its initial value) and create the corresponding control. ++ The properties must be public, i.e. defined by `this.prop = value`. + +Monitor variable changes outside of the GUI +-------------------------------------------------- +Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method + GUI.add(obj, "propName").listen(); +## Fire a function when someone uses a control + GUI.add(obj, "propName").onChange(function(n) { + alert("You changed me to " + n); + }); +Initiated by [George Michael Brower](http://georgemichaelbrower.com/) and [Jono Brandel](http://jonobr1.com/) of the Data Arts Team, Google Creative Lab. diff --git a/index.html b/index.html index ff4dbc8..259cc21 100644 --- a/index.html +++ b/index.html @@ -104,8 +104,20 @@ window.onload = function() {
  • gui-dat will infer the type of the property you're trying to add
    (based on its initial value) and create the corresponding control.
  • The properties must be public, i.e. defined by this.prop = value.
  • - + + + + + From fe172c75fb4beb4bc7def2805d18175d7c6a335b Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 02:25:48 +0000 Subject: [PATCH 04/54] Added updateValue method to StringController (so watched string controllers update). Moved easing from margin-top to height. It's now showing an ugly scrollbar jump. Hmm... --- controllers/controller.string.js | 50 ++++++++++++++++++-------------- gui.css | 8 ++--- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/controllers/controller.string.js b/controllers/controller.string.js index aa955ea..835ba39 100644 --- a/controllers/controller.string.js +++ b/controllers/controller.string.js @@ -1,27 +1,33 @@ var StringController = function() { - + this.type = "string"; - + var _this = this; - - Controller.apply(this, arguments); - - var input = document.createElement('input'); - - var initialValue = this.getValue(); - - input.setAttribute('value', initialValue); - input.setAttribute('spellcheck', 'false'); - this.domElement.addEventListener('mouseup', function() { - input.focus(); - input.select(); - }, false); - - input.addEventListener('keyup', function() { - _this.setValue(input.value); - }, false); - - this.domElement.appendChild(input); + + Controller.apply(this, arguments); + + var input = document.createElement('input'); + + var initialValue = this.getValue(); + + input.setAttribute('value', initialValue); + input.setAttribute('spellcheck', 'false'); + + this.domElement.addEventListener('mouseup', function() { + input.focus(); + input.select(); + }, false); + + input.addEventListener('keyup', function() { + _this.setValue(input.value); + }, false); + + this.domElement.appendChild(input); + + this.updateValue = function(val) { + input.setAttribute('value', val); + } + }; StringController.prototype = new Controller(); -StringController.prototype.constructor = StringController; \ No newline at end of file +StringController.prototype.constructor = StringController; diff --git a/gui.css b/gui.css index 98a57a8..d035320 100644 --- a/gui.css +++ b/gui.css @@ -8,9 +8,6 @@ left: 100%; margin-left: -300px; background-color: #fff; - -moz-transition: margin-top .2s ease-out; - -webkit-transition: margin-top .2s ease-out; - transition: margin-top .2s ease-out; -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); @@ -26,6 +23,9 @@ overflow-y: auto; overflow-x: hidden; background-color: rgba(0,0,0,0.1); + -moz-transition: height .2s ease-out; + -webkit-transition: height .2s ease-out; + transition: height .2s ease-out; } #guidat-toggle { @@ -155,4 +155,4 @@ width: 148px; .guidat-slider-fg { background-color: #00aeff; height: 20px; -} \ No newline at end of file +} From f736507fd460001e7b160324f9bc33b00515d2b2 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 19:55:43 -0700 Subject: [PATCH 05/54] Merged in mr doobs changes for watchers and changed setName to name --- controllers/controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/controller.js b/controllers/controller.js index ab9ae44..92c770f 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -4,7 +4,7 @@ var Controller = function() { this.parent = null; - this.setName = function(n) { + this.name = function(n) { this.propertyNameElement.innerHTML = n; return this; } @@ -57,7 +57,7 @@ var Controller = function() { this.propertyNameElement = document.createElement('span'); this.propertyNameElement.setAttribute('class', 'guidat-propertyname'); - this.setName(this.propertyName); + this.name(this.propertyName); this.domElement.appendChild(this.propertyNameElement); this.makeUnselectable(this.domElement); From a4d600f3b063d9b58054733c4ec1c0fe90001d80 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:03:56 -0700 Subject: [PATCH 06/54] why does README keep popping back up? --- README | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 README diff --git a/README b/README deleted file mode 100644 index 1f8431a..0000000 --- a/README +++ /dev/null @@ -1,42 +0,0 @@ -# gui-dat -**gui-dat** is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly. -## Basic Usage - - -+ ui-dat will infer the type of the property you're trying to add (based on its initial value) and create the corresponding control. -+ The properties must be public, i.e. defined by `**this**.prop = value`. -## Monitor variable changes outside of the GUI -Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method - GUI.add(obj, "propName").listen(); -## Fire a function when someone uses a control - GUI.add(obj, "propName").onChange(function(n) { - alert("You changed me to " + n); - }); -Initiated by [George Michael Brower]:http://georgemichaelbrower.com/ and [Jono Brandel]:http://jonobr1.com/ of the Data Arts Team, Google Creative Lab. From 092419bdad4e49333b8f8194a27035572d34225a Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:17:57 -0700 Subject: [PATCH 07/54] updated index.html doc to reflect setWatched() --- index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.html b/index.html index 259cc21..245dd3d 100644 --- a/index.html +++ b/index.html @@ -93,6 +93,9 @@ window.onload = function() { // Boolean checkbox gui.add(fizzyText, "displayOutline"); + // Watches a property + gui.add(fizzyText, "framesRendered").setWatched(); + // Fires a function called "explode" gui.add(fizzyText, "explode").setName("Explode!"); // Specify a custom name. From 2dc271fa44ac2aec43ffedd197fbe56bde299464 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:22:05 -0700 Subject: [PATCH 08/54] updated index to reflect the new listen() and onChange() functionality --- controllers/controller.js | 2 +- index.html | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/controller.js b/controllers/controller.js index 92c770f..0fa37ff 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -9,7 +9,7 @@ var Controller = function() { return this; } - this.setWatched = function() { + this.listen = function() { this.parent.watchController(this); return this; } diff --git a/index.html b/index.html index 245dd3d..416e06a 100644 --- a/index.html +++ b/index.html @@ -46,7 +46,7 @@ gui.add(fizzyText, "displayOutline"); // Watches a property - gui.add(fizzyText, "framesRendered").setWatched(); + gui.add(fizzyText, "framesRendered").listen(); // Fires a function called "explode" gui.add(fizzyText, "explode").setName("Explode!"); // Specify a custom name. @@ -94,7 +94,7 @@ window.onload = function() { gui.add(fizzyText, "displayOutline"); // Watches a property - gui.add(fizzyText, "framesRendered").setWatched(); + gui.add(fizzyText, "framesRendered").listen(); // Fires a function called "explode" gui.add(fizzyText, "explode").setName("Explode!"); // Specify a custom name. @@ -108,7 +108,7 @@ window.onload = function() {
  • The properties must be public, i.e. defined by this.prop = value.
  • - +});
    Initiated by George Michael Brower and Jono Brandel of the Data Arts Team, Google Creative Lab. From 54d198cac50a1adb08bb619bec6e0edc78b94f4f Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:27:17 -0700 Subject: [PATCH 09/54] minor tweaks --- demo/demo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/demo.js b/demo/demo.js index 0a4298a..5bea7e1 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -101,7 +101,7 @@ function FizzyText(message) { // Called once per frame, updates the animation. var render = function () { - that.framesRendered ++; + that.framesRendered ++; g.clearRect(0, 0, width, height); From d8dc82515e79a00de4595e8160b308e484832083 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:38:05 -0700 Subject: [PATCH 10/54] had to update setName() to name() again --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 416e06a..d020927 100644 --- a/index.html +++ b/index.html @@ -49,7 +49,7 @@ gui.add(fizzyText, "framesRendered").listen(); // Fires a function called "explode" - gui.add(fizzyText, "explode").setName("Explode!"); // Specify a custom name. + gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. }; @@ -97,7 +97,7 @@ window.onload = function() { gui.add(fizzyText, "framesRendered").listen(); // Fires a function called "explode" - gui.add(fizzyText, "explode").setName("Explode!"); // Specify a custom name. + gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. }; From d6edaf6da5f2e035704fb80c20b9496cef47e9ab Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:51:44 -0700 Subject: [PATCH 11/54] minor tweaks --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index d020927..3d751d9 100644 --- a/index.html +++ b/index.html @@ -93,8 +93,8 @@ window.onload = function() { // Boolean checkbox gui.add(fizzyText, "displayOutline"); - // Watches a property - gui.add(fizzyText, "framesRendered").listen(); + // Watches a property + gui.add(fizzyText, "framesRendered").listen(); // Fires a function called "explode" gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. From 7ba44aace68a0f04ac1c84da315122fff2dff92a Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:54:26 -0700 Subject: [PATCH 12/54] minor tweaks --- index.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/index.html b/index.html index 3d751d9..e4d62c6 100644 --- a/index.html +++ b/index.html @@ -93,9 +93,6 @@ window.onload = function() { // Boolean checkbox gui.add(fizzyText, "displayOutline"); - // Watches a property - gui.add(fizzyText, "framesRendered").listen(); - // Fires a function called "explode" gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. From a378d33baeb2e78e77ed03e40c165d9fe29d2368 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 03:56:32 +0000 Subject: [PATCH 13/54] Fixed loop issue. Now watched controllers don't set the value after updating. --- controllers/controller.boolean.js | 39 ++--- controllers/controller.function.js | 16 +- controllers/controller.js | 23 +-- controllers/controller.number.js | 226 +++++++++++++++-------------- controllers/controller.string.js | 15 +- controllers/slider.js | 3 +- gui.js | 2 +- 7 files changed, 167 insertions(+), 157 deletions(-) diff --git a/controllers/controller.boolean.js b/controllers/controller.boolean.js index 3acc78f..2287f19 100644 --- a/controllers/controller.boolean.js +++ b/controllers/controller.boolean.js @@ -1,25 +1,26 @@ var BooleanController = function() { this.type = "boolean"; - Controller.apply(this, arguments); + Controller.apply(this, arguments); - var _this = this; - var input = document.createElement('input'); - input.setAttribute('type', 'checkbox'); - - this.domElement.addEventListener('click', function(e) { - input.checked = !input.checked; - e.preventDefault(); - _this.setValue(input.checked); - }, false); - - input.addEventListener('mouseup', function(e) { - input.checked = !input.checked; // counteracts default. - }, false); - - this.domElement.style.cursor = "pointer"; - this.propertyNameElement.style.cursor = "pointer"; - this.domElement.appendChild(input); + var that = this; + var input = document.createElement('input'); + input.setAttribute('type', 'checkbox'); + + this.domElement.addEventListener('click', function(e) { + e.preventDefault(); + input.checked = !input.checked; + that.value = input.checked; + that.setTargetValue(that.value); + }, false); + + input.addEventListener('mouseup', function(e) { + input.checked = !input.checked; // counteracts default. + }, false); + + this.domElement.style.cursor = "pointer"; + this.propertyNameElement.style.cursor = "pointer"; + this.domElement.appendChild(input); }; BooleanController.prototype = new Controller(); -BooleanController.prototype.constructor = BooleanController; \ No newline at end of file +BooleanController.prototype.constructor = BooleanController; diff --git a/controllers/controller.function.js b/controllers/controller.function.js index d523562..c95c5ec 100644 --- a/controllers/controller.function.js +++ b/controllers/controller.function.js @@ -1,12 +1,12 @@ var FunctionController = function() { this.type = "function"; - var _this = this; - Controller.apply(this, arguments); - this.domElement.addEventListener('click', function() { - _this.object[_this.propertyName].call(_this.object); - }, false); - this.domElement.style.cursor = "pointer"; - this.propertyNameElement.style.cursor = "pointer"; + var that = this; + Controller.apply(this, arguments); + this.domElement.addEventListener('click', function() { + that.object[that.propertyName].call(that.object); + }, false); + this.domElement.style.cursor = "pointer"; + this.propertyNameElement.style.cursor = "pointer"; }; FunctionController.prototype = new Controller(); -FunctionController.prototype.constructor = FunctionController; \ No newline at end of file +FunctionController.prototype.constructor = FunctionController; diff --git a/controllers/controller.js b/controllers/controller.js index ab9ae44..80253dc 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -3,51 +3,52 @@ var Controller = function() { var onChange = null; this.parent = null; + this.value = null; this.setName = function(n) { this.propertyNameElement.innerHTML = n; return this; - } + }; this.setWatched = function() { this.parent.watchController(this); return this; - } + }; - this.getValue = function() { + this.getTargetValue = function() { return this.object[this.propertyName]; - } + }; - this.setValue = function(n) { + this.setTargetValue = function(n) { this.object[this.propertyName] = n; if (onChange != null) { onChange.call(this, n); } return this; - } + }; - this.watchValue = function() { + this.watchTargetValue = function() { this.updateValue(this.object[this.propertyName]); - } + }; this.onChange = function(fnc) { onChange = fnc; return this; - } + }; this.makeUnselectable = function(elem) { elem.onselectstart = function() { return false; }; elem.style.MozUserSelect = "none"; elem.style.KhtmlUserSelect = "none"; elem.unselectable = "on"; - } + }; this.makeSelectable = function(elem) { elem.onselectstart = function() { }; elem.style.MozUserSelect = "auto"; elem.style.KhtmlUserSelect = "auto"; elem.unselectable = "off"; - } + }; this.domElement = document.createElement('div'); this.domElement.setAttribute('class', 'guidat-controller ' + this.type); diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 0907c1c..30f2856 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -2,124 +2,130 @@ var NumberController = function() { this.type = "number"; - - Controller.apply(this, arguments); - - var _this = this; - - // If we simply click and release a number field, we want to highlight it. - // This variable keeps track of whether or not we've dragged - var draggedNumberField = false; - - var clickedNumberField = false; - - var y = py = 0; - - var min = arguments[2]; - var max = arguments[3]; - var step = arguments[4]; - - if (!step) { - step = min != undefined && max != undefined ? (max-min)*0.01: 1; - } - - var numberField = document.createElement('input'); - numberField.setAttribute('id', this.propertyName); - - // Little up and down arrows are pissing me off. - numberField.setAttribute('type', 'text'); - numberField.setAttribute('value', this.getValue()); - - if (step) numberField.setAttribute('step', step); - - this.domElement.appendChild(numberField); - - var slider; - - if (min != undefined && max != undefined) { - slider = new Slider(this, min, max, step, this.getValue()); - this.domElement.appendChild(slider.domElement); - } - - numberField.addEventListener('blur', function(e) { - var val = parseFloat(this.value); - if (!isNaN(val)) { - _this.updateValue(val); - } else { - this.value = _this.getValue(); - } - }, false); - - numberField.addEventListener('mousewheel', function(e) { - e.preventDefault(); - this.updateValue(_this.getValue() + Math.abs(e.wheelDeltaY)/e.wheelDeltaY*step); - return false; - }, false); - - numberField.addEventListener('mousedown', function(e) { - py = y = e.pageY; - clickedNumberField = true; - document.addEventListener('mousemove', dragNumberField, false); - }, false); - - document.addEventListener('mouseup', function(e) { - document.removeEventListener('mousemove', dragNumberField, false); - _this.makeSelectable(_this.parent.domElement); - _this.makeSelectable(numberField); - if (clickedNumberField && !draggedNumberField) { - numberField.focus(); - numberField.select(); - } - draggedNumberField = false; - clickedNumberField = false; - }, false); - - // Kinda nast - if (navigator.appVersion.indexOf('chrome') != -1) { - document.addEventListener('mouseout', function(e) { - document.removeEventListener('mousemove', dragNumberField, false); - }, false); - } - - var dragNumberField = function(e) { - draggedNumberField = true; + + Controller.apply(this, arguments); + + var that = this; + + // If we simply click and release a number field, we want to highlight it. + // This variable keeps track of whether or not we've dragged + var draggedNumberField = false, clickedNumberField = false, + y = 0, py = 0; + + var min = arguments[2], max = arguments[3], step = arguments[4]; + + if (!step) { + step = min != undefined && max != undefined ? (max-min)*0.01: 1; + } + + var numberField = document.createElement('input'); + numberField.setAttribute('id', this.propertyName); + + this.value = this.getTargetValue(); + + // Little up and down arrows are pissing me off. + numberField.setAttribute('type', 'text'); + numberField.setAttribute('value', this.value); + + if (step) numberField.setAttribute('step', step); + + this.domElement.appendChild(numberField); + + var slider; + + if (min != undefined && max != undefined) { + slider = new Slider(this, min, max, step, this.value); + this.domElement.appendChild(slider.domElement); + } + + numberField.addEventListener('blur', function(e) { + var val = parseFloat(this.value); + if (!isNaN(val)) { + that.updateValue(val); + that.setTargetValue(that.value); + } else { + this.value = that.value; + } + }, false); + + numberField.addEventListener('mousewheel', function(e) { e.preventDefault(); - + that.updateValue(that.value + Math.abs(e.wheelDeltaY)/e.wheelDeltaY*step); + that.setTargetValue(that.value); + return false; + }, false); + + numberField.addEventListener('mousedown', function(e) { + py = y = e.pageY; + clickedNumberField = true; + document.addEventListener('mousemove', dragNumberField, false); + }, false); + + document.addEventListener('mouseup', function(e) { + document.removeEventListener('mousemove', dragNumberField, false); + that.makeSelectable(that.parent.domElement); + that.makeSelectable(numberField); + + if (clickedNumberField && !draggedNumberField) { + numberField.focus(); + numberField.select(); + } + + draggedNumberField = false; + clickedNumberField = false; + }, false); + + // Kinda nast + if (navigator.appVersion.indexOf('chrome') != -1) { + document.addEventListener('mouseout', function(e) { + document.removeEventListener('mousemove', dragNumberField, false); + }, false); + } + + var dragNumberField = function(e) { + draggedNumberField = true; + e.preventDefault(); + // We don't want to be highlighting this field as we scroll. - // Or any other fields in this gui for that matter ... + // Or any other fields in this gui for that matter ... // TODO: Make makeUselectable go through each element and child element. - _this.makeUnselectable(_this.parent.domElement); - _this.makeUnselectable(numberField); - + that.makeUnselectable(that.parent.domElement); + that.makeUnselectable(numberField); + py = y; y = e.pageY; var dy = py - y; - var newVal = _this.getValue() + dy*step; - _this.updateValue(newVal); + that.updateValue(that.value + dy*step); + that.setTargetValue(that.value); return false; - } - - this.updateValue = function(val) { + } + + this.updateValue = function(val) { + + if (that.value != val) { + + val = parseFloat(val); + + if (min != undefined && val <= min) { + val = min; + } else if (max != undefined && val >= max) { + val = max; + } + + that.value = val; + + numberField.value = roundToDecimal(val, 4); + + if (slider) slider.value = val; + + } + } + + var roundToDecimal = function(n, decimals) { + var t = Math.pow(10, decimals); + return Math.round(n*t)/t; + } - val = parseFloat(val); - - if (min != undefined && val <= min) { - val = min; - } else if (max != undefined && val >= max) { - val = max; - } - - _this.setValue(val); - - numberField.value = roundToDecimal(_this.getValue(), 4); - if (slider) slider.value = _this.getValue(); - } - - var roundToDecimal = function(n, decimals) { - var t = Math.pow(10, decimals); - return Math.round(n*t)/t; - } - }; NumberController.prototype = new Controller(); diff --git a/controllers/controller.string.js b/controllers/controller.string.js index 835ba39..789d074 100644 --- a/controllers/controller.string.js +++ b/controllers/controller.string.js @@ -2,15 +2,14 @@ var StringController = function() { this.type = "string"; - var _this = this; + var that = this; Controller.apply(this, arguments); + this.value = this.getTargetValue(); + var input = document.createElement('input'); - - var initialValue = this.getValue(); - - input.setAttribute('value', initialValue); + input.setAttribute('value', this.value); input.setAttribute('spellcheck', 'false'); this.domElement.addEventListener('mouseup', function() { @@ -19,13 +18,15 @@ var StringController = function() { }, false); input.addEventListener('keyup', function() { - _this.setValue(input.value); + that.updateValue(input.value); + that.setTargetValue(that.value); }, false); this.domElement.appendChild(input); this.updateValue = function(val) { - input.setAttribute('value', val); + that.value = val; + input.setAttribute('value', that.value); } }; diff --git a/controllers/slider.js b/controllers/slider.js index a45ea1a..55db279 100644 --- a/controllers/slider.js +++ b/controllers/slider.js @@ -49,6 +49,7 @@ var Slider = function(numberController, min, max, step, initValue) { var val = map(e.pageX, pos[0], pos[0] + _this.domElement.offsetWidth, min, max); val = Math.round(val/step)*step; numberController.updateValue(val); + numberController.setTargetValue(numberController.value); } this.domElement.addEventListener('mousedown', function(e) { @@ -70,4 +71,4 @@ var Slider = function(numberController, min, max, step, initValue) { this.value = initValue; -} \ No newline at end of file +} diff --git a/gui.js b/gui.js index c9f1e8c..0bfc4a9 100644 --- a/gui.js +++ b/gui.js @@ -25,7 +25,7 @@ var GUI = function () { // Controllers Watcher setInterval( function() { for (var c in controllersWatched) { - controllersWatched[c].watchValue(); + controllersWatched[c].watchTargetValue(); } }, 1000 / 60 ); From 83a9cbae32ce25e25943352b39576f32cd77a0c5 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 21:05:47 -0700 Subject: [PATCH 14/54] minor tweaks --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index e4d62c6..2cc0c96 100644 --- a/index.html +++ b/index.html @@ -46,7 +46,7 @@ gui.add(fizzyText, "displayOutline"); // Watches a property - gui.add(fizzyText, "framesRendered").listen(); + // gui.add(fizzyText, "framesRendered").listen(); // Fires a function called "explode" gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. From 0e7c179bfc04c29a431e6734d770caa344017f94 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 21:41:25 -0700 Subject: [PATCH 15/54] README updated for more dynamic purposes --- README.md | 42 +----------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/README.md b/README.md index 415cd25..d82136f 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,4 @@ # gui-dat **gui-dat** is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly. -## Basic Usage - - -+ ui-dat will infer the type of the property you're trying to add (based on its initial value) and create the corresponding control. -+ The properties must be public, i.e. defined by `this.prop = value`. - -Monitor variable changes outside of the GUI --------------------------------------------------- -Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method - GUI.add(obj, "propName").listen(); -## Fire a function when someone uses a control - GUI.add(obj, "propName").onChange(function(n) { - alert("You changed me to " + n); - }); +## Check the [index page](http://jonobr1.github.com/gui-dat/) for usage. Initiated by [George Michael Brower](http://georgemichaelbrower.com/) and [Jono Brandel](http://jonobr1.com/) of the Data Arts Team, Google Creative Lab. From ff6ffca84f3c93ad78c8db9230ebd588a8e535c9 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:12:03 -0700 Subject: [PATCH 16/54] synced with versions branch --- index.html | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/index.html b/index.html index 3807409..c978c7f 100644 --- a/index.html +++ b/index.html @@ -4,8 +4,6 @@ - - @@ -61,7 +59,7 @@

    @@ -139,6 +137,5 @@ setInterval(function() { Initiated by George Michael Brower and Jono Brandel of the Data Arts Team, Google Creative Lab.
    - From 32014e0fe97e3865d7bf2d35259d5354a45ab512 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:14:23 -0700 Subject: [PATCH 17/54] removed gui.min.js from branch and synced with versions branch --- gui.min.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 gui.min.js diff --git a/gui.min.js b/gui.min.js deleted file mode 100644 index 8d5d355..0000000 --- a/gui.min.js +++ /dev/null @@ -1 +0,0 @@ -var GUI=new function(){var g=this;var c=[];var a="#guidat{color:#fff;position:fixed;width:280px;z-index:200;opacity:.97;top:0;left:100%;margin-left:-300px;background-color:#fff;-moz-transition:margin-top .2s ease-out;-webkit-transition:margin-top .2s ease-out;transition:margin-top .2s ease-out;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.3);-moz-box-shadow:0 0 10px rgba(0,0,0,0.3);box-shadow:0 0 10px rgba(0,0,0,0.3)}#guidat,#guidat input{font:9.5px Lucida Grande,sans-serif}#guidat-controllers{height:300px;overflow-y:auto;overflow-x:hidden;background-color:rgba(0,0,0,0.1)}#guidat-toggle{text-decoration:none;cursor:pointer;color:#fff;background-color:#222;text-align:center;display:block;padding:5px}#guidat-toggle:hover{background-color:#000}.guidat-controller{padding:3px;height:25px;clear:left;border-bottom:1px solid #222;background-color:#111}.guidat-controller,.guidat-controller input,.guidat-slider-bg,.guidat-slider-fg{-moz-transition:background-color .15s linear;-webkit-transition:background-color .15s linear;transition:background-color .15s linear}.guidat-controller.boolean:hover,.guidat-controller.function:hover{background-color:#000}.guidat-controller input{float:right;outline:none;border:0;padding:4px;margin-top:2px;background-color:#222}.guidat-controller input:hover{background-color:#444}.guidat-controller input:focus{background-color:#555}.guidat-controller.number{border-left:5px solid #00aeff}.guidat-controller.string{border-left:5px solid #1ed36f}.guidat-controller.string input{border:0;color:#1ed36f;margin-right:2px;width:148px}.guidat-controller.boolean{border-left:5px solid #54396e}.guidat-controller.function{border-left:5px solid #e61d5f}.guidat-controller.number input[type=text]{width:35px;margin-left:5px;margin-right:2px;color:#00aeff}#guidat .guidat-controller.boolean input{margin-top:6px;margin-right:2px;font-size:20px}.guidat-controller:last-child{border-bottom:none;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.5);box-shadow:0 1px 3px rgba(0,0,0,0.5)}.guidat-propertyname{padding:5px;padding-top:7px;cursor:default;display:inline-block}.guidat-slider-bg:hover,.guidat-slider-bg.active{background-color:#444}.guidat-slider-bg:hover .guidat-slider-fg,.guidat-slider-bg.active .guidat-slider-fg{background-color:#52c8ff}.guidat-slider-bg{background-color:#222;cursor:ew-resize;width:40%;margin-top:2px;float:right;height:21px}.guidat-slider-fg{background-color:#00aeff;height:20px}";this.add=function(){if(!h){i("Make sure to call GUI.start() in the window.onload function");return}var n=arguments[0];var l=arguments[1];if(d(n,l)){i('Controller for "'+l+'" already added.');return}var q=n[l];if(q==undefined){i(n+' either has no property "'+l+'", or the property is inaccessible.');return}var p=typeof q;var o=j[p];if(o==undefined){i('Cannot create controller for data type "'+p+'"');return}var m=o.apply(this,arguments);if(!m){i('Error creating controller for "'+l+'".');return}b.appendChild(m.domElement);c.push(m);return m};var j={number:function(){return k(NumberController,arguments)},string:function(){return k(StringController,arguments)},"boolean":function(){return k(BooleanController,arguments)},"function":function(){return k(FunctionController,arguments)},};var d=function(m,l){for(var n in c){if(c[n].object==m&&c[n].propertyName==l){return true}}return false};var i=function(l){if(typeof console.log=="function"){console.error("[GUI ERROR] "+l)}};var k=function(m,l){function n(){return m.apply(this,l)}n.prototype=m.prototype;return new n()};this.domElement=null;var b;var h=false;var f=false;var e=300;this.start=function(){var l=document.createElement("style");l.setAttribute("type","text/css");l.innerHTML=a;document.getElementsByTagName("head")[0].appendChild(l);this.domElement=document.createElement("div");this.domElement.setAttribute("id","guidat");b=document.createElement("div");b.setAttribute("id","guidat-controllers");toggleButton=document.createElement("a");toggleButton.setAttribute("id","guidat-toggle");toggleButton.setAttribute("href","#");toggleButton.innerHTML="Show Controls";toggleButton.addEventListener("click",function(m){g.toggle();m.preventDefault()},false);this.domElement.appendChild(b);this.domElement.appendChild(toggleButton);this.domElement.style.marginTop=-e+"px";document.body.appendChild(this.domElement);h=true};this.toggle=function(){if(f){this.hide()}else{this.show()}};this.show=function(){this.domElement.style.marginTop=0+"px";toggleButton.innerHTML="Hide Controls";f=true};this.hide=function(){this.domElement.style.marginTop=-e+"px";toggleButton.innerHTML="Show Controls";f=false}};var Slider=function(a,e,j,c,i){var e=e;var j=j;var c=c;var h=false;var f=this;var k,l;this.domElement=document.createElement("div");this.fg=document.createElement("div");this.domElement.setAttribute("class","guidat-slider-bg");this.fg.setAttribute("class","guidat-slider-fg");this.domElement.appendChild(this.fg);var b=function(m,p,n,q,o){var m=q+(o-q)*((m-p)/(n-p));if(mo){m=o}}return m};var g=function(m){var n=curtop=0;if(m.offsetParent){do{n+=m.offsetLeft;curtop+=m.offsetTop}while(m=m.offsetParent);return[n,curtop]}};this.__defineSetter__("value",function(n){var m=b(n,e,j,0,100);this.fg.style.width=m+"%"});var d=function(m){if(!h){return}var o=g(f.domElement);var n=b(m.pageX,o[0],o[0]+f.domElement.offsetWidth,e,j);n=Math.round(n/c)*c;a.updateValue(n)};this.domElement.addEventListener("mousedown",function(m){h=true;k=l=m.pageX;f.domElement.setAttribute("class","guidat-slider-bg active");f.fg.setAttribute("class","guidat-slider-fg active");d(m)},false);document.addEventListener("mouseup",function(m){f.domElement.setAttribute("class","guidat-slider-bg");f.fg.setAttribute("class","guidat-slider-fg");h=false},false);document.addEventListener("mousemove",d,false);this.value=i};var Controller=function(){var a=null;this.setName=function(b){this.propertyNameElement.innerHTML=b};this.setValue=function(b){this.object[this.propertyName]=b;if(a!=null){a.call(this,b)}};this.getValue=function(){return this.object[this.propertyName]};this.onChange=function(b){a=b};this.makeUnselectable=function(b){b.onselectstart=function(){return false};b.style.MozUserSelect="none";b.style.KhtmlUserSelect="none";b.unselectable="on"};this.makeSelectable=function(b){b.onselectstart=function(){};b.style.MozUserSelect="auto";b.style.KhtmlUserSelect="auto";b.unselectable="off"};this.domElement=document.createElement("div");this.domElement.setAttribute("class","guidat-controller "+this.type);this.object=arguments[0];this.propertyName=arguments[1];this.propertyNameElement=document.createElement("span");this.propertyNameElement.setAttribute("class","guidat-propertyname");this.setName(this.propertyName);this.domElement.appendChild(this.propertyNameElement);this.makeUnselectable(this.domElement)};var BooleanController=function(){this.type="boolean";Controller.apply(this,arguments);var b=this;var a=document.createElement("input");a.setAttribute("type","checkbox");this.domElement.addEventListener("click",function(c){a.checked=!a.checked;c.preventDefault();b.setValue(a.checked)},false);a.addEventListener("mouseup",function(c){a.checked=!a.checked},false);this.domElement.style.cursor="pointer";this.propertyNameElement.style.cursor="pointer";this.domElement.appendChild(a)};BooleanController.prototype=new Controller();BooleanController.prototype.constructor=BooleanController;var FunctionController=function(){this.type="function";var a=this;Controller.apply(this,arguments);this.domElement.addEventListener("click",function(){a.object[a.propertyName].call(a.object)},false);this.domElement.style.cursor="pointer";this.propertyNameElement.style.cursor="pointer"};FunctionController.prototype=new Controller();FunctionController.prototype.constructor=FunctionController;var NumberController=function(){this.type="number";Controller.apply(this,arguments);var f=this;var a=false;var g=false;var i=py=0;var e=arguments[2];var j=arguments[3];var d=arguments[4];if(!d){if(e&&j){d=(j-e)*0.01}else{d=1}}var c=document.createElement("input");c.setAttribute("id",this.propertyName);c.setAttribute("type","text");c.setAttribute("value",this.getValue());if(d){c.setAttribute("step",d)}this.domElement.appendChild(c);var b;if(e!=undefined&&j!=undefined){b=new Slider(this,e,j,d,this.getValue());this.domElement.appendChild(b.domElement)}c.addEventListener("blur",function(k){var l=parseFloat(this.value);if(!isNaN(l)){f.updateValue(l)}else{this.value=f.getValue()}},false);c.addEventListener("mousewheel",function(k){k.preventDefault();this.updateValue(f.getValue()+Math.abs(k.wheelDeltaY)/k.wheelDeltaY*d);return false},false);c.addEventListener("mousedown",function(k){py=i=k.pageY;g=true;document.addEventListener("mousemove",h,false)},false);document.addEventListener("mouseup",function(k){document.removeEventListener("mousemove",h,false);f.makeSelectable(GUI.domElement);f.makeSelectable(c);if(g&&!a){c.focus();c.select()}a=false;g=false},false);if(navigator.appVersion.indexOf("chrome")!=-1){document.addEventListener("mouseout",function(k){document.removeEventListener("mousemove",h,false)},false)}var h=function(m){a=true;m.preventDefault();f.makeUnselectable(GUI.domElement);f.makeUnselectable(c);py=i;i=m.pageY;var k=py-i;var l=f.getValue()+k*d;f.updateValue(l);return false};this.updateValue=function(k){k=parseFloat(k);if(e!=undefined&&k<=e){k=e}else{if(j!=undefined&&k>=j){k=j}}f.setValue(k);c.value=f.getValue();if(b){b.value=f.getValue()}}};NumberController.prototype=new Controller();NumberController.prototype.constructor=NumberController;var StringController=function(){this.type="string";var c=this;Controller.apply(this,arguments);var b=document.createElement("input");var a=this.getValue();b.setAttribute("value",a);b.setAttribute("spellcheck","false");this.domElement.addEventListener("mouseup",function(){b.focus();b.select()},false);b.addEventListener("keyup",function(){c.setValue(b.value)},false);this.domElement.appendChild(b)};StringController.prototype=new Controller();StringController.prototype.constructor=StringController; \ No newline at end of file From ee383082004b807f75fa435eab2810f13e4429f3 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:16:31 -0700 Subject: [PATCH 18/54] removed gui.min.js from branch --- gui.min.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 gui.min.js diff --git a/gui.min.js b/gui.min.js deleted file mode 100644 index 8d5d355..0000000 --- a/gui.min.js +++ /dev/null @@ -1 +0,0 @@ -var GUI=new function(){var g=this;var c=[];var a="#guidat{color:#fff;position:fixed;width:280px;z-index:200;opacity:.97;top:0;left:100%;margin-left:-300px;background-color:#fff;-moz-transition:margin-top .2s ease-out;-webkit-transition:margin-top .2s ease-out;transition:margin-top .2s ease-out;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.3);-moz-box-shadow:0 0 10px rgba(0,0,0,0.3);box-shadow:0 0 10px rgba(0,0,0,0.3)}#guidat,#guidat input{font:9.5px Lucida Grande,sans-serif}#guidat-controllers{height:300px;overflow-y:auto;overflow-x:hidden;background-color:rgba(0,0,0,0.1)}#guidat-toggle{text-decoration:none;cursor:pointer;color:#fff;background-color:#222;text-align:center;display:block;padding:5px}#guidat-toggle:hover{background-color:#000}.guidat-controller{padding:3px;height:25px;clear:left;border-bottom:1px solid #222;background-color:#111}.guidat-controller,.guidat-controller input,.guidat-slider-bg,.guidat-slider-fg{-moz-transition:background-color .15s linear;-webkit-transition:background-color .15s linear;transition:background-color .15s linear}.guidat-controller.boolean:hover,.guidat-controller.function:hover{background-color:#000}.guidat-controller input{float:right;outline:none;border:0;padding:4px;margin-top:2px;background-color:#222}.guidat-controller input:hover{background-color:#444}.guidat-controller input:focus{background-color:#555}.guidat-controller.number{border-left:5px solid #00aeff}.guidat-controller.string{border-left:5px solid #1ed36f}.guidat-controller.string input{border:0;color:#1ed36f;margin-right:2px;width:148px}.guidat-controller.boolean{border-left:5px solid #54396e}.guidat-controller.function{border-left:5px solid #e61d5f}.guidat-controller.number input[type=text]{width:35px;margin-left:5px;margin-right:2px;color:#00aeff}#guidat .guidat-controller.boolean input{margin-top:6px;margin-right:2px;font-size:20px}.guidat-controller:last-child{border-bottom:none;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.5);box-shadow:0 1px 3px rgba(0,0,0,0.5)}.guidat-propertyname{padding:5px;padding-top:7px;cursor:default;display:inline-block}.guidat-slider-bg:hover,.guidat-slider-bg.active{background-color:#444}.guidat-slider-bg:hover .guidat-slider-fg,.guidat-slider-bg.active .guidat-slider-fg{background-color:#52c8ff}.guidat-slider-bg{background-color:#222;cursor:ew-resize;width:40%;margin-top:2px;float:right;height:21px}.guidat-slider-fg{background-color:#00aeff;height:20px}";this.add=function(){if(!h){i("Make sure to call GUI.start() in the window.onload function");return}var n=arguments[0];var l=arguments[1];if(d(n,l)){i('Controller for "'+l+'" already added.');return}var q=n[l];if(q==undefined){i(n+' either has no property "'+l+'", or the property is inaccessible.');return}var p=typeof q;var o=j[p];if(o==undefined){i('Cannot create controller for data type "'+p+'"');return}var m=o.apply(this,arguments);if(!m){i('Error creating controller for "'+l+'".');return}b.appendChild(m.domElement);c.push(m);return m};var j={number:function(){return k(NumberController,arguments)},string:function(){return k(StringController,arguments)},"boolean":function(){return k(BooleanController,arguments)},"function":function(){return k(FunctionController,arguments)},};var d=function(m,l){for(var n in c){if(c[n].object==m&&c[n].propertyName==l){return true}}return false};var i=function(l){if(typeof console.log=="function"){console.error("[GUI ERROR] "+l)}};var k=function(m,l){function n(){return m.apply(this,l)}n.prototype=m.prototype;return new n()};this.domElement=null;var b;var h=false;var f=false;var e=300;this.start=function(){var l=document.createElement("style");l.setAttribute("type","text/css");l.innerHTML=a;document.getElementsByTagName("head")[0].appendChild(l);this.domElement=document.createElement("div");this.domElement.setAttribute("id","guidat");b=document.createElement("div");b.setAttribute("id","guidat-controllers");toggleButton=document.createElement("a");toggleButton.setAttribute("id","guidat-toggle");toggleButton.setAttribute("href","#");toggleButton.innerHTML="Show Controls";toggleButton.addEventListener("click",function(m){g.toggle();m.preventDefault()},false);this.domElement.appendChild(b);this.domElement.appendChild(toggleButton);this.domElement.style.marginTop=-e+"px";document.body.appendChild(this.domElement);h=true};this.toggle=function(){if(f){this.hide()}else{this.show()}};this.show=function(){this.domElement.style.marginTop=0+"px";toggleButton.innerHTML="Hide Controls";f=true};this.hide=function(){this.domElement.style.marginTop=-e+"px";toggleButton.innerHTML="Show Controls";f=false}};var Slider=function(a,e,j,c,i){var e=e;var j=j;var c=c;var h=false;var f=this;var k,l;this.domElement=document.createElement("div");this.fg=document.createElement("div");this.domElement.setAttribute("class","guidat-slider-bg");this.fg.setAttribute("class","guidat-slider-fg");this.domElement.appendChild(this.fg);var b=function(m,p,n,q,o){var m=q+(o-q)*((m-p)/(n-p));if(mo){m=o}}return m};var g=function(m){var n=curtop=0;if(m.offsetParent){do{n+=m.offsetLeft;curtop+=m.offsetTop}while(m=m.offsetParent);return[n,curtop]}};this.__defineSetter__("value",function(n){var m=b(n,e,j,0,100);this.fg.style.width=m+"%"});var d=function(m){if(!h){return}var o=g(f.domElement);var n=b(m.pageX,o[0],o[0]+f.domElement.offsetWidth,e,j);n=Math.round(n/c)*c;a.updateValue(n)};this.domElement.addEventListener("mousedown",function(m){h=true;k=l=m.pageX;f.domElement.setAttribute("class","guidat-slider-bg active");f.fg.setAttribute("class","guidat-slider-fg active");d(m)},false);document.addEventListener("mouseup",function(m){f.domElement.setAttribute("class","guidat-slider-bg");f.fg.setAttribute("class","guidat-slider-fg");h=false},false);document.addEventListener("mousemove",d,false);this.value=i};var Controller=function(){var a=null;this.setName=function(b){this.propertyNameElement.innerHTML=b};this.setValue=function(b){this.object[this.propertyName]=b;if(a!=null){a.call(this,b)}};this.getValue=function(){return this.object[this.propertyName]};this.onChange=function(b){a=b};this.makeUnselectable=function(b){b.onselectstart=function(){return false};b.style.MozUserSelect="none";b.style.KhtmlUserSelect="none";b.unselectable="on"};this.makeSelectable=function(b){b.onselectstart=function(){};b.style.MozUserSelect="auto";b.style.KhtmlUserSelect="auto";b.unselectable="off"};this.domElement=document.createElement("div");this.domElement.setAttribute("class","guidat-controller "+this.type);this.object=arguments[0];this.propertyName=arguments[1];this.propertyNameElement=document.createElement("span");this.propertyNameElement.setAttribute("class","guidat-propertyname");this.setName(this.propertyName);this.domElement.appendChild(this.propertyNameElement);this.makeUnselectable(this.domElement)};var BooleanController=function(){this.type="boolean";Controller.apply(this,arguments);var b=this;var a=document.createElement("input");a.setAttribute("type","checkbox");this.domElement.addEventListener("click",function(c){a.checked=!a.checked;c.preventDefault();b.setValue(a.checked)},false);a.addEventListener("mouseup",function(c){a.checked=!a.checked},false);this.domElement.style.cursor="pointer";this.propertyNameElement.style.cursor="pointer";this.domElement.appendChild(a)};BooleanController.prototype=new Controller();BooleanController.prototype.constructor=BooleanController;var FunctionController=function(){this.type="function";var a=this;Controller.apply(this,arguments);this.domElement.addEventListener("click",function(){a.object[a.propertyName].call(a.object)},false);this.domElement.style.cursor="pointer";this.propertyNameElement.style.cursor="pointer"};FunctionController.prototype=new Controller();FunctionController.prototype.constructor=FunctionController;var NumberController=function(){this.type="number";Controller.apply(this,arguments);var f=this;var a=false;var g=false;var i=py=0;var e=arguments[2];var j=arguments[3];var d=arguments[4];if(!d){if(e&&j){d=(j-e)*0.01}else{d=1}}var c=document.createElement("input");c.setAttribute("id",this.propertyName);c.setAttribute("type","text");c.setAttribute("value",this.getValue());if(d){c.setAttribute("step",d)}this.domElement.appendChild(c);var b;if(e!=undefined&&j!=undefined){b=new Slider(this,e,j,d,this.getValue());this.domElement.appendChild(b.domElement)}c.addEventListener("blur",function(k){var l=parseFloat(this.value);if(!isNaN(l)){f.updateValue(l)}else{this.value=f.getValue()}},false);c.addEventListener("mousewheel",function(k){k.preventDefault();this.updateValue(f.getValue()+Math.abs(k.wheelDeltaY)/k.wheelDeltaY*d);return false},false);c.addEventListener("mousedown",function(k){py=i=k.pageY;g=true;document.addEventListener("mousemove",h,false)},false);document.addEventListener("mouseup",function(k){document.removeEventListener("mousemove",h,false);f.makeSelectable(GUI.domElement);f.makeSelectable(c);if(g&&!a){c.focus();c.select()}a=false;g=false},false);if(navigator.appVersion.indexOf("chrome")!=-1){document.addEventListener("mouseout",function(k){document.removeEventListener("mousemove",h,false)},false)}var h=function(m){a=true;m.preventDefault();f.makeUnselectable(GUI.domElement);f.makeUnselectable(c);py=i;i=m.pageY;var k=py-i;var l=f.getValue()+k*d;f.updateValue(l);return false};this.updateValue=function(k){k=parseFloat(k);if(e!=undefined&&k<=e){k=e}else{if(j!=undefined&&k>=j){k=j}}f.setValue(k);c.value=f.getValue();if(b){b.value=f.getValue()}}};NumberController.prototype=new Controller();NumberController.prototype.constructor=NumberController;var StringController=function(){this.type="string";var c=this;Controller.apply(this,arguments);var b=document.createElement("input");var a=this.getValue();b.setAttribute("value",a);b.setAttribute("spellcheck","false");this.domElement.addEventListener("mouseup",function(){b.focus();b.select()},false);b.addEventListener("keyup",function(){c.setValue(b.value)},false);this.domElement.appendChild(b)};StringController.prototype=new Controller();StringController.prototype.constructor=StringController; \ No newline at end of file From 4dbb680cfa547dbaa176c84fbb4b6637d908eba0 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:21:01 -0700 Subject: [PATCH 19/54] changed file size on download link --- README.md | 2 +- index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d82136f..e81b17b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # gui-dat **gui-dat** is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly. -## Check the [index page](http://jonobr1.github.com/gui-dat/) for usage. +##Check the [index page](http://jonobr1.github.com/gui-dat/) for usage. Initiated by [George Michael Brower](http://georgemichaelbrower.com/) and [Jono Brandel](http://jonobr1.com/) of the Data Arts Team, Google Creative Lab. diff --git a/index.html b/index.html index c978c7f..b8d259c 100644 --- a/index.html +++ b/index.html @@ -59,7 +59,7 @@

    From 8ba92f76cd20b24f4d342a116d86ea391da6110e Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:27:06 -0700 Subject: [PATCH 20/54] cleaning up GUI-DAT to gui-dat --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index b8d259c..640ed6f 100644 --- a/index.html +++ b/index.html @@ -60,7 +60,7 @@

    Basic Usage

    From 554767fa70031de6266794b495cf922cbf5cd8c0 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Sun, 30 Jan 2011 16:03:09 -0700 Subject: [PATCH 21/54] totally resizeable :) --- controllers/controller.number.js | 6 +- demo/demo.js | 18 ++- gui.css | 33 ++-- gui.js | 257 ++++++++++++++++++++++++++----- index.html | 39 ++++- 5 files changed, 289 insertions(+), 64 deletions(-) diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 235e24a..da8b201 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -18,6 +18,8 @@ var NumberController = function() { var max = arguments[4]; var step = arguments[5]; + console.log("NumberController", this.propertyName, arguments); + if (!step) { if (min != undefined && max != undefined) { step = (max-min)*0.01; @@ -28,8 +30,6 @@ var NumberController = function() { var numberField = document.createElement('input'); numberField.setAttribute('id', this.propertyName); - - // Little up and down arrows are pissing me off. numberField.setAttribute('type', 'text'); numberField.setAttribute('value', this.getValue()); @@ -47,7 +47,7 @@ var NumberController = function() { numberField.addEventListener('blur', function(e) { var val = parseFloat(this.value); if (!isNaN(val)) { - _this.updateValue(val); + _this.updateDisplay(); } else { this.value = _this.getValue(); } diff --git a/demo/demo.js b/demo/demo.js index 5bea7e1..62eca6e 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -47,6 +47,7 @@ function FizzyText(message) { var textAscent = 82; var textOffsetLeft = 80; var noiseScale = 300; + var frameTime = 30; var colors = ["#00aeff", "#0fa954", "#54396e", "#e61d5f"]; @@ -146,8 +147,16 @@ function FizzyText(message) { // the createBitmap function. this.message = message; + var loop = function() { + // Don't render if we don't see it. + // Would be cleaner if I dynamically acquired the top of the canvas. + if (document.body.scrollTop < height + 20) { + render(); + } + } + // This calls the render function every 30 milliseconds. - setInterval(render, 30); + setInterval(loop, frameTime); // This class is responsible for drawing and moving those little // colored dots. @@ -196,7 +205,7 @@ function FizzyText(message) { this.x += Math.cos(angle) * _this.speed + this.vx; this.y += -Math.sin(angle) * _this.speed + this.vy; - this.r = constrain(this.r, 0, _this.maxSize); + this.r = GUI.constrain(this.r, 0, _this.maxSize); // If we're tiny, keep moving around until we find a black // pixel. @@ -215,10 +224,5 @@ function FizzyText(message) { } - var constrain = function (v, o1, o2) { - if (v < o1) v = o1; - else if (v > o2) v = o2; - return v; - } } diff --git a/gui.css b/gui.css index d035320..ba8ec75 100644 --- a/gui.css +++ b/gui.css @@ -1,34 +1,43 @@ #guidat { +position: fixed; +top: 0; +left: 0; +width: 100%; +z-index: 1001; +text-align: right; +} + +.guidat { color: #fff; - position: fixed; - width: 280px; - z-index: 200; opacity: 0.97; - top: 0; - left: 100%; - margin-left: -300px; + text-align: left; + float: right; + margin-right: 20px; + margin-bottom: 20px; background-color: #fff; -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); } -#guidat, -#guidat input { +.guidat, +.guidat input { font: 9.5px Lucida Grande, sans-serif; } -#guidat-controllers { +.guidat-controllers { height: 300px; overflow-y: auto; overflow-x: hidden; background-color: rgba(0,0,0,0.1); + /* -moz-transition: height .2s ease-out; -webkit-transition: height .2s ease-out; transition: height .2s ease-out; + */ } -#guidat-toggle { +a.guidat-toggle { text-decoration: none; cursor: pointer; color: #fff; @@ -39,7 +48,7 @@ } -#guidat-toggle:hover { +a.guidat-toggle:hover { background-color: #000; } @@ -112,7 +121,7 @@ width: 148px; color: #00aeff; } -#guidat .guidat-controller.boolean input { +.guidat .guidat-controller.boolean input { margin-top: 6px; margin-right: 2px; font-size: 20px; diff --git a/gui.js b/gui.js index 14ffc15..87603b5 100644 --- a/gui.js +++ b/gui.js @@ -2,40 +2,178 @@ var GUI = function() { var _this = this; + var MIN_WIDTH = 200; + var MAX_WIDTH = 500; + var controllers = []; var listening = []; var autoListen = true; + var listenInterval; - var _this = this, open = false, - controllers = [], controllersWatched = []; + + // Sum total of heights of controllers in this gui + var controllerHeight; + + var curControllerContainerHeight = 0; + + // How big we get when we open + var openHeight; + + var _this = this, open = false; + + var name; + var width = 280; + + var resizeTo = 0; + var resizeTimeout; this.domElement = document.createElement('div'); - this.domElement.setAttribute('id', 'guidat'); + this.domElement.setAttribute('class', 'guidat'); + this.domElement.style.width = width+'px' - controllerContainer = document.createElement('div'); - controllerContainer.setAttribute('id', 'guidat-controllers'); + var controllerContainer = document.createElement('div'); + controllerContainer.setAttribute('class', 'guidat-controllers'); - // @doob - // I think this is way more elegant than the negative margin. - // Only wish we didn't have to see the scrollbar on its way open. - // Any thoughts? controllerContainer.style.height = '0px'; - toggleButton = document.createElement('a'); - toggleButton.setAttribute('id', 'guidat-toggle'); + var toggleButton = document.createElement('a'); + toggleButton.setAttribute('class', 'guidat-toggle'); toggleButton.setAttribute('href', '#'); toggleButton.innerHTML = "Show Controls"; - toggleButton.addEventListener('click', function(e) { - _this.toggle(); - e.preventDefault(); - }, false); + + var toggleDragged = false; + var dragDisplacementY = 0; + var togglePressed = false; + + var my, pmy, mx, pmx; + + var resize = function(e) { + if (!open) { + open = true; + curControllerContainerHeight = openHeight = 0; + } + pmy = my; + pmx = mx; + my = e.pageY; + mx = e.pageX; + + var dmy = my - pmy; + // TODO: Flip this if you want to resize to the left. + var dmx = pmx - mx; + + if (dmy > 0 && + curControllerContainerHeight > controllerHeight) { + var d = GUI.map(curControllerContainerHeight, controllerHeight, controllerHeight + 100, 1, 0); + dmy *= Math.pow(d, 1.5); + } + toggleDragged = true; + dragDisplacementY += dmy; + dragDisplacementX += dmx; + openHeight += dmy; + width += dmx; + curControllerContainerHeight += dmy; + controllerContainer.style.height = openHeight+'px'; + width = GUI.constrain(width, MIN_WIDTH, MAX_WIDTH); + _this.domElement.style.width = width+'px'; + checkForOverflow(); + }; + + toggleButton.addEventListener('mousedown', function(e) { + pmy = my = e.pageY; + pmx = mx = e.pageX; + togglePressed = true; + e.preventDefault(); + dragDisplacementY = 0; + dragDisplacementX = 0; + document.addEventListener('mousemove', resize, false); + return false; + + }, false); + + + toggleButton.addEventListener('click', function(e) { + e.preventDefault(); + return false; + }, false); + + + document.addEventListener('mouseup', function(e) { + + + if (togglePressed && !toggleDragged) { + + _this.toggle(); + + // Clears lingering slider column + _this.domElement.style.width = (width+1)+'px'; + setTimeout(function() { + _this.domElement.style.width = width+'px'; + }, 1); + } + + if (togglePressed && toggleDragged) { + + if (dragDisplacementX == 0) { + + // Clears lingering slider column + _this.domElement.style.width = (width+1)+'px'; + setTimeout(function() { + _this.domElement.style.width = width+'px'; + }, 1); + + } + + if (openHeight > controllerHeight) { + + clearTimeout(resizeTimeout); + openHeight = resizeTo = controllerHeight; + beginResize(); + + } else if (controllerContainer.children.length >= 1) { + + var singleControllerHeight = controllerContainer.children[0].offsetHeight; + clearTimeout(resizeTimeout); + var target = Math.round(curControllerContainerHeight/singleControllerHeight)*singleControllerHeight-1; + resizeTo = target; + if (resizeTo <= 0) { + _this.hide(); + openHeight = singleControllerHeight*2; + console.log("HIDING, wTF"); + } else { + openHeight = resizeTo; + beginResize(); + } + } + + + + } + + + document.removeEventListener('mousemove', resize, false); + e.preventDefault(); + toggleDragged = false; + togglePressed = false; + + return false; + + }, false); + this.domElement.appendChild(controllerContainer); this.domElement.appendChild(toggleButton); - + if (GUI.autoPlace) { + if(GUI.autoPlaceContainer == null) { + GUI.autoPlaceContainer = document.createElement('div'); + GUI.autoPlaceContainer.setAttribute("id", "guidat"); + document.body.appendChild(GUI.autoPlaceContainer); + } + GUI.autoPlaceContainer.appendChild(this.domElement); + } + this.autoListenIntervalTime = 1000/60; var createListenInterval = function() { @@ -70,7 +208,6 @@ var GUI = function() { }; this.listen = function(whoToListenTo) { - var arr = whoToListenTo || listening; for (var i in arr) { arr[i].updateDisplay(); @@ -100,11 +237,6 @@ var GUI = function() { return false; }; - var error = function(str) { - if (typeof console.log == 'function') { - console.error("[GUI ERROR] " + str); - } - }; var construct = function(constructor, args) { function F() { @@ -121,15 +253,15 @@ var GUI = function() { // Have we already added this? if (alreadyControlled(object, propertyName)) { - error("Controller for \"" + propertyName+"\" already added."); - return; + // GUI.error("Controller for \"" + propertyName+"\" already added."); + // return; } var value = object[propertyName]; // Does this value exist? Is it accessible? if (value == undefined) { - error(object + " either has no property \""+propertyName+"\", or the property is inaccessible."); + GUI.error(object + " either has no property \""+propertyName+"\", or the property is inaccessible."); return; } @@ -138,11 +270,11 @@ var GUI = function() { // Do we know how to deal with this data type? if (handler == undefined) { - error("Cannot create controller for data type \""+type+"\""); + GUI.error("Cannot create controller for data type \""+type+"\""); return; } - var args = [_this]; // Set first arg (parent) to this + var args = [this]; // Set first arg (parent) to this for (var j = 0; j < arguments.length; j++) { args.push(arguments[j]); } @@ -151,7 +283,7 @@ var GUI = function() { // Were we able to make the controller? if (!controllerObject) { - error("Error creating controller for \""+propertyName+"\"."); + GUI.error("Error creating controller for \""+propertyName+"\"."); return; } @@ -159,10 +291,30 @@ var GUI = function() { controllerContainer.appendChild(controllerObject.domElement); controllers.push(controllerObject); + // Compute sum height of controllers. + controllerHeight = 0; + for (var i in controllers) { + controllerHeight += controllers[i].domElement.offsetHeight; + } + + openHeight = controllerHeight; + + checkForOverflow(); + + + return controllerObject; } + var checkForOverflow = function() { + if (controllerHeight - 1 > openHeight) { + controllerContainer.style.overflowY = "auto"; + } else { + controllerContainer.style.overflowY = "hidden"; + } + } + var addHandlers = { "number": NumberController, "string": StringController, @@ -180,12 +332,6 @@ var GUI = function() { return false; }; - var error = function(str) { - if (typeof console.log == 'function') { - console.error("[GUI ERROR] " + str); - } - }; - var construct = function(constructor, args) { function F() { return constructor.apply(this, args); @@ -203,19 +349,43 @@ var GUI = function() { }; this.show = function() { - controllerContainer.style.height = '300px'; - toggleButton.innerHTML = "Hide Controls"; + toggleButton.innerHTML = name || "Hide Controls"; + resizeTo = openHeight; + clearTimeout(resizeTimeout); + beginResize(); open = true; } this.hide = function() { - controllerContainer.style.height = '0px'; - toggleButton.innerHTML = "Show Controls"; + toggleButton.innerHTML = name || "Show Controls"; + resizeTo = 0; + clearTimeout(resizeTimeout); + beginResize(); open = false; } + + this.name = function(n) { + name = n; + toggleButton.innerHTML = n; + } + + var beginResize = function() { + //console.log("Resizing from " + curControllerContainerHeight + " to " + resizeTo); + curControllerContainerHeight += (resizeTo - curControllerContainerHeight)*0.6; + if (Math.abs(curControllerContainerHeight-resizeTo) < 1) { + curControllerContainerHeight = resizeTo; + } else { + resizeTimeout = setTimeout(beginResize, 1000/30); + } + controllerContainer.style.height = Math.round(curControllerContainerHeight)+'px'; + + } }; +GUI.autoPlace = true; +GUI.autoPlaceContainer = null; + // Util functions GUI.makeUnselectable = function(elem) { @@ -234,7 +404,18 @@ GUI.makeSelectable = function(elem) { GUI.map = function(v, i1, i2, o1, o2) { var v = o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); + return v; +} + +GUI.constrain = function (v, o1, o2) { if (v < o1) v = o1; else if (v > o2) v = o2; return v; } + +GUI.error = function(str) { + if (typeof console.log == 'function') { + console.GUI.error("[GUI ERROR] " + str); + } +}; + diff --git a/index.html b/index.html index 640ed6f..86be472 100644 --- a/index.html +++ b/index.html @@ -26,7 +26,6 @@ var fizzyText = new FizzyText("gui-dat"); var gui = new GUI(); - document.body.appendChild( gui.domElement ); // Text field gui.add(fizzyText, "message"); @@ -72,7 +71,6 @@ window.onload = function() { var fizzyText = new FizzyText("gui-dat"); var gui = new GUI(); - document.body.appendChild( gui.domElement ); // Text field gui.add(fizzyText, "message"); @@ -108,13 +106,13 @@ window.onload = function() {

    Listen for variable changes outside of the GUI

    Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method.

    -
    gui.add(obj, "propName").listen();
    +
    gui.add(obj, "changingProperty").listen();

    Advanced listening

    By default, gui-dat will create an internal interval that checks for changes in the values you've marked with listen(). If you'd like to check for these changes in an interval of your own definition, use the following:

     gui.autoListen = false; // disables internal interval
    -gui.add(obj, "propName").listen();
    +gui.add(obj, "changingProperty").listen();
     
     // Make your own loop
     setInterval(function() {
    @@ -133,6 +131,39 @@ setInterval(function() {
     	gui.listenAll(); // updates ALL values managed by this gui
     }, 1000 / 60);
     
    +
    +

    Multiple panels and custom placement

    +

    You can instantiate multiple GUI objects and name them however you'd like.

    +
    +var gui1 = new GUI();
    +var gui2 = new GUI();
    +
    +// The name function overwrites the "Show Controls" text.
    +gui1.name("Utilities");
    +gui2.name("Camera Placement");
    +
    +

    By default, gui-dat panels will be automatically added to the HTML document and fixed to the top of the screen. You can disable this behavior / styling and append the gui DOM element to a container of your choosing.

    +
    // Notice this belongs to the GUI class (uppercase) 
    +// and not an instance thereof.
    +GUI.autoPlace = false; 
    +
    +var gui = new GUI();
    +
    +// Do some custom styles ...
    +gui.domElement.style.position = "absolute";
    +gui.domElement.style.top = "20px";
    +gui.domElement.style.left = "20px";
    +
    +document.getElementById("my-gui-container").appendChild( gui.domElement );
    +
    + From 5b38f59def8d929f874c1dd0fc586b6b4a3aa00e Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Sun, 30 Jan 2011 23:53:33 -0500 Subject: [PATCH 22/54] Lots of saving goodness though a few things left to be done / tested. Started to add collapsable sections on demo headers. Won't be stable enough by tomorrow morning. --- controllers/controller.number.js | 2 - demo/demo.css | 41 ++++- gui.css | 3 - gui.js | 96 ++++++++++- index.html | 288 ++++++++++++++++++++----------- 5 files changed, 314 insertions(+), 116 deletions(-) diff --git a/controllers/controller.number.js b/controllers/controller.number.js index da8b201..495577c 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -18,8 +18,6 @@ var NumberController = function() { var max = arguments[4]; var step = arguments[5]; - console.log("NumberController", this.propertyName, arguments); - if (!step) { if (min != undefined && max != undefined) { step = (max-min)*0.01; diff --git a/demo/demo.css b/demo/demo.css index f4fb66b..1191128 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -28,7 +28,7 @@ h1 { font-weight: 800; text-transform: lowercase; line-height: 80px; - margin: 20px 0 20px 0; + margin: 39px 0 20px 0; } h1 a:link, h1 a:visited, h1 a:hover, h1 a:active { @@ -48,6 +48,37 @@ h2 { margin-bottom: 24px; } + +h2.collapsed { + + float: left; + clear: both; + padding-top:24px; + margin-top: 0; + border-top: 1px solid #ccc; + width: 100%; +cursor: pointer; +} +h2.collapsed:before { +content: '+'; +font-weight: normal; +line-height: 2px; +float: left; +margin-top: 6px; +margin-right: 6px; +font-size: 9px; +font-family: Monaco, monospace; +} +h2.collapsed:hover:before { +color: red; +} + +.collapsable { +clear: both; + +display: none; +} + #helvetica-demo { position: absolute; left: 0; @@ -74,16 +105,18 @@ pre { background-color: #222; max-width: 500px; font: 10px Monaco, monospace; + clear: both; } -p, ul { +p, ul, ol { font-size: 125%; + clear: both; line-height: 18px; margin-bottom: 24px; } li { - margin-left: 18px; + margin-left: 22px; } ul#desc { @@ -112,6 +145,8 @@ footer { background-color: #eee; width: 510px; padding: 10px; + clear: both; + } pre a:link, diff --git a/gui.css b/gui.css index ba8ec75..c06bbc3 100644 --- a/gui.css +++ b/gui.css @@ -15,9 +15,6 @@ text-align: right; margin-right: 20px; margin-bottom: 20px; background-color: #fff; - -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); - box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); } .guidat, diff --git a/gui.js b/gui.js index 87603b5..7eb4a01 100644 --- a/gui.js +++ b/gui.js @@ -1,3 +1,6 @@ + + + var GUI = function() { var _this = this; @@ -60,15 +63,16 @@ var GUI = function() { mx = e.pageX; var dmy = my - pmy; + // TODO: Flip this if you want to resize to the left. var dmx = pmx - mx; if (dmy > 0 && curControllerContainerHeight > controllerHeight) { var d = GUI.map(curControllerContainerHeight, controllerHeight, controllerHeight + 100, 1, 0); - dmy *= Math.pow(d, 1.5); - + dmy *= d; } + toggleDragged = true; dragDisplacementY += dmy; dragDisplacementX += dmx; @@ -290,7 +294,16 @@ var GUI = function() { // Success. controllerContainer.appendChild(controllerObject.domElement); controllers.push(controllerObject); + GUI.allControllers.push(controllerObject); + // Do we have a saved value for this controller? + if (type != "function" && + GUI.saveIndex < GUI.savedValues.length) { + controllerObject.setValue(GUI.savedValues[GUI.saveIndex]); + GUI.saveIndex++; + } + + // Compute sum height of controllers. controllerHeight = 0; for (var i in controllers) { @@ -300,9 +313,6 @@ var GUI = function() { openHeight = controllerHeight; checkForOverflow(); - - - return controllerObject; } @@ -383,8 +393,83 @@ var GUI = function() { }; +// Static members + GUI.autoPlace = true; GUI.autoPlaceContainer = null; +GUI.allControllers = []; + +GUI.saveURL = function() { + title = window.location; + url = GUI.replaceGetVar("saveString", GUI.getSaveString()); + window.location = url; +}; + +GUI.load = function(saveString) { + GUI.savedValues = saveString.split(","); +}; + +GUI.savedValues = []; + +GUI.getSaveString = function() { + var s = ""; + var vals = []; + for (var i in GUI.allControllers) { + if (GUI.allControllers[i].type == "function") { + continue; + } + var v = GUI.allControllers[i].getValue(); + vals.push(v); + } + vals.join(','); + return vals; +} + +GUI.getSaveStringFromURL = function() { + + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split("=") + if (hash == undefined) continue; + if (hash[0] == "saveString") { + return hash[1]; + } + } + + return null; + +}; + +GUI.replaceGetVar = function(varName, val) { + + var vars = [], hash; + var loc = window.location.href; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + + + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split("=") + if (hash == undefined) continue; + if (hash[0] == varName) { + return loc.replace(hash[1], val); + } + } + + if (window.location.href.indexOf('?') != -1) { + return loc + "&"+varName+"="+val; + } + + return loc+"?"+varName+"="+val; + +}; + +GUI.saveIndex = 0; + +GUI.showSaveString = function() { + alert(GUI.getSaveString()); +} // Util functions @@ -419,3 +504,4 @@ GUI.error = function(str) { } }; +if (GUI.getSaveStringFromURL() != null) GUI.load(GUI.getSaveStringFromURL()); \ No newline at end of file diff --git a/index.html b/index.html index 86be472..062b5e1 100644 --- a/index.html +++ b/index.html @@ -1,126 +1,201 @@ - - - gui-dat - - + - - - - - - - - + + + + + gui-dat + + + + + + + + + + + + + + - - - + - // Boolean checkbox - gui.add(fizzyText, "displayOutline"); - - // Fires a function called "explode" - gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. + +
    + +
    - }; +
    - - - -
    -
    -
    -

    GUI-DAT flag

    -

    - gui-dat is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly. -

    +

    GUI-DAT flag

    - +

    gui-dat is a lightweight controller library for JavaScript. It allows you to easily manipulate variables and fire functions on the fly.

    -

    Basic Usage

    -
    <script type="text/javascript" src="demo/demo.js"></script>
    -<script type="text/javascript">
    +    
    +
    +    

    Basic Usage

    +
    +<script type="text/javascript" src="demo/demo.js"></script>
    +<script type="text/javascript">
     
     window.onload = function() {
     
    -   var fizzyText = new FizzyText("gui-dat");
    +   var fizzyText = new FizzyText("gui-dat");
     
        var gui = new GUI();
     
        // Text field
    -   gui.add(fizzyText, "message");
    +   gui.add(fizzyText, "message");
     
        // Sliders with min and max
    -   gui.add(fizzyText, "maxSize", 0.5, 7);
    -   gui.add(fizzyText, "growthSpeed", 0.01, 1);
    -   gui.add(fizzyText, "speed", 0.1, 2);
    +   gui.add(fizzyText, "maxSize", 0.5, 7);
    +   gui.add(fizzyText, "growthSpeed", 0.01, 1);
    +   gui.add(fizzyText, "speed", 0.1, 2);
     
        // Sliders with min, max and increment.
    -   gui.add(fizzyText, "noiseStrength", 10, 100, 5);
    +   gui.add(fizzyText, "noiseStrength", 10, 100, 5);
     
        // Boolean checkbox
    -   gui.add(fizzyText, "displayOutline");
    +   gui.add(fizzyText, "displayOutline");
     
    -   // Fires a function called "explode"
    -   gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name.
    +   // Fires a function called "explode"
    +   gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name.
     
     };
     
    -</script>
    +</script> +
    -
      -
    • gui-dat will infer the type of the property you're trying to add
      (based on its initial value) and create the corresponding control.
    • -
    • The properties must be public, i.e. defined by this.prop = value.
    • -
    -
    - -

    Fire a function when someone uses a control

    -
    gui.add(obj, "propName").onChange(function(n) {
    -	alert("You changed me to " + n);
    -});
    -
    -

    Listen for variable changes outside of the GUI

    -

    Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method.

    -
    gui.add(obj, "changingProperty").listen();
    -
    -

    Advanced listening

    -

    By default, gui-dat will create an internal interval that checks for changes in the values you've marked with listen(). If you'd like to check for these changes in an interval of your own definition, use the following: -

    +    
      +
    • gui-dat will infer the type of the property you're trying to add
      + (based on its initial value) and create the corresponding control.
    • + +
    • The properties must be public, i.e. defined by this.prop = value.
    • +
    + + + + +
    +

    The simplest way to save your parameters is via GUI.saveURL(). This method directs your browser to a URL containing the current GUI settings.

    +
    +// Make a button for the url function
    +gui.add(GUI, "saveURL");
    +
    + +
    + +
    +

    Let's say you'd like to share your settings with someone. Instead of sending a long link with lots of parameters stored in it, you can make your saved settings the defaults.

    + +

    First, add the method GUI.showSaveString() to a gui object:

    +
    +var gui = new GUI();
    +
    +// Add some stuff (and pretend I change their values);
    +gui.add(someObject, "someProperty");
    +gui.add(someObject, "someOtherProperty");
    +
    +// Make a save button.
    +gui.add(GUI, "showSaveString");
    +
    + +

    Clicking the "showSaveString" button bring up an alert with a string. Copy and paste that string into the method GUI.load() before you instantiate any gui objects.

    +
    +// Replace COPIED STRING with the value you got from 
    +GUI.load("COPIED STRING");
    +
    +var gui = new GUI();
    +
    +// Now these properties will be set to the values you just saved.
    +gui.add(someObject, "someProperty");
    +gui.add(someObject, "someOtherProperty");
    +
    + +

    Save strings won't work if you change the order in which you've added properties to your gui objects. If you want to add more parameters to your gui and use an old save string, make sure they're added after the properties whose values you've saved.

    +
    + + + +
    +

    Let's say you have a variable that changes by itself from time to time. If you'd like the GUI to reflect those changes, use the listen() method.

    +
    +gui.add(obj, "changingProperty").listen();
    +
    + +
    + +
    +

    By default, gui-dat will create an internal interval that checks for changes in the values you've marked with listen(). If you'd like to check for these changes in an interval of your own definition, use the following:

    +
     gui.autoListen = false; // disables internal interval
     gui.add(obj, "changingProperty").listen();
     
     // Make your own loop
     setInterval(function() {
    -	gui.listen(); // updates values you've marked with listen()
    +        gui.listen(); // updates values you've marked with listen()
     }, 1000 / 60);
     
    -

    Alternatively, you can forego calling listen() on individual controllers, and instead choose to monitor changes in all values controlled by your gui.

    -
    +
    +    

    Alternatively, you can forego calling listen() on individual controllers, and instead choose to monitor changes in all values controlled by your gui.

    +
     gui.autoListen = false; // disables internal interval
     gui.add(obj, "add");
     gui.add(obj, "lotsa");
    @@ -128,13 +203,16 @@ gui.add(obj, "properties");
     
     // Make your own loop
     setInterval(function() {
    -	gui.listenAll(); // updates ALL values managed by this gui
    +        gui.listenAll(); // updates ALL values managed by this gui
     }, 1000 / 60);
     
    -
    -

    Multiple panels and custom placement

    -

    You can instantiate multiple GUI objects and name them however you'd like.

    -
    +
    + + + +
    +

    You can instantiate multiple GUI objects and name them however you'd like.

    +
     var gui1 = new GUI();
     var gui2 = new GUI();
     
    @@ -142,8 +220,10 @@ var gui2 = new GUI();
     gui1.name("Utilities");
     gui2.name("Camera Placement");
     
    -

    By default, gui-dat panels will be automatically added to the HTML document and fixed to the top of the screen. You can disable this behavior / styling and append the gui DOM element to a container of your choosing.

    -
    // Notice this belongs to the GUI class (uppercase) 
    +
    +    

    By default, gui-dat panels will be automatically added to the HTML document and fixed to the top of the screen. You can disable this behavior / styling and append the gui DOM element to a container of your choosing.

    +
    +// Notice this belongs to the GUI class (uppercase) 
     // and not an instance thereof.
     GUI.autoPlace = false; 
     
    @@ -156,17 +236,19 @@ gui.domElement.style.left = "20px";
     
     document.getElementById("my-gui-container").appendChild( gui.domElement );
     
    - - -
    - +
    + + + +
    +
      +
    1. gui-dat panels are resizeable. Drag the toggle button.
    2. + +
    3. Press H to make panels invisible. Then press H to show them again.
    4. +
    + + +
    +
    + From ea585f0de45a04c3a20a5cfa8cc0c8032a7fdef3 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 10:47:07 -0500 Subject: [PATCH 23/54] Saving via URL is on lock. Almost done making it so that panel appearance is saved as well, but bugs with resizing afterwards. --- controllers/controller.boolean.js | 10 +++ controllers/controller.js | 9 ++ controllers/controller.number.js | 8 +- gui.js | 136 +++++++++++++++++++++++------- index.html | 4 +- 5 files changed, 128 insertions(+), 39 deletions(-) diff --git a/controllers/controller.boolean.js b/controllers/controller.boolean.js index f2e4607..8c52605 100644 --- a/controllers/controller.boolean.js +++ b/controllers/controller.boolean.js @@ -24,6 +24,16 @@ var BooleanController = function() { this.updateDisplay = function() { input.checked = _this.getValue(); }; + + + this.setValue = function(val) { + if (typeof val != "boolean") { + try { + val = eval(val); + } catch (e) {} + } + return Controller.prototype.setValue.call(this, val); + } }; BooleanController.prototype = new Controller(); diff --git a/controllers/controller.js b/controllers/controller.js index cd75609..59fdf29 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -4,6 +4,8 @@ var Controller = function() { this.object = arguments[1]; this.propertyName = arguments[2]; + if (arguments.length > 0) this.initialValue = this.propertyName[this.object]; + this.domElement = document.createElement('div'); this.domElement.setAttribute('class', 'guidat-controller ' + this.type); @@ -23,12 +25,19 @@ Controller.prototype.name = function(n) { return this; }; +Controller.prototype.reset = function() { + this.setValue(this.initialValue); + return this; +}; + Controller.prototype.listen = function() { this.parent.listenTo(this); + return this; } Controller.prototype.unlisten = function() { this.parent.unlistenTo(this); // <--- hasn't been implemented yet + return this; } Controller.prototype.setValue = function(n) { diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 495577c..37e35ad 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -53,7 +53,7 @@ var NumberController = function() { numberField.addEventListener('mousewheel', function(e) { e.preventDefault(); - this.updateValue(_this.getValue() + Math.abs(e.wheelDeltaY)/e.wheelDeltaY*step); + _this.setValue(_this.getValue() + Math.abs(e.wheelDeltaY)/e.wheelDeltaY*step); return false; }, false); @@ -95,10 +95,6 @@ var NumberController = function() { return false; } - var roundToDecimal = function(n, decimals) { - var t = Math.pow(10, decimals); - return Math.round(n*t)/t; - } this.setValue = function(val) { @@ -116,7 +112,7 @@ var NumberController = function() { } this.updateDisplay = function() { - numberField.value = roundToDecimal(_this.getValue(), 4); + numberField.value = GUI.roundToDecimal(_this.getValue(), 4); if (slider) slider.value = _this.getValue(); } }; diff --git a/gui.js b/gui.js index 7eb4a01..db6020a 100644 --- a/gui.js +++ b/gui.js @@ -1,11 +1,8 @@ - - - var GUI = function() { var _this = this; - var MIN_WIDTH = 200; + var MIN_WIDTH = 240; var MAX_WIDTH = 500; var controllers = []; @@ -15,19 +12,24 @@ var GUI = function() { var listenInterval; - // Sum total of heights of controllers in this gui var controllerHeight; var curControllerContainerHeight = 0; // How big we get when we open + + + var _this = this; + + + + var open = false; + var width = 280; + var explicitOpenHeight = false; var openHeight; - var _this = this, open = false; - var name; - var width = 280; var resizeTo = 0; var resizeTimeout; @@ -53,10 +55,6 @@ var GUI = function() { var my, pmy, mx, pmx; var resize = function(e) { - if (!open) { - open = true; - curControllerContainerHeight = openHeight = 0; - } pmy = my; pmx = mx; my = e.pageY; @@ -64,6 +62,18 @@ var GUI = function() { var dmy = my - pmy; + + if (!open) { + if (dmy > 0) { + open = true; + curControllerContainerHeight = openHeight = 1; + toggleButton.innerHTML = name || "Hide Controls"; + } else { + return; + } + } + + // TODO: Flip this if you want to resize to the left. var dmx = pmx - mx; @@ -145,7 +155,6 @@ var GUI = function() { if (resizeTo <= 0) { _this.hide(); openHeight = singleControllerHeight*2; - console.log("HIDING, wTF"); } else { openHeight = resizeTo; beginResize(); @@ -302,27 +311,27 @@ var GUI = function() { controllerObject.setValue(GUI.savedValues[GUI.saveIndex]); GUI.saveIndex++; } - - + // Compute sum height of controllers. - controllerHeight = 0; - for (var i in controllers) { - controllerHeight += controllers[i].domElement.offsetHeight; - } - + checkForOverflow(); + openHeight = controllerHeight; - checkForOverflow(); return controllerObject; } var checkForOverflow = function() { + controllerHeight = 0; + for (var i in controllers) { + controllerHeight += controllers[i].domElement.offsetHeight; + } if (controllerHeight - 1 > openHeight) { controllerContainer.style.overflowY = "auto"; } else { controllerContainer.style.overflowY = "hidden"; } + console.log(controllerHeight, openHeight); } var addHandlers = { @@ -350,7 +359,9 @@ var GUI = function() { return new F(); }; - + this.reset = function() { + // + } // GUI ... GUI @@ -379,6 +390,11 @@ var GUI = function() { toggleButton.innerHTML = n; } + // used in saveURL + this.appearanceVars = function() { + return [open, width, openHeight]; + } + var beginResize = function() { //console.log("Resizing from " + curControllerContainerHeight + " to " + resizeTo); curControllerContainerHeight += (resizeTo - curControllerContainerHeight)*0.6; @@ -388,9 +404,26 @@ var GUI = function() { resizeTimeout = setTimeout(beginResize, 1000/30); } controllerContainer.style.height = Math.round(curControllerContainerHeight)+'px'; - + checkForOverflow(); } + if (GUI.guiIndex < GUI.savedAppearanceVars.length) { + + width = parseInt(GUI.savedAppearanceVars[GUI.guiIndex][1]); + _this.domElement.style.width = width+"px"; + + openHeight = parseInt(GUI.savedAppearanceVars[GUI.guiIndex][2]); + + if (eval(GUI.savedAppearanceVars[GUI.guiIndex][0]) == true) { + // TODO: weirdness on open ... + this.show(); + } + + GUI.guiIndex++; + } + + GUI.allGuis.push(this); + }; // Static members @@ -398,6 +431,7 @@ var GUI = function() { GUI.autoPlace = true; GUI.autoPlaceContainer = null; GUI.allControllers = []; +GUI.allGuis = []; GUI.saveURL = function() { title = window.location; @@ -405,27 +439,60 @@ GUI.saveURL = function() { window.location = url; }; +// TODO: Not working in FF. GUI.load = function(saveString) { - GUI.savedValues = saveString.split(","); + GUI.savedAppearanceVars = []; + var vals = saveString.split(','); + var numGuis = parseInt(vals[0]); + var vv = vals.splice(1, vals.length-1); + var numGuis = vals[0]; + console.log(numGuis); + for (var i = 0; i < numGuis; i++) { + var appr = vv.splice(0, 3); + GUI.savedAppearanceVars.push(appr); + } + GUI.savedValues = vv; }; GUI.savedValues = []; +GUI.savedAppearanceVars = []; GUI.getSaveString = function() { - var s = ""; + var vals = []; + + vals.push(GUI.allGuis.length); + + for (var i in GUI.allGuis) { + var av = GUI.allGuis[i].appearanceVars(); + for (var j = 0; j <= GUI.allGuis.length; j++) { + vals.push(av[j]); + } + } + for (var i in GUI.allControllers) { + + // We don't save values for functions. if (GUI.allControllers[i].type == "function") { continue; } + var v = GUI.allControllers[i].getValue(); + + // Round numbers so they don't get enormous + if (GUI.allControllers[i].type == "number") { + v = GUI.roundToDecimal(v, 4); + } + vals.push(v); + } - vals.join(','); - return vals; + + return vals.join(','); + } -GUI.getSaveStringFromURL = function() { +GUI.getVarFromURL = function(v) { var vars = [], hash; var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); @@ -433,7 +500,7 @@ GUI.getSaveStringFromURL = function() { for (var i = 0; i < hashes.length; i++) { hash = hashes[i].split("=") if (hash == undefined) continue; - if (hash[0] == "saveString") { + if (hash[0] == v) { return hash[1]; } } @@ -448,7 +515,6 @@ GUI.replaceGetVar = function(varName, val) { var loc = window.location.href; var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); - for (var i = 0; i < hashes.length; i++) { hash = hashes[i].split("=") if (hash == undefined) continue; @@ -466,6 +532,7 @@ GUI.replaceGetVar = function(varName, val) { }; GUI.saveIndex = 0; +GUI.guiIndex = 0; GUI.showSaveString = function() { alert(GUI.getSaveString()); @@ -499,9 +566,14 @@ GUI.constrain = function (v, o1, o2) { } GUI.error = function(str) { - if (typeof console.log == 'function') { + if (typeof console.error == 'function') { console.GUI.error("[GUI ERROR] " + str); } }; -if (GUI.getSaveStringFromURL() != null) GUI.load(GUI.getSaveStringFromURL()); \ No newline at end of file +GUI.roundToDecimal = function(n, decimals) { + var t = Math.pow(10, decimals); + return Math.round(n*t)/t; +} + +if (GUI.getVarFromURL('saveString') != null) GUI.load(GUI.getVarFromURL('saveString')); \ No newline at end of file diff --git a/index.html b/index.html index 062b5e1..a5c0527 100644 --- a/index.html +++ b/index.html @@ -39,11 +39,13 @@ var fizzyText = new FizzyText("gui-dat"); - //GUI.load("changed,3.2,0.10890000000000001,1.121,45,true"); var gui = new GUI(); + var gui2 = new GUI(); + // Text field gui.add(fizzyText, "message"); + gui2.add(window, "onload"); // Sliders with min and max gui.add(fizzyText, "maxSize", 0.5, 7); From 0a220426e98f31f52ff5c72d60401929c271a779 Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 12:21:14 -0800 Subject: [PATCH 24/54] updated index to handle toggling of documentation and also css fix to gui.css --- demo/demo.css | 47 +++++---- demo/demo.js | 1 - gui.css | 4 +- gui.js | 4 +- index.html | 262 ++++++++++++++++++++++++++++++-------------------- 5 files changed, 193 insertions(+), 125 deletions(-) diff --git a/demo/demo.css b/demo/demo.css index 1191128..ae91c79 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -48,8 +48,7 @@ h2 { margin-bottom: 24px; } - -h2.collapsed { +div.collapsed h2, div.expanded h2 { float: left; clear: both; @@ -57,27 +56,39 @@ h2.collapsed { margin-top: 0; border-top: 1px solid #ccc; width: 100%; -cursor: pointer; + cursor: pointer; } -h2.collapsed:before { -content: '+'; -font-weight: normal; -line-height: 2px; -float: left; -margin-top: 6px; -margin-right: 6px; -font-size: 9px; -font-family: Monaco, monospace; +div.expanded h2:before { + content: '-'; } -h2.collapsed:hover:before { -color: red; +div.collapsed h2:before { + content: '+'; +} +div.expanded h2:before, div.collapsed h2:before { + font-weight: normal; + line-height: 2px; + float: left; + margin-top: 6px; + margin-right: 6px; + font-size: 9px; + font-family: Monaco, monospace; +} +div.collapsed:hover h2:before, div.expanded:hover h2:before { + color: red; } -.collapsable { -clear: both; - -display: none; +div.collapsed .collapsable { + overflow: hidden; + clear: both; + height: 0; } +div.expanded .collapsable { + overflow: hidden; + clear: both; + height: auto; +} + +div.expanded { cursor: pointer; } #helvetica-demo { position: absolute; diff --git a/demo/demo.js b/demo/demo.js index 62eca6e..e002bd1 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -224,5 +224,4 @@ function FizzyText(message) { } - } diff --git a/gui.css b/gui.css index c06bbc3..a3cb075 100644 --- a/gui.css +++ b/gui.css @@ -1,8 +1,8 @@ #guidat { position: fixed; top: 0; -left: 0; -width: 100%; +right: 0; +width: auto; z-index: 1001; text-align: right; } diff --git a/gui.js b/gui.js index db6020a..842638a 100644 --- a/gui.js +++ b/gui.js @@ -331,7 +331,7 @@ var GUI = function() { } else { controllerContainer.style.overflowY = "hidden"; } - console.log(controllerHeight, openHeight); + // console.log(controllerHeight, openHeight); } var addHandlers = { @@ -446,7 +446,7 @@ GUI.load = function(saveString) { var numGuis = parseInt(vals[0]); var vv = vals.splice(1, vals.length-1); var numGuis = vals[0]; - console.log(numGuis); + // console.log(numGuis); for (var i = 0; i < numGuis; i++) { var appr = vv.splice(0, 3); GUI.savedAppearanceVars.push(appr); diff --git a/index.html b/index.html index a5c0527..6962bb3 100644 --- a/index.html +++ b/index.html @@ -30,7 +30,7 @@ @@ -74,8 +121,10 @@
    +
    +

    GUI-DAT flag

    @@ -133,124 +182,133 @@ window.onload = function() {
    gui.add(obj, "propName").onChange(function(n) {
             alert("You changed me to " + n);
     });
    --> - - -
    -

    The simplest way to save your parameters is via GUI.saveURL(). This method directs your browser to a URL containing the current GUI settings.

    -
    -// Make a button for the url function
    -gui.add(GUI, "saveURL");
    -
    + + + + + + -
    - -
    -

    By default, gui-dat will create an internal interval that checks for changes in the values you've marked with listen(). If you'd like to check for these changes in an interval of your own definition, use the following:

    -
    -gui.autoListen = false; // disables internal interval
    -gui.add(obj, "changingProperty").listen();
    +	
    -

    Alternatively, you can forego calling listen() on individual controllers, and instead choose to monitor changes in all values controlled by your gui.

    -
    -gui.autoListen = false; // disables internal interval
    -gui.add(obj, "add");
    -gui.add(obj, "lotsa");
    -gui.add(obj, "properties");
    +	    	

    By default, gui-dat panels will be automatically added to the HTML document and fixed to the top of the screen. You can disable this behavior / styling and append the gui DOM element to a container of your choosing.

    +
    +	// Notice this belongs to the GUI class (uppercase) 
    +	// and not an instance thereof.
    +	GUI.autoPlace = false; 
     
    -// Make your own loop
    -setInterval(function() {
    -        gui.listenAll(); // updates ALL values managed by this gui
    -}, 1000 / 60);
    -
    -
    - + var gui = new GUI(); - -
    -

    You can instantiate multiple GUI objects and name them however you'd like.

    -
    -var gui1 = new GUI();
    -var gui2 = new GUI();
    +	// Do some custom styles ...
    +	gui.domElement.style.position = "absolute";
    +	gui.domElement.style.top = "20px";
    +	gui.domElement.style.left = "20px";
     
    -// The name function overwrites the "Show Controls" text.
    -gui1.name("Utilities");
    -gui2.name("Camera Placement");
    -
    - -

    By default, gui-dat panels will be automatically added to the HTML document and fixed to the top of the screen. You can disable this behavior / styling and append the gui DOM element to a container of your choosing.

    -
    -// Notice this belongs to the GUI class (uppercase) 
    -// and not an instance thereof.
    -GUI.autoPlace = false; 
    -
    -var gui = new GUI();
    -
    -// Do some custom styles ...
    -gui.domElement.style.position = "absolute";
    -gui.domElement.style.top = "20px";
    -gui.domElement.style.left = "20px";
    -
    -document.getElementById("my-gui-container").appendChild( gui.domElement );
    -
    -
    - - - -
    -
      -
    1. gui-dat panels are resizeable. Drag the toggle button.
    2. - -
    3. Press H to make panels invisible. Then press H to show them again.
    4. -
    - - + document.getElementById("my-gui-container").appendChild( gui.domElement ); + +
    - + + + + From 109474c99ca5fc941dc8a9d12115e3d40438d2a9 Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 12:25:57 -0800 Subject: [PATCH 25/54] added key event up and down arrows to controller.number.js --- controllers/controller.number.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 37e35ad..8f0a7a2 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -62,6 +62,20 @@ var NumberController = function() { clickedNumberField = true; document.addEventListener('mousemove', dragNumberField, false); }, false); + + // Handle up arrow and down arrow + numberField.addEventListener('keyup', function(e) { + switch(e.keyCode) { + case 38: // up + var newVal = _this.getValue() + step; + _this.setValue(newVal); + break; + case 40: // down + var newVal = _this.getValue() - step; + _this.setValue(newVal); + break; + } + }, false); document.addEventListener('mouseup', function(e) { document.removeEventListener('mousemove', dragNumberField, false); From c3fd69b95aaa9079df81f47705bcb2090fe34b7b Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 12:28:18 -0800 Subject: [PATCH 26/54] changed keyEvent from keyup to keydown --- controllers/controller.number.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 8f0a7a2..3f8e3fb 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -64,7 +64,7 @@ var NumberController = function() { }, false); // Handle up arrow and down arrow - numberField.addEventListener('keyup', function(e) { + numberField.addEventListener('keydown', function(e) { switch(e.keyCode) { case 38: // up var newVal = _this.getValue() + step; From a960a0d1ca440fa79b749875fb969d8a91c8d6fb Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 18:15:29 -0500 Subject: [PATCH 27/54] Working on string controller --- controllers/controller.string.js | 1 + demo/demo.css | 12 ++++++++---- gui.js | 14 +++++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/controllers/controller.string.js b/controllers/controller.string.js index 7d5d4d7..57cb832 100644 --- a/controllers/controller.string.js +++ b/controllers/controller.string.js @@ -17,6 +17,7 @@ var StringController = function() { input.select(); }, false); + // TODO: getting messed up on ctrl a input.addEventListener('keyup', function() { _this.setValue(input.value); }, false); diff --git a/demo/demo.css b/demo/demo.css index 1191128..9579001 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -48,14 +48,18 @@ h2 { margin-bottom: 24px; } +h2.collapsed { + padding-top:24px; + border-top: 1px solid #ccc; + margin-top: 0; + } + +/* h2.collapsed { float: left; clear: both; - padding-top:24px; - margin-top: 0; - border-top: 1px solid #ccc; width: 100%; cursor: pointer; } @@ -77,7 +81,7 @@ color: red; clear: both; display: none; -} +}*/ #helvetica-demo { position: absolute; diff --git a/gui.js b/gui.js index db6020a..9291dc3 100644 --- a/gui.js +++ b/gui.js @@ -26,6 +26,9 @@ var GUI = function() { var open = false; var width = 280; + + // Prevents checkForOverflow bug in which loaded gui appearance + // settings are not respected by presence of scrollbar. var explicitOpenHeight = false; var openHeight; @@ -315,7 +318,11 @@ var GUI = function() { // Compute sum height of controllers. checkForOverflow(); - openHeight = controllerHeight; + // Prevents checkForOverflow bug in which loaded gui appearance + // settings are not respected by presence of scrollbar. + if (!explicitOpenHeight) { + openHeight = controllerHeight; + } return controllerObject; @@ -406,6 +413,8 @@ var GUI = function() { controllerContainer.style.height = Math.round(curControllerContainerHeight)+'px'; checkForOverflow(); } + + // Load saved appearance: if (GUI.guiIndex < GUI.savedAppearanceVars.length) { @@ -413,9 +422,8 @@ var GUI = function() { _this.domElement.style.width = width+"px"; openHeight = parseInt(GUI.savedAppearanceVars[GUI.guiIndex][2]); - + explicitOpenHeight = true; if (eval(GUI.savedAppearanceVars[GUI.guiIndex][0]) == true) { - // TODO: weirdness on open ... this.show(); } From b1631b0327a4c2ec08d22e1673eb08704e8b4bfb Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 15:50:06 -0800 Subject: [PATCH 28/54] added unListenTo method --- gui.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gui.js b/gui.js index 842638a..3d9be28 100644 --- a/gui.js +++ b/gui.js @@ -217,7 +217,13 @@ var GUI = function() { }; this.unlistenTo = function(controller) { - // TODO + // TODO: test this + for(var i = 0; i < listening.length; i++) { + if(listening[i] == controller) listening.splice(i, 1); + } + if(listening.length <= 0) { + clearInterval(listenInterval); + } }; this.listen = function(whoToListenTo) { From 84472b9b77522f41190b61d08964166d065c8868 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 20:24:30 -0500 Subject: [PATCH 29/54] typo --- gui.js | 3 --- index.html | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/gui.js b/gui.js index f87afab..4d47fe1 100644 --- a/gui.js +++ b/gui.js @@ -438,7 +438,6 @@ var GUI = function() { }, 0); if (GUI.scrollTop > -1) { - console.log("hey"); document.body.scrollTop = GUI.scrollTop; } resizeTo = openHeight; @@ -470,11 +469,9 @@ GUI.scrollTop = -1; // TODO: Not working in FF. GUI.load = function(saveString) { - console.log(saveString); //GUI.savedAppearanceVars = []; var vals = saveString.split(","); - console.log(vals); var numGuis = parseInt(vals[0]); GUI.scrollTop = parseInt(vals[1]); for (var i = 0; i < numGuis; i++) { diff --git a/index.html b/index.html index 1a2578b..9941152 100644 --- a/index.html +++ b/index.html @@ -139,7 +139,7 @@

    Basic Usage

    -<script type="text/javascript" src="demo/demo.js"></script>
    +<script type="text/javascript" src="gui.min.js"></script>
     <script type="text/javascript">
     
     window.onload = function() {
    @@ -210,7 +210,7 @@ gui.add(GUI, "showSaveString");

    Clicking the "showSaveString" button bring up an alert with a string. Copy and paste that string into the method GUI.load() before you instantiate any gui objects.

    -// Replace COPIED STRING with the value you got from 
    +// Replace COPIED STRING with the value you got from showSaveString()
     GUI.load("COPIED STRING");
     
     var gui = new GUI();
    @@ -219,7 +219,7 @@ var gui = new GUI();
     gui.add(someObject, "someProperty");
     gui.add(someObject, "someOtherProperty");
    -

    Save strings won't work if you change the order in which you've added properties to your gui objects. If you want to add more parameters to your gui and use an old save string, make sure they're added after the properties whose values you've saved.

    +

    Save strings won't work if you change the order in which you've added properties to your gui objects, or the order of the gui objects themselves.. If you want to add more parameters to your gui and use an old save string, make sure they're added after the properties whose values you've saved.

    @@ -290,7 +290,7 @@ document.getElementById("my-gui-container").appendChild( gui.domElement );

    Pro tips.

      -
    1. gui-dat panels are resizeable. Drag the toggle button.
    2. +
    3. gui-dat panels are resizeable. Drag the show/hide button.
    4. Press H to make panels invisible. Then press H to show them again.
    From 45743a5f1a00f037ea4ad9f8af30802dc455d335 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 20:42:22 -0500 Subject: [PATCH 30/54] typo --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 9941152..00632bf 100644 --- a/index.html +++ b/index.html @@ -292,7 +292,7 @@ document.getElementById("my-gui-container").appendChild( gui.domElement );
    1. gui-dat panels are resizeable. Drag the show/hide button.
    2. -
    3. Press H to make panels invisible. Then press H to show them again.
    4. +
    5. Pro tip #2 forthcoming.
    From d099440e0ee2c6b5e806a889844b040777119942 Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 19:06:34 -0800 Subject: [PATCH 31/54] fixed the firefox horizontal issue --- controllers/controller.js | 2 +- gui.css | 17 +++++++++++------ gui.js | 24 ++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/controllers/controller.js b/controllers/controller.js index 59fdf29..c785d53 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -36,7 +36,7 @@ Controller.prototype.listen = function() { } Controller.prototype.unlisten = function() { - this.parent.unlistenTo(this); // <--- hasn't been implemented yet + this.parent.unlistenTo(this); // <--- hasn't been tested yet return this; } diff --git a/gui.css b/gui.css index a3cb075..d33d588 100644 --- a/gui.css +++ b/gui.css @@ -1,10 +1,15 @@ #guidat { -position: fixed; -top: 0; -right: 0; -width: auto; -z-index: 1001; -text-align: right; + position: fixed; + top: 0; + right: 0; + width: auto; + z-index: 1001; + text-align: right; +} + +.guidat * { + padding: 0px; + margin: 0px; } .guidat { diff --git a/gui.js b/gui.js index f87afab..b14aa5c 100644 --- a/gui.js +++ b/gui.js @@ -37,11 +37,31 @@ var GUI = function() { this.domElement = document.createElement('div'); this.domElement.setAttribute('class', 'guidat'); - this.domElement.style.width = width+'px' + this.domElement.style.width = width+'px'; var controllerContainer = document.createElement('div'); controllerContainer.setAttribute('class', 'guidat-controllers'); + // Firefox hack for horizontal scrolling + controllerContainer.addEventListener('DOMMouseScroll', function(e) { + + var scrollAmount = this.scrollTop; + + if (e.wheelDelta) { + scrollAmount+=e.wheelDelta; + } else if (e.detail) { + scrollAmount+=e.detail; + } + + if (e.preventDefault) { + e.preventDefault(); + } + e.returnValue = false; + + controllerContainer.scrollTop = scrollAmount; + + }, false); + controllerContainer.style.height = '0px'; var toggleButton = document.createElement('a'); @@ -117,7 +137,6 @@ var GUI = function() { document.addEventListener('mouseup', function(e) { - if (togglePressed && !toggleDragged) { _this.toggle(); @@ -183,6 +202,7 @@ var GUI = function() { if(GUI.autoPlaceContainer == null) { GUI.autoPlaceContainer = document.createElement('div'); GUI.autoPlaceContainer.setAttribute("id", "guidat"); + document.body.appendChild(GUI.autoPlaceContainer); } GUI.autoPlaceContainer.appendChild(this.domElement); From f23464c58c2f45109df21459035a51f4bfe9fe66 Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 19:09:32 -0800 Subject: [PATCH 32/54] removed extraneous styles --- gui.css | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gui.css b/gui.css index d33d588..f05ca69 100644 --- a/gui.css +++ b/gui.css @@ -7,11 +7,6 @@ text-align: right; } -.guidat * { - padding: 0px; - margin: 0px; -} - .guidat { color: #fff; opacity: 0.97; From 548f0fa3d22a1c31ec49f7be479abbd0818292eb Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Tue, 1 Feb 2011 13:45:22 -0500 Subject: [PATCH 33/54] Moved Controller classes to GUI namespace --- controllers/controller.boolean.js | 9 +++-- controllers/controller.function.js | 7 ++-- controllers/controller.js | 20 +++++------ controllers/controller.number.js | 9 +++-- controllers/controller.string.js | 7 ++-- demo/demo.css | 6 ++-- gui.js | 55 +++++++++++++----------------- index.html | 12 ++----- 8 files changed, 52 insertions(+), 73 deletions(-) diff --git a/controllers/controller.boolean.js b/controllers/controller.boolean.js index 8c52605..66808ca 100644 --- a/controllers/controller.boolean.js +++ b/controllers/controller.boolean.js @@ -1,7 +1,7 @@ -var BooleanController = function() { +GUI.BooleanController = function() { this.type = "boolean"; - Controller.apply(this, arguments); + GUI.Controller.apply(this, arguments); var _this = this; var input = document.createElement('input'); @@ -32,9 +32,8 @@ var BooleanController = function() { val = eval(val); } catch (e) {} } - return Controller.prototype.setValue.call(this, val); + return GUI.Controller.prototype.setValue.call(this, val); } }; -BooleanController.prototype = new Controller(); -BooleanController.prototype.constructor = BooleanController; +GUI.extendController(GUI.BooleanController); \ No newline at end of file diff --git a/controllers/controller.function.js b/controllers/controller.function.js index c95c5ec..bf17507 100644 --- a/controllers/controller.function.js +++ b/controllers/controller.function.js @@ -1,12 +1,11 @@ -var FunctionController = function() { +GUI.FunctionController = function() { this.type = "function"; var that = this; - Controller.apply(this, arguments); + GUI.Controller.apply(this, arguments); this.domElement.addEventListener('click', function() { that.object[that.propertyName].call(that.object); }, false); this.domElement.style.cursor = "pointer"; this.propertyNameElement.style.cursor = "pointer"; }; -FunctionController.prototype = new Controller(); -FunctionController.prototype.constructor = FunctionController; +GUI.extendController(GUI.FunctionController); diff --git a/controllers/controller.js b/controllers/controller.js index c785d53..aedbc46 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -1,4 +1,4 @@ -var Controller = function() { +GUI.Controller = function() { this.parent = arguments[0]; this.object = arguments[1]; @@ -18,29 +18,29 @@ var Controller = function() { }; -Controller.prototype.changeFunction = null; +GUI.Controller.prototype.changeFunction = null; -Controller.prototype.name = function(n) { +GUI.Controller.prototype.name = function(n) { this.propertyNameElement.innerHTML = n; return this; }; -Controller.prototype.reset = function() { +GUI.Controller.prototype.reset = function() { this.setValue(this.initialValue); return this; }; -Controller.prototype.listen = function() { +GUI.Controller.prototype.listen = function() { this.parent.listenTo(this); return this; } -Controller.prototype.unlisten = function() { +GUI.Controller.prototype.unlisten = function() { this.parent.unlistenTo(this); // <--- hasn't been tested yet return this; } -Controller.prototype.setValue = function(n) { +GUI.Controller.prototype.setValue = function(n) { this.object[this.propertyName] = n; if (this.changeFunction != null) { this.changeFunction.call(this, n); @@ -51,13 +51,13 @@ Controller.prototype.setValue = function(n) { return this; } -Controller.prototype.getValue = function() { +GUI.Controller.prototype.getValue = function() { return this.object[this.propertyName]; } -Controller.prototype.updateDisplay = function() {} +GUI.Controller.prototype.updateDisplay = function() {} -Controller.prototype.onChange = function(fnc) { +GUI.Controller.prototype.onChange = function(fnc) { this.changeFunction = fnc; return this; } diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 3f8e3fb..24a8582 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -1,8 +1,8 @@ -var NumberController = function() { +GUI.NumberController = function() { this.type = "number"; - Controller.apply(this, arguments); + GUI.Controller.apply(this, arguments); var _this = this; @@ -121,7 +121,7 @@ var NumberController = function() { val = max; } - return Controller.prototype.setValue.call(this, val); + return GUI.Controller.prototype.setValue.call(this, val); } @@ -131,5 +131,4 @@ var NumberController = function() { } }; -NumberController.prototype = new Controller(); -NumberController.prototype.constructor = NumberController; +GUI.extendController(GUI.NumberController); diff --git a/controllers/controller.string.js b/controllers/controller.string.js index 57cb832..d29804d 100644 --- a/controllers/controller.string.js +++ b/controllers/controller.string.js @@ -1,9 +1,9 @@ -var StringController = function() { +GUI.StringController = function() { this.type = "string"; var _this = this; - Controller.apply(this, arguments); + GUI.Controller.apply(this, arguments); var input = document.createElement('input'); @@ -30,5 +30,4 @@ var StringController = function() { }; -StringController.prototype = new Controller(); -StringController.prototype.constructor = StringController; +GUI.extendController(GUI.StringController); \ No newline at end of file diff --git a/demo/demo.css b/demo/demo.css index 966a9ad..9e5ce3d 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -66,10 +66,6 @@ div.collapsed h2, div.expanded h2 { width: 100%; cursor: pointer; } -h2.last { -border-bottom: 1px dotted #ccc; -margin-bottom: 20px; -} div.expanded h2:before { content: '-'; @@ -162,10 +158,12 @@ a:active { } footer { +margin-top: 20px; background-color: #eee; width: 510px; padding: 10px; clear: both; + color: #444; } diff --git a/gui.js b/gui.js index 326ed84..b2c317d 100644 --- a/gui.js +++ b/gui.js @@ -17,9 +17,6 @@ var GUI = function() { var curControllerContainerHeight = 0; - // How big we get when we open - - var _this = this; var open = false; @@ -28,6 +25,8 @@ var GUI = function() { // Prevents checkForOverflow bug in which loaded gui appearance // settings are not respected by presence of scrollbar. var explicitOpenHeight = false; + + // How big we get when we open var openHeight; var name; @@ -42,7 +41,7 @@ var GUI = function() { var controllerContainer = document.createElement('div'); controllerContainer.setAttribute('class', 'guidat-controllers'); - // Firefox hack for horizontal scrolling + // Firefox hack to prevent horizontal scrolling controllerContainer.addEventListener('DOMMouseScroll', function(e) { var scrollAmount = this.scrollTop; @@ -82,18 +81,16 @@ var GUI = function() { mx = e.pageX; var dmy = my - pmy; - - - if (!open) { - if (dmy > 0) { - open = true; - curControllerContainerHeight = openHeight = 1; - toggleButton.innerHTML = name || "Hide Controls"; - } else { - return; + + if (!open) { + if (dmy > 0) { + open = true; + curControllerContainerHeight = openHeight = 1; + toggleButton.innerHTML = name || "Hide Controls"; + } else { + return; + } } - } - // TODO: Flip this if you want to resize to the left. var dmx = pmx - mx; @@ -260,13 +257,6 @@ var GUI = function() { this.autoListen = true; - var handlerTypes = { - "number": NumberController, - "string": StringController, - "boolean": BooleanController, - "function": FunctionController - }; - var alreadyControlled = function(object, propertyName) { for (var i in controllers) { if (controllers[i].object == object && @@ -362,14 +352,13 @@ var GUI = function() { } else { controllerContainer.style.overflowY = "hidden"; } - // console.log(controllerHeight, openHeight); } - var addHandlers = { - "number": NumberController, - "string": StringController, - "boolean": BooleanController, - "function": FunctionController + var handlerTypes = { + "number": GUI.NumberController, + "string": GUI.StringController, + "boolean": GUI.BooleanController, + "function": GUI.FunctionController }; var alreadyControlled = function(object, propertyName) { @@ -391,7 +380,7 @@ var GUI = function() { }; this.reset = function() { - // + // TODO } // GUI ... GUI @@ -486,10 +475,8 @@ GUI.saveURL = function() { GUI.scrollTop = -1; -// TODO: Not working in FF. GUI.load = function(saveString) { - //GUI.savedAppearanceVars = []; var vals = saveString.split(","); var numGuis = parseInt(vals[0]); @@ -500,6 +487,7 @@ GUI.load = function(saveString) { } GUI.savedValues = vals.splice(2, vals.length); + }; GUI.savedValues = []; @@ -626,4 +614,9 @@ GUI.roundToDecimal = function(n, decimals) { return Math.round(n*t)/t; } +GUI.extendController = function(clazz) { + clazz.prototype = new GUI.Controller(); + clazz.prototype.constructor = clazz; +} + if (GUI.getVarFromURL('saveString') != null) GUI.load(GUI.getVarFromURL('saveString')); \ No newline at end of file diff --git a/index.html b/index.html index 00632bf..06737e5 100644 --- a/index.html +++ b/index.html @@ -36,17 +36,12 @@ prettyPrint(); - var fizzyText = new FizzyText("gui-dat"); var gui = new GUI(); - var gui2 = new GUI(); - // Text field gui.add(fizzyText, "message"); - gui2.add(window, "onload"); - // Sliders with min and max gui.add(fizzyText, "maxSize", 0.5, 7); gui.add(fizzyText, "growthSpeed", 0.01, 1); @@ -61,9 +56,6 @@ // Fires a function called "explode" gui.add(fizzyText, "explode").name("Explode!"); // Specify a custom name. - gui.add(GUI, "showSaveString"); - gui.add(GUI, "saveURL"); - // Javascript for documentation getCollapsables(); @@ -286,8 +278,8 @@ document.getElementById("my-gui-container").appendChild( gui.domElement ); -