diff --git a/demo/demo.css b/demo/demo.css index 0994563..bd65ce6 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -18,7 +18,7 @@ h1 { font-weight: 800; text-transform: lowercase; line-height: 80px; - margin: 20px 0 0 0; + margin: 20px 0 20px 0; } h1 a:link, h1 a:visited, h1 a:hover, h1 a:active { @@ -26,20 +26,27 @@ h1 a:link, h1 a:visited, h1 a:hover, h1 a:active { margin-right: 7px; } -h1 span { - -} - h1 img { width: 45px; height: 45px; -moz-border-radius: 9px; border-radius: 9px; - margin-bottom: 20px; + margin-bottom: 8px; } h2 { + margin-top: 30px; font-size: 18px; + margin-bottom: 24px; +} + +#helvetica-demo { + position: absolute; + left: 0; + top: 0; + width: 800; + height: 300; + z-index: -1; } pre { @@ -50,39 +57,62 @@ pre { font: 10px Monaco, monospace; } -p { font-size: 125%; max-width: 530px; line-height: 18px; margin-bottom: 36px; } +p, ul { + font-size: 125%; + max-width: 530px; + line-height: 18px; + margin-bottom: 24px; +} + +li { + margin-left: 18px; +} + +ul#desc { + list-style: circle; + font-size: 100%; + max-width: 380px; +} a:link { color: #00aeff; } + a:visited { color: #0fa954; } + a:hover { color: #e61d5f; } + a:active { color: #54396e; } footer { -background-color: #eee; -width: 510px; -padding: 10px; + background-color: #eee; + width: 510px; + padding: 10px; } -#columns { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - height: 10px; +pre a:link, +pre a:visited, +pre a:active { +color: #ccc; } -#columns div { - float: left; - width : auto; - height: 10px; +pre a:hover { +color: #e61d5f; +} + +code { + font: 10px Monaco, monospace; +} + +code strong { + font-weight: normal; + color: #e61d5f; } /* SPAN elements with the classes below are added by prettyprint. */ diff --git a/demo/demo.js b/demo/demo.js index 7568a34..1029d3f 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,142 +1,169 @@ -function DynamicText(message, width, height, textAscent) { - +function FizzyText(message) { + var _this = this; - + + var width = 550; + var height = 200; + var textAscent = 82; + var textLeft = 80; + + this.growthSpeed = 0.5; this.minSize = 0; - this.maxSize = 3; - + this.maxSize = 3.2; + this.noiseScale = 300; this.noiseStrength = 10; - this.stepSize = 1; - + this.speed = 0.4; + this.displayOutline = false; - - var message = message; - - this.width = width; - this.height = height; - + this.textAscent = textAscent; - - var colors = [ - "#00aeff", - "#0fa954", - "#54396e", - "#e61d5f" - ] - + + + var colors = ["#00aeff", "#0fa954", "#54396e", "#e61d5f"]; + var r = document.createElement('canvas'); var s = r.getContext('2d'); - + var c = document.createElement('canvas'); var g = c.getContext('2d'); - - r.setAttribute('width', width); - c.setAttribute('width', width); + + r.setAttribute('width', width); + c.setAttribute('width', width); r.setAttribute('height', height); c.setAttribute('height', height); - + document.getElementById('helvetica-demo').appendChild(c); - - var pixels = []; + + var pixels = []; var particles = []; - - s.font = g.font = "800 "+textAscent+"px helvetica, arial, sans-serif"; - - // Set reference onto particles - for (var i = 0; i < 1000; i++) { - particles.push( new Particle(Math.random()*width, Math.random()*height)); - } - - var createBitmap = function(m) { + + s.font = g.font = "800 " + textAscent + "px helvetica, arial, sans-serif"; + + // Set reference onto particles + for (var i = 0; i < 1000; i++) { + particles.push(new Particle(Math.random() * width, Math.random() * height)); + } + + var createBitmap = function (m) { s.fillStyle = "#fff"; s.fillRect(0, 0, width, height); - + s.fillStyle = "#222"; - s.fillText(m, 0, textAscent); - + s.fillText(m, textLeft, textAscent); + // Pull reference var imageData = s.getImageData(0, 0, width, height); pixels = imageData.data; - + }; - - var render = function() { - + + var render = function () { + g.clearRect(0, 0, width, height); - - if(_this.displayOutline) { + + if (_this.displayOutline) { g.globalCompositeOperation = "source-over"; g.strokeStyle = "#000"; - g.lineWidth = .25; - g.strokeText(message, 0, textAscent); + g.lineWidth = .5; + g.strokeText(message, textLeft, textAscent); } - + g.globalCompositeOperation = "darker"; - + for (var i = 0; i < particles.length; i++) { - g.fillStyle = colors[i%colors.length]; + g.fillStyle = colors[i % colors.length]; particles[i].render(); } }; - - var getPosition = function(i) { - return { x: (i - (width * 4) * Math.floor(i/(width * 4))) / 4, y: Math.floor(i/(width * 4)) }; - }; - - var getColor = function(x, y) { - var base = (Math.floor(y) * width + Math.floor(x)) * 4; - var c = { r: pixels[base + 0], g: pixels[base + 1], b: pixels[base + 2], a: pixels[base + 3]}; - return "rgb("+c.r+","+c.g+","+c.b+")"; + var getPosition = function (i) { + return { + x: (i - (width * 4) * Math.floor(i / (width * 4))) / 4, + y: Math.floor(i / (width * 4)) + }; }; - - this.__defineGetter__("message", function() { + + var getColor = function (x, y) { + var base = (Math.floor(y) * width + Math.floor(x)) * 4; + var c = { + r: pixels[base + 0], + g: pixels[base + 1], + b: pixels[base + 2], + a: pixels[base + 3] + }; + + return "rgb(" + c.r + "," + c.g + "," + c.b + ")"; + }; + + this.__defineGetter__("message", function () { return message; }); - - this.__defineSetter__("message", function(m) { + + this.__defineSetter__("message", function (m) { message = m; createBitmap(message); }); - - createBitmap(message); - setInterval(render, 30); - - function Particle(x, y, c) { - this.p = { x: x, y: y }; - this.r = 0; - - this.render = function() { - var c = getColor(this.x, this.y); - - var angle = noise(this.p.x/_this.noiseScale, this.p.y/_this.noiseScale) * _this.noiseStrength; - var c = getColor(this.p.x, this.p.y); - if (c == "rgb(255,255,255)") { - this.r -= _this.growthSpeed; - } else { - this.r += _this.growthSpeed; - } - this.p.x += Math.cos(angle) * _this.stepSize; - this.p.y += -Math.sin(angle) * _this.stepSize; - this.r = constrain(this.r, _this.minSize, _this.maxSize); - if(this.r <= _this.minSize) { - this.p.x = Math.random() * width; - this.p.y = Math.random() * height; - } - g.beginPath(); - g.arc(this.p.x, this.p.y, this.r, 0, Math.PI*2, false); - g.fill(); + + this.explode = function() { + var mag = Math.random()*30+30; + for (var i in particles) { + var angle= Math.random()*Math.PI*2; + particles[i].vx = Math.cos(angle)*mag; + particles[i].vy = Math.sin(angle)*mag; } - } + }; + this.message = message; - var constrain = function(v, o1, o2) { - if (v < o1) v = o1; - else if (v > o2) v = o2; - return v; - } + setInterval(render, 30); + + function Particle(x, y, c) { + this.x = x; + this.y = y; -} + this.vx = 0; + this.vy = 0; + this.r = 0; + + this.render = function () { + var c = getColor(this.x, this.y); + var angle = noise(this.x / _this.noiseScale, this.y / _this.noiseScale) * _this.noiseStrength; + + var onScreen = this.x > 0 && this.x < width && + this.y > 0 && this.y < height; + var isBlack = c != "rgb(255,255,255)" && + onScreen; + + if (isBlack) { + this.r += _this.growthSpeed; + } else { + this.r -= _this.growthSpeed; + } + this.vx *= 0.5; + this.vy *= 0.5; + this.x += Math.cos(angle) * _this.speed + this.vx; + this.y += -Math.sin(angle) * _this.speed + this.vy; + this.r = constrain(this.r, _this.minSize, _this.maxSize); + if (this.r <= _this.minSize) { + this.x = Math.random() * width; + this.y = Math.random() * height; + } + if (this.r <= 0) { + return; + } + g.beginPath(); + g.arc(this.x, this.y, this.r, 0, Math.PI * 2, false); + g.fill(); + } + } + + var constrain = function (v, o1, o2) { + if (v < o1) v = o1; + else if (v > o2) v = o2; + return v; + } + +} \ No newline at end of file diff --git a/gui-tobeminified.js b/gui-tobeminified.js new file mode 100644 index 0000000..4dce9e3 --- /dev/null +++ b/gui-tobeminified.js @@ -0,0 +1,489 @@ +// This version of gui.js appends the style definitions via javascript. +var GUI = new function() { + + var _this = this; + + var controllers = []; + + var style = '#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() { + + // We need to call GUI.start() before .add() + if (!started) { + error("Make sure to call GUI.start() in the window.onload function"); + return; + } + + var object = arguments[0]; + var propertyName = arguments[1]; + + // Have we already added this? + if (alreadyControlled(object, propertyName)) { + 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."); + return; + } + + var type = typeof value; + var handler = addHandlers[type]; + + // Do we know how to deal with this data type? + if (handler == undefined) { + error("Cannot create controller for data type \""+type+"\""); + return; + } + + var controllerObject = handler.apply(this, arguments); + + // Were we able to make the controller? + if (!controllerObject) { + error("Error creating controller for \""+propertyName+"\"."); + return; + } + + // Success. + controllerContainer.appendChild(controllerObject.domElement); + controllers.push(controllerObject); + + return controllerObject; + + } + + var addHandlers = { + + "number": function() { + return construct(NumberController, arguments); + }, + + "string": function() { + return construct(StringController, arguments); + }, + + "boolean": function() { + return construct(BooleanController, arguments); + }, + + "function": function() { + return construct(FunctionController, arguments); + }, + + }; + + var alreadyControlled = function(object, propertyName) { + for (var i in controllers) { + if (controllers[i].object == object && + controllers[i].propertyName == propertyName) { + return true; + } + } + 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); + } + F.prototype = constructor.prototype; + return new F(); + }; + + + + // GUI ... GUI + + this.domElement = null; + var controllerContainer; + var started = false; + var open = false; + + // TODO: obtain this dynamically? + var domElementMarginTop = 300; + + this.start = function() { + + var styleSheet = document.createElement('style'); + styleSheet.setAttribute('type', 'text/css'); + styleSheet.innerHTML = style; + document.getElementsByTagName('head')[0].appendChild(styleSheet); + + + this.domElement = document.createElement('div'); + this.domElement.setAttribute('id', 'guidat'); + + controllerContainer = document.createElement('div'); + controllerContainer.setAttribute('id', 'guidat-controllers'); + + toggleButton = document.createElement('a'); + toggleButton.setAttribute('id', 'guidat-toggle'); + toggleButton.setAttribute('href', '#'); + toggleButton.innerHTML = "Show Controls"; + toggleButton.addEventListener('click', function(e) { + _this.toggle(); + e.preventDefault(); + }, false); + + this.domElement.appendChild(controllerContainer); + this.domElement.appendChild(toggleButton); + + this.domElement.style.marginTop = -domElementMarginTop+"px"; + + document.body.appendChild(this.domElement); + + started = true; + + }; + + this.toggle = function() { + + if (open) { + this.hide(); + } else { + this.show(); + } + + }; + + this.show = function() { + this.domElement.style.marginTop = 0+"px"; + toggleButton.innerHTML = "Hide Controls"; + open = true; + } + + this.hide = function() { + this.domElement.style.marginTop = -domElementMarginTop+"px"; + toggleButton.innerHTML = "Show Controls"; + open = false; + } + +}; +// TODO: Leaving the window while dragging the slider and then removing the mouse +// still leaves slider in focus. +// TODO: Problem with multiple sliders. +var Slider = function(numberController, min, max, step, initValue) { + + var min = min; + var max = max; + var step = step; + + var clicked = false; + var _this = this; + + var x, px; + + 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 map = function(v, i1, i2, o1, o2) { + var v = o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); + if (v < o1) v = o1; + else if (v > o2) v = o2; + return v; + } + + var findPos = function(obj) { + var curleft = curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while (obj = obj.offsetParent); + return [curleft,curtop]; + } + } + + this.__defineSetter__('value', function(e) { + + var pct = map(e, min, max, 0, 100); + this.fg.style.width = pct+"%"; + + }); + + var onDrag = function(e) { + if (!clicked) return; + var pos = findPos(_this.domElement); + var val = map(e.pageX, pos[0], pos[0] + _this.domElement.offsetWidth, min, max); + val = Math.round(val/step)*step; + numberController.updateValue(val); + } + + this.domElement.addEventListener('mousedown', function(e) { + clicked = true; + x = px = e.pageX; + _this.domElement.setAttribute('class', 'guidat-slider-bg active'); + _this.fg.setAttribute('class', 'guidat-slider-fg active'); + onDrag(e); + }, false); + + + document.addEventListener('mouseup', function(e) { + _this.domElement.setAttribute('class', 'guidat-slider-bg'); + _this.fg.setAttribute('class', 'guidat-slider-fg'); + clicked = false; + }, false); + + document.addEventListener('mousemove', onDrag, false); + + + + + this.value = initValue; + +} +var Controller = function() { + + var onChange = null; + + this.setName = function(n) { + this.propertyNameElement.innerHTML = n; + } + + this.setValue = function(n) { + this.object[this.propertyName] = n; + if (onChange != null) { + onChange.call(this, n); + } + } + + this.getValue = function() { + return this.object[this.propertyName]; + } + + this.onChange = function(fnc) { + onChange = fnc; + } + + 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); + +}; +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; +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; +// 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 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) { + 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 != 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(GUI.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; + 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; + _this.updateValue(newVal); + return false; + } + + this.updateValue = function(val) { + + val = parseFloat(val); + + if (min != undefined && val <= min) { + val = min; + } else if (max != undefined && 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; +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/gui.css b/gui.css index 005ec90..e55b459 100644 --- a/gui.css +++ b/gui.css @@ -94,7 +94,7 @@ border: 0; color: #1ed36f; margin-right: 2px; -width: 53%; +width: 148px; } .guidat-controller.boolean { diff --git a/gui.min.js b/gui.min.js new file mode 100644 index 0000000..8d5d355 --- /dev/null +++ b/gui.min.js @@ -0,0 +1 @@ +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 diff --git a/index.html b/index.html index 391a72c..7b66cfc 100644 --- a/index.html +++ b/index.html @@ -1,66 +1,34 @@ - GUI-DAT + gui-dat - - - - - - - - - - - + -

GUI-DAT flag

+
+

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.

-

Download the minified source [2.3kb]
- • Contribute on GitHub!

+

Basic Usage

- -
-<script type="text/javascript" src="gui.min.js"></script>
-<script type="text/javascript">
-
-var controllableObject = 
-   {   
-	  numberProperty: 20,
-	  constrainedNum: 0,
-	  notchedNum: 240,
-	  textProperty: "a string",
-	  anotherTextProperty: "another string",
-	  booleanProperty: false,
-	  anotherBooleanProperty: false,
-	  functionProperty: function() {
-		 alert("I am a function!");
-	  }
-   };
-
-window.onload = function() {
-
-   GUI.start();
-
-   // Creates a number box
-   GUI.add(controllableObject, "numberProperty");
-
-   // Creates a slider (min, max)
-   GUI.add(controllableObject, "constrainedNum", -100, 100)
-
-   // Creates a slider with notches
-   GUI.add(controllableObject, "notchedNum", 0, 800, 100)
-
-   // Creates a text field
-   GUI.add(controllableObject, "textProperty");
-
-   // Creates a checkbox
-   GUI.add(controllableObject, "booleanProperty");
-
-   // Creates a button
-   GUI.add(controllableObject, "functionProperty")
-      .setName("Fire a Function");
-
-};
-
-</script>
+
<script type="text/javascript" src="gui.min.js"></script>
<script type="text/javascript">

window
.onload = function() {

   
var fizzyText = new FizzyText("gui-dat");

   GUI
.start();
   
   
// Adds a text field
   GUI
.add(fizzyText, "message");
   
   
// Adds 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);
   
   
// Adds sliders with min, max and increment.
   GUI
.add(fizzyText, "noiseStrength", 10, 100, 5);
   
   
// Adds a boolean checkbox
   GUI
.add(fizzyText, "displayOutline");

   
// Adds a function button
   GUI
.add(fizzyText, "explode")
   
};

</script>
+ +