From 1d72449b36fc8b504b40f98d6af11e483498ee6b Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Tue, 25 Jan 2011 01:22:04 -0700 Subject: [PATCH] Added controllers folder, some small css fixes --- controllers/controller.boolean.js | 25 ++++++ controllers/controller.function.js | 12 +++ controllers/controller.js | 42 ++++++++++ controllers/controller.number.js | 122 +++++++++++++++++++++++++++++ controllers/controller.string.js | 27 +++++++ controllers/slider.js | 11 +++ demo.css | 1 + gui.css | 14 +++- index.html | 11 +-- 9 files changed, 258 insertions(+), 7 deletions(-) create mode 100644 controllers/controller.boolean.js create mode 100644 controllers/controller.function.js create mode 100644 controllers/controller.js create mode 100644 controllers/controller.number.js create mode 100644 controllers/controller.string.js create mode 100644 controllers/slider.js 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 @@ - - - - - + + + + + +