diff --git a/controllers/controller.boolean.js b/controllers/controller.boolean.js
new file mode 100644
index 0000000..3acc78f
--- /dev/null
+++ b/controllers/controller.boolean.js
@@ -0,0 +1,25 @@
+var BooleanController = function() {
+ this.type = "boolean";
+ 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);
+
+};
+BooleanController.prototype = new Controller();
+BooleanController.prototype.constructor = BooleanController;
\ No newline at end of file
diff --git a/controllers/controller.function.js b/controllers/controller.function.js
new file mode 100644
index 0000000..d523562
--- /dev/null
+++ b/controllers/controller.function.js
@@ -0,0 +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";
+};
+FunctionController.prototype = new Controller();
+FunctionController.prototype.constructor = FunctionController;
\ No newline at end of file
diff --git a/controllers/controller.js b/controllers/controller.js
new file mode 100644
index 0000000..719b420
--- /dev/null
+++ b/controllers/controller.js
@@ -0,0 +1,42 @@
+var Controller = function() {
+
+ this.setName = function(n) {
+ this.propertyNameElement.innerHTML = n;
+ }
+
+ this.setValue = function(n) {
+ this.object[this.propertyName] = n;
+ }
+
+ this.getValue = function() {
+ return this.object[this.propertyName];
+ }
+
+ 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);
+
+ 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);
+
+};
\ No newline at end of file
diff --git a/controllers/controller.number.js b/controllers/controller.number.js
new file mode 100644
index 0000000..0e828ce
--- /dev/null
+++ b/controllers/controller.number.js
@@ -0,0 +1,122 @@
+// TODO: Provide alternate controllers for non-html5 browsers?
+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 draggedNumberField.
+ var draggedNumberField = false;
+ var clickedNumberField = false;
+
+ var y = py = 0;
+
+ var min = arguments[2];
+ var max = arguments[3];
+ var step = arguments[4];
+
+ if (!step) {
+ if (min && max) {
+ step = (max-min)*0.01;
+ } else {
+ step = 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 && max) {
+ slider = new Slider();
+ this.domElement.appendChild(slider.domElement);
+ }
+
+ numberField.addEventListener('blur', function(e) {
+ var val = parseFloat(this.value);
+ if (!isNaN(val)) {
+ updateValue(val);
+ } else {
+ this.value = _this.getValue();
+ }
+ }, false);
+
+ numberField.addEventListener('mousewheel', function(e) {
+ e.preventDefault();
+ 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(GUI.domElement);
+ _this.makeSelectable(numberField);
+ if (clickedNumberField && !draggedNumberField) {
+ numberField.focus();
+ numberField.select();
+ }
+ draggedNumberField = false;
+ clickedNumberField = false;
+ }, false);
+
+ 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 ...
+ // TODO: Make makeUselectable go through each element and child element.
+ _this.makeUnselectable(GUI.domElement);
+ _this.makeUnselectable(numberField);
+
+ py = y;
+ y = e.pageY;
+ var dy = py - y;
+ var newVal = _this.getValue() + dy*step;
+ updateValue(newVal);
+ return false;
+ }
+
+ var updateValue = function(val) {
+
+ val = parseFloat(val);
+
+ if (min && val <= min) {
+ val = min;
+ } else if (max && val >= max) {
+ val = max;
+ }
+ _this.setValue(val);
+
+ numberField.value = _this.getValue();
+ if (slider) slider.value = _this.getValue();
+ }
+
+};
+
+NumberController.prototype = new Controller();
+NumberController.prototype.constructor = NumberController;
\ No newline at end of file
diff --git a/controllers/controller.string.js b/controllers/controller.string.js
new file mode 100644
index 0000000..aa955ea
--- /dev/null
+++ b/controllers/controller.string.js
@@ -0,0 +1,27 @@
+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);
+};
+StringController.prototype = new Controller();
+StringController.prototype.constructor = StringController;
\ No newline at end of file
diff --git a/controllers/slider.js b/controllers/slider.js
new file mode 100644
index 0000000..76bedb7
--- /dev/null
+++ b/controllers/slider.js
@@ -0,0 +1,11 @@
+var Slider = function() {
+
+ this.domElement = document.createElement('div');
+ this.domElement.setAttribute('class', 'guidat-slider-bg');
+
+ this.fg = document.createElement('div');
+ this.fg.setAttribute('class', 'guidat-slider-fg');
+
+ this.domElement.appendChild(this.fg);
+
+}
\ No newline at end of file
diff --git a/demo.css b/demo.css
index 560d1e0..01d56ef 100644
--- a/demo.css
+++ b/demo.css
@@ -9,6 +9,7 @@ max-width: 500px;
font: 10px Monaco, monospace;
}
+
/* SPAN elements with the classes below are added by prettyprint. */
.str { color: #0fa954; }
.kwd { color: #e61d5f; }
diff --git a/gui.css b/gui.css
index de0b8a3..a8a3680 100644
--- a/gui.css
+++ b/gui.css
@@ -25,7 +25,7 @@
height: 300px;
overflow-y: auto;
overflow-x: hidden;
- background-color: #eee;
+ background-color: rgba(0,0,0,0.1);
}
#guidat-toggle {
@@ -65,6 +65,17 @@
background-color: #222;
}
+.guidat-controller input::selection {
+background-color: #000;
+}
+
+.guidat-controller input:hover {
+ background-color: #444;
+}
+.guidat-controller input:focus {
+ background-color: #555;
+}
+
.guidat-controller.number {
border-left: 5px solid #00aeff ;
}
@@ -96,7 +107,6 @@
.guidat-controller.number input[type=slider] {
width: 50%;
-
}
#guidat .guidat-controller.boolean input {
diff --git a/index.html b/index.html
index 2fc401b..12fd13c 100644
--- a/index.html
+++ b/index.html
@@ -5,11 +5,12 @@
-
-
-
-
-
+
+
+
+
+
+