From 67557292bb563bcc4331bcc7e8bab8b8b6a6832b Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 00:44:54 +0000 Subject: [PATCH 01/65] 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 eb410d3fda4ff8bba5137575dde13b970ae5ece4 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 01:23:20 +0000 Subject: [PATCH 02/65] 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 5f9af3d3ee03b80f71210375ed22976fae4546b8 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 01:34:57 +0000 Subject: [PATCH 03/65] 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 46b5d1ff24fe3a762853a1c1cbfbc685f6779054 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 02:25:48 +0000 Subject: [PATCH 04/65] 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 e11bd9b98a718c9d69df24401629d93d21c87851 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 19:55:43 -0700 Subject: [PATCH 05/65] 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 790083fa3b9958ce6b7badb70981cf152fd5c689 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:03:56 -0700 Subject: [PATCH 06/65] 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 ebf5294ee5c5cff55091c9627461264ad43876b2 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:17:57 -0700 Subject: [PATCH 07/65] 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 d3effd0e8a322a4c96b137970d9a72a6b7f7f99d Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:22:05 -0700 Subject: [PATCH 08/65] 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 d3dc2fd5665c6bf58442194396f138d336b18b84 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:27:17 -0700 Subject: [PATCH 09/65] 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 ce9bba65a5752762a5e805fff91fd2afe7a3def1 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:38:05 -0700 Subject: [PATCH 10/65] 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 14e14244c6f19ddf92e8f6ed8602e3b040709a85 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:51:44 -0700 Subject: [PATCH 11/65] 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 450eddf55f0b8c1619cdb06e6526d107eb5bdbd2 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 20:54:26 -0700 Subject: [PATCH 12/65] 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 d47e5662d89a825f1db8c5bbe95c802193d20ab3 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 29 Jan 2011 03:56:32 +0000 Subject: [PATCH 13/65] 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 1c2d2c201b305958d9867d27feba43b49a693e28 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 21:05:47 -0700 Subject: [PATCH 14/65] 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 c0f4dadbf6ba6459a4580f6a0d57841935ed14c2 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 21:41:25 -0700 Subject: [PATCH 15/65] 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 fed73755360922f2fba4a15af853eb35a4b0e83a Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:12:03 -0700 Subject: [PATCH 16/65] 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 8d04da6a2525384d16e28c3d8d900183c533bcea Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:14:23 -0700 Subject: [PATCH 17/65] 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 0674431e3c36bc0a2d7fcdde983b8fd319edda60 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:16:31 -0700 Subject: [PATCH 18/65] 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 02e6e567c6d5c34665c9e18f0966d5935fefb6c9 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:21:01 -0700 Subject: [PATCH 19/65] 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 c1c34662335e38ecaddcda433785fda751446cc1 Mon Sep 17 00:00:00 2001 From: jonobr1 Date: Fri, 28 Jan 2011 22:27:06 -0700 Subject: [PATCH 20/65] 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 f6324d64cc958998bf9f93dc13305df54a8e6c5a Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Sun, 30 Jan 2011 16:03:09 -0700 Subject: [PATCH 21/65] 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 738b4d0d0684804d389eb413eb9c4fb7d5aed0db Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Sun, 30 Jan 2011 23:53:33 -0500 Subject: [PATCH 22/65] 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 5bde5f79a11d77ecb7b5e4ac3b40d347746b716c Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 10:47:07 -0500 Subject: [PATCH 23/65] 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 7ce2af6f8ea7dcac1abba1d47d5850f37771934e Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 12:21:14 -0800 Subject: [PATCH 24/65] 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 7048931536d716861d8cbe0f0ada21f1ffc45c52 Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 12:25:57 -0800 Subject: [PATCH 25/65] 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 87f7f877c1c5ff4d359f25b2950ae39f0eec8a4d Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 12:28:18 -0800 Subject: [PATCH 26/65] 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 7501ba9839392405a6601d73865c0e11159c4dff Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 18:15:29 -0500 Subject: [PATCH 27/65] 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 6b61ad9b30bd57b4c21437eda5f884011610bb10 Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 15:50:06 -0800 Subject: [PATCH 28/65] 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 b50e86c7a0bc9aea2afe6d135c882c7628510b0d Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 20:24:30 -0500 Subject: [PATCH 29/65] 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 ea51f26d587b8c0a3bbec417998c9df49bec6e63 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Mon, 31 Jan 2011 20:42:22 -0500 Subject: [PATCH 30/65] 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 4354f96be7516cc83999e7565d8709ac50b340ad Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 19:06:34 -0800 Subject: [PATCH 31/65] 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 15d1ffce87686444369f3a7b193ed12ce3f38c1c Mon Sep 17 00:00:00 2001 From: Jono Brandel Date: Mon, 31 Jan 2011 19:09:32 -0800 Subject: [PATCH 32/65] 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 0aa2e7eea518547ef043c8664300e9cfd1fd3609 Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Tue, 1 Feb 2011 13:45:22 -0500 Subject: [PATCH 33/65] 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 ); -