diff --git a/controllers/controller.boolean.js b/controllers/controller.boolean.js index 66808ca..2cb68b3 100644 --- a/controllers/controller.boolean.js +++ b/controllers/controller.boolean.js @@ -1,39 +1,39 @@ GUI.BooleanController = function() { - this.type = "boolean"; - GUI.Controller.apply(this, arguments); + this.type = "boolean"; + GUI.Controller.apply(this, arguments); - var _this = this; + 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); + input.checked = !input.checked; + e.preventDefault(); + _this.setValue(input.checked); }, false); - + input.addEventListener('mouseup', function(e) { - input.checked = !input.checked; // counteracts default. + input.checked = !input.checked; // counteracts default. }, false); - + this.domElement.style.cursor = "pointer"; this.propertyNameElement.style.cursor = "pointer"; this.domElement.appendChild(input); - + this.updateDisplay = function() { - input.checked = _this.getValue(); + input.checked = _this.getValue(); }; - - + + this.setValue = function(val) { - if (typeof val != "boolean") { - try { - val = eval(val); - } catch (e) {} - } - return GUI.Controller.prototype.setValue.call(this, val); - } + if (typeof val != "boolean") { + try { + val = eval(val); + } catch (e) {} + } + return GUI.Controller.prototype.setValue.call(this, val); + }; }; -GUI.extendController(GUI.BooleanController); \ No newline at end of file +GUI.extendController(GUI.BooleanController); diff --git a/controllers/controller.function.js b/controllers/controller.function.js index ee0b831..75c84b9 100644 --- a/controllers/controller.function.js +++ b/controllers/controller.function.js @@ -1,30 +1,29 @@ GUI.FunctionController = function() { - - this.type = "function"; - - var _this = this; - - GUI.Controller.apply(this, arguments); - - this.domElement.addEventListener('click', function() { - _this.fire(); - }, false); - - this.domElement.style.cursor = "pointer"; - this.propertyNameElement.style.cursor = "pointer"; - - var fireFunction = null; - this.onFire = function(fnc) { - fireFunction = fnc; - return this; - } - - this.fire = function() { - if (fireFunction != null) { - fireFunction.call(this); - } - _this.object[_this.propertyName].call(_this.object); - }; - + + this.type = "function"; + + var _this = this; + + GUI.Controller.apply(this, arguments); + + this.domElement.addEventListener('click', function() { + _this.fire(); + }, false); + + this.domElement.style.cursor = "pointer"; + this.propertyNameElement.style.cursor = "pointer"; + + var fireFunction = null; + this.onFire = function(fnc) { + fireFunction = fnc; + return this; + } + + this.fire = function() { + if (fireFunction != null) { + fireFunction.call(this); + } + _this.object[_this.propertyName].call(_this.object); + }; }; GUI.extendController(GUI.FunctionController); diff --git a/controllers/controller.js b/controllers/controller.js index c2f6eef..c054fa0 100644 --- a/controllers/controller.js +++ b/controllers/controller.js @@ -1,96 +1,97 @@ GUI.Controller = function() { - this.parent = arguments[0]; + this.parent = arguments[0]; this.object = arguments[1]; this.propertyName = arguments[2]; - if (arguments.length > 0) this.initialValue = this.propertyName[this.object]; + if (arguments.length > 0) this.initialValue = this.propertyName[this.object]; this.domElement = document.createElement('div'); this.domElement.setAttribute('class', 'guidat-controller ' + this.type); - + this.propertyNameElement = document.createElement('span'); this.propertyNameElement.setAttribute('class', 'guidat-propertyname'); this.name(this.propertyName); this.domElement.appendChild(this.propertyNameElement); - + GUI.makeUnselectable(this.domElement); - + }; GUI.Controller.prototype.changeFunction = null; GUI.Controller.prototype.finishChangeFunction = null; GUI.Controller.prototype.name = function(n) { - this.propertyNameElement.innerHTML = n; - return this; + this.propertyNameElement.innerHTML = n; + return this; }; GUI.Controller.prototype.reset = function() { - this.setValue(this.initialValue); - return this; + this.setValue(this.initialValue); + return this; }; GUI.Controller.prototype.listen = function() { - this.parent.listenTo(this); - return this; -} + this.parent.listenTo(this); + return this; +}; GUI.Controller.prototype.unlisten = function() { - this.parent.unlistenTo(this); // <--- hasn't been tested yet - return this; -} - -GUI.Controller.prototype.setValue = function(n) { - this.object[this.propertyName] = n; - if (this.changeFunction != null) { - this.changeFunction.call(this, n); - } - this.updateDisplay(); - return this; -} - -GUI.Controller.prototype.getValue = function() { - return this.object[this.propertyName]; -} + this.parent.unlistenTo(this); // <--- hasn't been tested yet + return this; +}; + +GUI.Controller.prototype.setValue = function(n) { + this.object[this.propertyName] = n; + if (this.changeFunction != null) { + this.changeFunction.call(this, n); + } + this.updateDisplay(); + return this; +}; + +GUI.Controller.prototype.getValue = function() { + return this.object[this.propertyName]; +}; + +GUI.Controller.prototype.updateDisplay = function() {}; -GUI.Controller.prototype.updateDisplay = function() {} - GUI.Controller.prototype.onChange = function(fnc) { - this.changeFunction = fnc; - return this; -} + this.changeFunction = fnc; + return this; +}; + GUI.Controller.prototype.onFinishChange = function(fnc) { - this.finishChangeFunction = fnc; - return this; -} + this.finishChangeFunction = fnc; + return this; +}; GUI.Controller.prototype.options = function() { - var _this = this; - var select = document.createElement('select'); - if (arguments.length == 1) { - var arr = arguments[0]; - for (var i in arr) { - var opt = document.createElement('option'); - opt.innerHTML = i; - opt.setAttribute('value', arr[i]); - select.appendChild(opt); - } - } else { - for (var i = 0; i < arguments.length; i++) { - var opt = document.createElement('option'); - opt.innerHTML = arguments[i]; - opt.setAttribute('value', arguments[i]); - select.appendChild(opt); - } - } - - select.addEventListener('change', function() { - _this.setValue(this.value); - if (_this.finishChangeFunction != null) { - _this.finishChangeFunction.call(this, _this.getValue()); - } - }); - _this.domElement.appendChild(select); - return this; -} + var _this = this; + var select = document.createElement('select'); + if (arguments.length == 1) { + var arr = arguments[0]; + for (var i in arr) { + var opt = document.createElement('option'); + opt.innerHTML = i; + opt.setAttribute('value', arr[i]); + select.appendChild(opt); + } + } else { + for (var i = 0; i < arguments.length; i++) { + var opt = document.createElement('option'); + opt.innerHTML = arguments[i]; + opt.setAttribute('value', arguments[i]); + select.appendChild(opt); + } + } + + select.addEventListener('change', function() { + _this.setValue(this.value); + if (_this.finishChangeFunction != null) { + _this.finishChangeFunction.call(this, _this.getValue()); + } + }, false); + _this.domElement.appendChild(select); + return this; +}; diff --git a/controllers/controller.number.js b/controllers/controller.number.js index 4a63372..7c5923a 100644 --- a/controllers/controller.number.js +++ b/controllers/controller.number.js @@ -1,150 +1,152 @@ GUI.NumberController = function() { - this.type = "number"; - + this.type = "number"; + GUI.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 y = 0, py = 0; + var min = arguments[3]; var max = arguments[4]; var step = arguments[5]; - + if (!step) { - if (min != undefined && max != undefined) { - step = (max-min)*0.01; - } else { - step = 1; - } + if (min != undefined && max != undefined) { + step = (max-min)*0.01; + } else { + step = 1; + } } - + var numberField = document.createElement('input'); numberField.setAttribute('id', this.propertyName); 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 GUI.Slider(this, min, max, step, this.getValue()); - this.domElement.appendChild(slider.domElement); + slider = new GUI.Slider(this, min, max, step, this.getValue()); + this.domElement.appendChild(slider.domElement); } - + numberField.addEventListener('blur', function(e) { var val = parseFloat(this.value); - console.log(val); if (!isNaN(val)) { - _this.setValue(val); + _this.setValue(val); } }, false); - + numberField.addEventListener('mousewheel', function(e) { - e.preventDefault(); - _this.setValue(_this.getValue() + Math.abs(e.wheelDeltaY)/e.wheelDeltaY*step); - return false; + e.preventDefault(); + _this.setValue(_this.getValue() + Math.abs(e.wheelDeltaY)/e.wheelDeltaY*step); + return false; }, false); - + numberField.addEventListener('mousedown', function(e) { py = y = e.pageY; - clickedNumberField = true; + clickedNumberField = true; document.addEventListener('mousemove', dragNumberField, false); - document.addEventListener('mouseup', mouseup, false); + document.addEventListener('mouseup', mouseup, false); + }, false); + + // Handle up arrow and down arrow + numberField.addEventListener('keydown', function(e) { + var newVal; + switch(e.keyCode) { + case 38: // up + newVal = _this.getValue() + step; + _this.setValue(newVal); + break; + case 40: // down + newVal = _this.getValue() - step; + _this.setValue(newVal); + break; + } }, false); - // Handle up arrow and down arrow - numberField.addEventListener('keydown', 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); - var mouseup = function(e) { document.removeEventListener('mousemove', dragNumberField, false); - GUI.makeSelectable(_this.parent.domElement); + GUI.makeSelectable(_this.parent.domElement); GUI.makeSelectable(numberField); - if (clickedNumberField && !draggedNumberField) { - numberField.focus(); - numberField.select(); + if (clickedNumberField && !draggedNumberField) { + numberField.focus(); + numberField.select(); } + if(slider) slider.domElement.className = slider.domElement.className.replace(' active', ''); draggedNumberField = false; clickedNumberField = false; - if (_this.finishChangeFunction != null) { - _this.finishChangeFunction.call(this, _this.getValue()); - } - document.removeEventListener('mouseup', mouseup, false); - } + if (_this.finishChangeFunction != null) { + _this.finishChangeFunction.call(this, _this.getValue()); + } + document.removeEventListener('mouseup', mouseup, 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. + 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. + + GUI.makeUnselectable(_this.parent.domElement); + GUI.makeUnselectable(numberField); + + if(slider) slider.domElement.className += ' active'; + + py = y; + y = e.pageY; + var dy = py - y; + var newVal = _this.getValue() + dy*step; + _this.setValue(newVal); + return false; + }; - GUI.makeUnselectable(_this.parent.domElement); - GUI.makeUnselectable(numberField); - - py = y; - y = e.pageY; - var dy = py - y; - var newVal = _this.getValue() + dy*step; - _this.setValue(newVal); - return false; - } - this.options = function() { - _this.noSlider(); - _this.domElement.removeChild(numberField); - return GUI.Controller.prototype.options.apply(this, arguments); + _this.noSlider(); + _this.domElement.removeChild(numberField); + return GUI.Controller.prototype.options.apply(this, arguments); }; - + this.noSlider = function() { - if (slider) { - _this.domElement.removeChild(slider.domElement); - } - return this; + if (slider) { + _this.domElement.removeChild(slider.domElement); + } + return this; }; - + this.setValue = function(val) { - - val = parseFloat(val); - - if (min != undefined && val <= min) { - val = min; - } else if (max != undefined && val >= max) { - val = max; - } - - return GUI.Controller.prototype.setValue.call(this, val); - - } - + + val = parseFloat(val); + + if (min != undefined && val <= min) { + val = min; + } else if (max != undefined && val >= max) { + val = max; + } + + return GUI.Controller.prototype.setValue.call(this, val); + + }; + this.updateDisplay = function() { numberField.value = GUI.roundToDecimal(_this.getValue(), 4); if (slider) slider.value = _this.getValue(); - } + }; }; GUI.extendController(GUI.NumberController); diff --git a/controllers/controller.string.js b/controllers/controller.string.js index 9167358..1b6fa45 100644 --- a/controllers/controller.string.js +++ b/controllers/controller.string.js @@ -1,47 +1,47 @@ GUI.StringController = function() { - this.type = "string"; - - var _this = this; + this.type = "string"; + + var _this = this; GUI.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(); + input.focus(); + input.select(); }, false); - + // TODO: getting messed up on ctrl a input.addEventListener('keyup', function(e) { - if (e.keyCode == 13 && _this.finishChangeFunction != null) { - _this.finishChangeFunction.call(this, _this.getValue()); - } + if (e.keyCode == 13 && _this.finishChangeFunction != null) { + _this.finishChangeFunction.call(this, _this.getValue()); + } _this.setValue(input.value); }, false); - + input.addEventListener('blur', function() { - if (_this.finishChangeFunction != null) { - _this.finishChangeFunction.call(this, _this.getValue()); - } + if (_this.finishChangeFunction != null) { + _this.finishChangeFunction.call(this, _this.getValue()); + } }, false); - + this.updateDisplay = function() { - input.value = _this.getValue(); - } - - this.options = function() { - _this.domElement.removeChild(input); - return GUI.Controller.prototype.options.apply(this, arguments); + input.value = _this.getValue(); }; - + + this.options = function() { + _this.domElement.removeChild(input); + return GUI.Controller.prototype.options.apply(this, arguments); + }; + this.domElement.appendChild(input); - + }; -GUI.extendController(GUI.StringController); \ No newline at end of file +GUI.extendController(GUI.StringController); diff --git a/controllers/slider.js b/controllers/slider.js index b3ad28a..c7cec99 100644 --- a/controllers/slider.js +++ b/controllers/slider.js @@ -1,69 +1,92 @@ GUI.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.domElement.setAttribute('class', 'guidat-slider-bg'); - - this.fg = document.createElement('div'); - this.fg.setAttribute('class', 'guidat-slider-fg'); - - this.domElement.appendChild(this.fg); - - 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 = GUI.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 = GUI.map(e.pageX, pos[0], pos[0] + _this.domElement.offsetWidth, min, max); - val = Math.round(val/step)*step; - numberController.setValue(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); - document.addEventListener('mouseup', mouseup, false); - }, false); - - - var mouseup = function(e) { - _this.domElement.setAttribute('class', 'guidat-slider-bg'); - _this.fg.setAttribute('class', 'guidat-slider-fg'); - clicked = false; - if (numberController.finishChangeFunction != null) { - numberController.finishChangeFunction.call(this, numberController.getValue()); - } - document.removeEventListener('mouseup', mouseup, false); - }; + var clicked = false; + var _this = this; - - document.addEventListener('mousemove', onDrag, false); - - this.value = initValue; - -} + var x, px; + + 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); + + var onDrag = function(e) { + if (!clicked) return; + var pos = findPos(_this.domElement); + var val = GUI.map(e.pageX, pos[0], pos[0] + _this.domElement.offsetWidth, min, max); + val = Math.round(val/step)*step; + numberController.setValue(val); + }; + + this.domElement.addEventListener('mousedown', function(e) { + clicked = true; + x = px = e.pageX; + _this.domElement.className += ' active'; + _this.fg.className += ' active'; + numberController.domElement.className += ' active'; + onDrag(e); + document.addEventListener('mouseup', mouseup, false); + }, false); + + var mouseup = function(e) { + _this.domElement.className = _this.domElement.className.replace(' active', ''); + _this.fg.className = _this.fg.className.replace(' active', ''); + numberController.domElement.className = numberController.domElement.className.replace(' active', ''); + clicked = false; + if (numberController.finishChangeFunction != null) { + numberController.finishChangeFunction.call(this, numberController.getValue()); + } + document.removeEventListener('mouseup', mouseup, false); + }; + + var findPos = function(obj) { + var curleft = 0, 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 = GUI.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 = GUI.map(e.pageX, pos[0], pos[0] + _this.domElement.offsetWidth, min, max); + val = Math.round(val/step)*step; + numberController.setValue(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); + document.addEventListener('mouseup', mouseup, false); + }, false); + + var mouseup = function(e) { + _this.domElement.setAttribute('class', 'guidat-slider-bg'); + _this.fg.setAttribute('class', 'guidat-slider-fg'); + clicked = false; + if (numberController.finishChangeFunction != null) { + numberController.finishChangeFunction.call(this, numberController.getValue()); + } + document.removeEventListener('mouseup', mouseup, false); + }; + + document.addEventListener('mousemove', onDrag, false); + + this.value = initValue; + +}; diff --git a/demo/demo.css b/demo/demo.css index ddebc64..4344df3 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -67,12 +67,16 @@ div.collapsed h2, div.expanded h2 { cursor: pointer; } +.last { margin-bottom: 0px !important; } +.first { margin-top: 0px; } + div.trans { border-top: 1px dotted #ccc; margin: 0px 0px 20px 0px; } ol#secrets { -/* padding: 0px 0px 20px 0px;*/ + padding: 0px; + margin: 0px; } div.expanded h2:before { content: '-'; @@ -102,6 +106,8 @@ div.collapsable { } div.collapsable div { + padding-bottom: 20px; + margin-bottom: -20px; height: auto; } diff --git a/demo/demo.js b/demo/demo.js index e002bd1..b5a48eb 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,15 +1,15 @@ function FizzyText(message) { - var that = this; + 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. + // 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.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; @@ -26,37 +26,37 @@ function FizzyText(message) { createBitmap(message); }); - // We can even add functions to the GUI! As long as they have - // 0 arguments, we can call them from the dat-gui panel. - - 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; - } - }; + // We can even add functions to the GUI! As long as they have + // 0 arguments, we can call them from the dat-gui panel. + + 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; + } + }; - //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// var _this = this; - var width = 550; - var height = 200; - var textAscent = 82; + var width = 550; + var height = 200; + var textAscent = 82; var textOffsetLeft = 80; - var noiseScale = 300; - var frameTime = 30; - + var noiseScale = 300; + var frameTime = 30; + var colors = ["#00aeff", "#0fa954", "#54396e", "#e61d5f"]; - - // This is the context we use to get a bitmap of text using - // the getImageData function. + + // This is the context we use to get a bitmap of text using + // the getImageData function. var r = document.createElement('canvas'); var s = r.getContext('2d'); - // This is the context we actually use to draw. + // This is the context we actually use to draw. var c = document.createElement('canvas'); var g = c.getContext('2d'); @@ -65,17 +65,17 @@ function FizzyText(message) { r.setAttribute('height', height); c.setAttribute('height', height); - // Add our demo to the HTML + // Add our demo to the HTML document.getElementById('helvetica-demo').appendChild(c); - // Stores bitmap image + // Stores bitmap image var pixels = []; // Stores a list of particles var particles = []; - // Set g.font to the same font as the bitmap canvas, incase we - // want to draw some outlines. + // Set g.font to the same font as the bitmap canvas, incase we + // want to draw some outlines. s.font = g.font = "800 " + textAscent + "px helvetica, arial, sans-serif"; // Instantiate some particles @@ -83,8 +83,8 @@ function FizzyText(message) { particles.push(new Particle(Math.random() * width, Math.random() * height)); } - // This function creates a bitmap of pixels based on your message - // It's called every time we change the message property. + // This function creates a bitmap of pixels based on your message + // It's called every time we change the message property. var createBitmap = function (msg) { s.fillStyle = "#fff"; @@ -99,10 +99,10 @@ function FizzyText(message) { }; - // Called once per frame, updates the animation. + // Called once per frame, updates the animation. var render = function () { - that.framesRendered ++; + that.framesRendered ++; g.clearRect(0, 0, width, height); @@ -122,7 +122,7 @@ function FizzyText(message) { }; - // Returns x, y coordinates for a given index in the pixel array. + // Returns x, y coordinates for a given index in the pixel array. var getPosition = function (i) { return { x: (i - (width * 4) * Math.floor(i / (width * 4))) / 4, @@ -130,7 +130,7 @@ function FizzyText(message) { }; }; - // Returns a color for a given pixel in the pixel array. + // Returns a color for a given pixel in the pixel array. var getColor = function (x, y) { var base = (Math.floor(y) * width + Math.floor(x)) * 4; var c = { @@ -142,33 +142,33 @@ function FizzyText(message) { return "rgb(" + c.r + "," + c.g + "," + c.b + ")"; }; - - // This calls the setter we've defined above, so it also calls - // 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(loop, frameTime); + + // This calls the setter we've defined above, so it also calls + // 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(loop, frameTime); - // This class is responsible for drawing and moving those little - // colored dots. + // This class is responsible for drawing and moving those little + // colored dots. function Particle(x, y, c) { - // Position + // Position this.x = x; this.y = y; - + // Size of particle this.r = 0; - + // This velocity is used by the explode function. this.vx = 0; this.vy = 0; @@ -184,12 +184,12 @@ function FizzyText(message) { // Are we within the boundaries of the image? var onScreen = this.x > 0 && this.x < width && - this.y > 0 && this.y < height; - + this.y > 0 && this.y < height; + var isBlack = c != "rgb(255,255,255)" && onScreen; - - // If we're on top of a black pixel, grow. - // If not, shrink. + + // If we're on top of a black pixel, grow. + // If not, shrink. if (isBlack) { this.r += _this.growthSpeed; } else { diff --git a/demo/improvedNoise.js b/demo/improvedNoise.js index 30e06a1..0947d32 100644 --- a/demo/improvedNoise.js +++ b/demo/improvedNoise.js @@ -2,72 +2,72 @@ var ImprovedNoise = function () { - var p = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10, - 23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87, - 174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211, - 133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208, - 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5, - 202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119, - 248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232, - 178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249, - 14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205, - 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; + var p = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10, + 23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87, + 174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211, + 133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208, + 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5, + 202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119, + 248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232, + 178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249, + 14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205, + 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; - for ( var i = 0; i < 256 ; i++ ) { + for ( var i = 0; i < 256 ; i++ ) { - p[ 256 + i ] = p[ i ]; + p[ 256 + i ] = p[ i ]; - } + } - function fade( t ) { + function fade( t ) { - return t * t * t * ( t * ( t * 6 - 15 ) + 10 ); + return t * t * t * ( t * ( t * 6 - 15 ) + 10 ); - } + } - function lerp( t, a, b ) { + function lerp( t, a, b ) { - return a + t * ( b - a ); + return a + t * ( b - a ); - } + } - function grad( hash, x, y, z ) { + function grad( hash, x, y, z ) { - var h = hash & 15; - var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; - return ( ( h & 1 ) == 0 ? u : -u ) + ( ( h & 2 ) == 0 ? v : -v ); + var h = hash & 15; + var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; + return ( ( h & 1 ) == 0 ? u : -u ) + ( ( h & 2 ) == 0 ? v : -v ); - } + } - return { + return { - noise: function ( x, y, z ) { + noise: function ( x, y, z ) { - var floorX = Math.floor( x ), floorY = Math.floor( y ), floorZ = Math.floor( z ); + var floorX = Math.floor( x ), floorY = Math.floor( y ), floorZ = Math.floor( z ); - var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255; + var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255; - x -= floorX; - y -= floorY; - z -= floorZ; + x -= floorX; + y -= floorY; + z -= floorZ; - var xMinus1 = x -1, yMinus1 = y - 1, zMinus1 = z - 1; + var xMinus1 = x -1, yMinus1 = y - 1, zMinus1 = z - 1; - var u = fade( x ), v = fade( y ), w = fade( z ); + var u = fade( x ), v = fade( y ), w = fade( z ); - var A = p[ X ] + Y, AA = p[ A ] + Z, AB = p[ A + 1 ] + Z, B = p[ X + 1 ] + Y, BA = p[ B ] + Z, BB = p[ B + 1 ] + Z; + var A = p[ X ] + Y, AA = p[ A ] + Z, AB = p[ A + 1 ] + Z, B = p[ X + 1 ] + Y, BA = p[ B ] + Z, BB = p[ B + 1 ] + Z; - return lerp( w, lerp( v, lerp( u, grad( p[ AA ], x, y, z ), - grad( p[ BA ], xMinus1, y, z ) ), - lerp( u, grad( p[ AB ], x, yMinus1, z ), - grad( p[ BB ], xMinus1, yMinus1, z ) ) ), - lerp( v, lerp( u, grad( p[ AA + 1 ], x, y, zMinus1 ), - grad( p[ BA + 1 ], xMinus1, y, z - 1 ) ), - lerp( u, grad( p[ AB + 1 ], x, yMinus1, zMinus1 ), - grad( p[ BB + 1 ], xMinus1, yMinus1, zMinus1 ) ) ) ); + return lerp( w, lerp( v, lerp( u, grad( p[ AA ], x, y, z ), + grad( p[ BA ], xMinus1, y, z ) ), + lerp( u, grad( p[ AB ], x, yMinus1, z ), + grad( p[ BB ], xMinus1, yMinus1, z ) ) ), + lerp( v, lerp( u, grad( p[ AA + 1 ], x, y, zMinus1 ), + grad( p[ BA + 1 ], xMinus1, y, z - 1 ) ), + lerp( u, grad( p[ AB + 1 ], x, yMinus1, zMinus1 ), + grad( p[ BB + 1 ], xMinus1, yMinus1, zMinus1 ) ) ) ); - } - } + } + } } var currentRandom = Math.random; @@ -77,21 +77,21 @@ function Marsaglia(i1, i2) { // from http://www.math.uni-bielefeld.de/~sillke/ALGORITHMS/random/marsaglia-c var z=i1 || 362436069, w= i2 || 521288629; var nextInt = function() { - z=(36969*(z&65535)+(z>>>16)) & 0xFFFFFFFF; - w=(18000*(w&65535)+(w>>>16)) & 0xFFFFFFFF; - return (((z&0xFFFF)<<16) | (w&0xFFFF)) & 0xFFFFFFFF; + z=(36969*(z&65535)+(z>>>16)) & 0xFFFFFFFF; + w=(18000*(w&65535)+(w>>>16)) & 0xFFFFFFFF; + return (((z&0xFFFF)<<16) | (w&0xFFFF)) & 0xFFFFFFFF; }; this.nextDouble = function() { - var i = nextInt() / 4294967296; - return i < 0 ? 1 + i : i; + var i = nextInt() / 4294967296; + return i < 0 ? 1 + i : i; }; this.nextInt = nextInt; } Marsaglia.createRandomized = function() { var now = new Date(); return new Marsaglia((now / 60000) & 0xFFFFFFFF, now & 0xFFFFFFFF); -}; +}; // Noise functions and helpers function PerlinNoise(seed) { @@ -107,75 +107,75 @@ function PerlinNoise(seed) { for(i=0;i<256;++i) { p[i + 256] = p[i]; } function grad3d(i,x,y,z) { - var h = i & 15; // convert into 12 gradient directions - var u = h<8 ? x : y, - v = h<4 ? y : h===12||h===14 ? x : z; - return ((h&1) === 0 ? u : -u) + ((h&2) === 0 ? v : -v); + var h = i & 15; // convert into 12 gradient directions + var u = h<8 ? x : y, + v = h<4 ? y : h===12||h===14 ? x : z; + return ((h&1) === 0 ? u : -u) + ((h&2) === 0 ? v : -v); } function grad2d(i,x,y) { - var v = (i & 1) === 0 ? x : y; - return (i&2) === 0 ? -v : v; + var v = (i & 1) === 0 ? x : y; + return (i&2) === 0 ? -v : v; } function grad1d(i,x) { - return (i&1) === 0 ? -x : x; + return (i&1) === 0 ? -x : x; } function lerp(t,a,b) { return a + t * (b - a); } - + this.noise3d = function(x, y, z) { - var X = Math.floor(x)&255, Y = Math.floor(y)&255, Z = Math.floor(z)&255; - x -= Math.floor(x); y -= Math.floor(y); z -= Math.floor(z); - var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y, fz = (3-2*z)*z*z; - var p0 = p[X]+Y, p00 = p[p0] + Z, p01 = p[p0 + 1] + Z, p1 = p[X + 1] + Y, p10 = p[p1] + Z, p11 = p[p1 + 1] + Z; - return lerp(fz, - lerp(fy, lerp(fx, grad3d(p[p00], x, y, z), grad3d(p[p10], x-1, y, z)), - lerp(fx, grad3d(p[p01], x, y-1, z), grad3d(p[p11], x-1, y-1,z))), - lerp(fy, lerp(fx, grad3d(p[p00 + 1], x, y, z-1), grad3d(p[p10 + 1], x-1, y, z-1)), - lerp(fx, grad3d(p[p01 + 1], x, y-1, z-1), grad3d(p[p11 + 1], x-1, y-1,z-1)))); + var X = Math.floor(x)&255, Y = Math.floor(y)&255, Z = Math.floor(z)&255; + x -= Math.floor(x); y -= Math.floor(y); z -= Math.floor(z); + var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y, fz = (3-2*z)*z*z; + var p0 = p[X]+Y, p00 = p[p0] + Z, p01 = p[p0 + 1] + Z, p1 = p[X + 1] + Y, p10 = p[p1] + Z, p11 = p[p1 + 1] + Z; + return lerp(fz, + lerp(fy, lerp(fx, grad3d(p[p00], x, y, z), grad3d(p[p10], x-1, y, z)), + lerp(fx, grad3d(p[p01], x, y-1, z), grad3d(p[p11], x-1, y-1,z))), + lerp(fy, lerp(fx, grad3d(p[p00 + 1], x, y, z-1), grad3d(p[p10 + 1], x-1, y, z-1)), + lerp(fx, grad3d(p[p01 + 1], x, y-1, z-1), grad3d(p[p11 + 1], x-1, y-1,z-1)))); }; this.noise2d = function(x, y) { - var X = Math.floor(x)&255, Y = Math.floor(y)&255; - x -= Math.floor(x); y -= Math.floor(y); - var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y; - var p0 = p[X]+Y, p1 = p[X + 1] + Y; - return lerp(fy, - lerp(fx, grad2d(p[p0], x, y), grad2d(p[p1], x-1, y)), - lerp(fx, grad2d(p[p0 + 1], x, y-1), grad2d(p[p1 + 1], x-1, y-1))); + var X = Math.floor(x)&255, Y = Math.floor(y)&255; + x -= Math.floor(x); y -= Math.floor(y); + var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y; + var p0 = p[X]+Y, p1 = p[X + 1] + Y; + return lerp(fy, + lerp(fx, grad2d(p[p0], x, y), grad2d(p[p1], x-1, y)), + lerp(fx, grad2d(p[p0 + 1], x, y-1), grad2d(p[p1 + 1], x-1, y-1))); }; this.noise1d = function(x) { - var X = Math.floor(x)&255; - x -= Math.floor(x); - var fx = (3-2*x)*x*x; - return lerp(fx, grad1d(p[X], x), grad1d(p[X+1], x-1)); + var X = Math.floor(x)&255; + x -= Math.floor(x); + var fx = (3-2*x)*x*x; + return lerp(fx, grad1d(p[X], x), grad1d(p[X+1], x-1)); }; } -// these are lifted from Processing.js +// these are lifted from Processing.js // processing defaults var noiseProfile = { generator: undefined, octaves: 4, fallout: 0.5, seed: undefined}; function noise(x, y, z) { if(noiseProfile.generator === undefined) { - // caching - noiseProfile.generator = new PerlinNoise(noiseProfile.seed); + // caching + noiseProfile.generator = new PerlinNoise(noiseProfile.seed); } var generator = noiseProfile.generator; var effect = 1, k = 1, sum = 0; for(var i=0; i 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; - - if (dmy > 0 && - curControllerContainerHeight > controllerHeight) { - var d = GUI.map(curControllerContainerHeight, controllerHeight, controllerHeight + 100, 1, 0); - dmy *= d; - } - - 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; + var open = false; + var width = 280; - }, false); - - - toggleButton.addEventListener('click', function(e) { - e.preventDefault(); - return false; - }, false); - - - document.addEventListener('mouseup', function(e) { - - if (togglePressed && !toggleDragged) { - - _this.toggle(); + // Prevents checkForOverflow bug in which loaded gui appearance + // settings are not respected by presence of scrollbar. + var explicitOpenHeight = false; - // 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) { + // How big we get when we open + var openHeight; + + var name; + + var resizeTo = 0; + var resizeTimeout; + + this.domElement = document.createElement('div'); + this.domElement.setAttribute('class', 'guidat'); + this.domElement.style.width = width+'px'; - 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; - } else { - openHeight = resizeTo; - beginResize(); - } - } - - - - } - - - document.removeEventListener('mousemove', resize, false); - e.preventDefault(); - toggleDragged = false; - togglePressed = false; - - return false; + var controllerContainer = document.createElement('div'); + controllerContainer.setAttribute('class', 'guidat-controllers'); + + // Firefox hack to prevent 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'; - }, false); - - this.domElement.appendChild(controllerContainer); - this.domElement.appendChild(toggleButton); + var toggleButton = document.createElement('a'); + toggleButton.setAttribute('class', 'guidat-toggle'); + toggleButton.setAttribute('href', '#'); + toggleButton.innerHTML = "Show Controls"; + + var toggleDragged = false; + var dragDisplacementY = 0; + var togglePressed = false; + + var my, pmy, mx, pmx; + + var resize = function(e) { + pmy = my; + pmx = mx; + my = e.pageY; + mx = e.pageX; + + 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; + + if (dmy > 0 && + curControllerContainerHeight > controllerHeight) { + var d = GUI.map(curControllerContainerHeight, controllerHeight, controllerHeight + 100, 1, 0); + dmy *= d; + } + + 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; - 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); - } + }, false); - this.autoListenIntervalTime = 1000/60; + toggleButton.addEventListener('click', function(e) { + e.preventDefault(); + return false; + }, false); - var createListenInterval = function() { - listenInterval = setInterval(function() { - _this.listen(); - }, this.autoListenIntervalTime); - } - - this.__defineSetter__("autoListen", function(v) { - autoListen = v; - if (!autoListen) { - clearInterval(listenInterval); - } else { - if (listening.length > 0) createListenInterval(); - } - }); - - this.__defineGetter__("autoListen", function(v) { - return autoListen; - }); - - this.listenTo = function(controller) { - // TODO: check for duplicates - if (listening.length == 0) { - createListenInterval(); - } - listening.push(controller); - }; - - this.unlistenTo = function(controller) { - // 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) { - var arr = whoToListenTo || listening; - for (var i in arr) { - arr[i].updateDisplay(); - } - }; - - this.listenAll = function() { - this.listen(controllers); - } - - this.autoListen = true; + document.addEventListener('mouseup', function(e) { + + if (togglePressed && !toggleDragged) { + _this.toggle(); + } + + if (togglePressed && toggleDragged) { + + if (dragDisplacementX == 0) { + adaptToScrollbar(); + } + + if (openHeight > controllerHeight) { + + clearTimeout(resizeTimeout); + openHeight = resizeTo = controllerHeight; + beginResize(); + + } else if (controllerContainer.children.length >= 1) { - var alreadyControlled = function(object, propertyName) { - for (var i in controllers) { - if (controllers[i].object == object && - controllers[i].propertyName == propertyName) { - return true; - } - } - return false; - }; + 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; + } 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() { + listenInterval = setInterval(function() { + _this.listen(); + }, this.autoListenIntervalTime); + }; + + this.__defineSetter__("autoListen", function(v) { + autoListen = v; + if (!autoListen) { + clearInterval(listenInterval); + } else { + if (listening.length > 0) createListenInterval(); + } + }); + + this.__defineGetter__("autoListen", function(v) { + return autoListen; + }); + + this.listenTo = function(controller) { + // TODO: check for duplicates + if (listening.length == 0) { + createListenInterval(); + } + listening.push(controller); + }; + + this.unlistenTo = function(controller) { + // 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) { + var arr = whoToListenTo || listening; + for (var i in arr) { + arr[i].updateDisplay(); + } + }; + + this.listenAll = function() { + this.listen(controllers); + } + + this.autoListen = true; + + var alreadyControlled = function(object, propertyName) { + for (var i in controllers) { + if (controllers[i].object == object && + controllers[i].propertyName == propertyName) { + return true; + } + } + return false; + }; - var construct = function(constructor, args) { - function F() { - return constructor.apply(this, args); - } - F.prototype = constructor.prototype; - return new F(); - }; - - this.add = function() { - - var object = arguments[0]; - var propertyName = arguments[1]; - - // Have we already added this? - if (alreadyControlled(object, propertyName)) { - // GUI.error("Controller for \"" + propertyName+"\" already added."); - // return; - } - - var value = object[propertyName]; - - // Does this value exist? Is it accessible? - if (value == undefined) { - GUI.error(object + " either has no property \""+propertyName+"\", or the property is inaccessible."); - return; - } - - var type = typeof value; - var handler = handlerTypes[type]; - - // Do we know how to deal with this data type? - if (handler == undefined) { - GUI.error("Cannot create controller for data type \""+type+"\""); - return; - } - - var args = [this]; // Set first arg (parent) to this - for (var j = 0; j < arguments.length; j++) { - args.push(arguments[j]); - } - - var controllerObject = construct(handler, args); - - // Were we able to make the controller? - if (!controllerObject) { - GUI.error("Error creating controller for \""+propertyName+"\"."); - return; - } - - // 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. - checkForOverflow(); - - // Prevents checkForOverflow bug in which loaded gui appearance - // settings are not respected by presence of scrollbar. - if (!explicitOpenHeight) { - openHeight = controllerHeight; - } - - 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"; - } - } - - var handlerTypes = { - "number": GUI.NumberController, - "string": GUI.StringController, - "boolean": GUI.BooleanController, - "function": GUI.FunctionController - }; - - var alreadyControlled = function(object, propertyName) { - for (var i in controllers) { - if (controllers[i].object == object && - controllers[i].propertyName == propertyName) { - return true; - } - } - return false; - }; - - var construct = function(constructor, args) { + var construct = function(constructor, args) { function F() { return constructor.apply(this, args); } @@ -379,84 +258,198 @@ var GUI = function() { return new F(); }; - this.reset = function() { - // TODO - } + this.add = function() { - // GUI ... GUI - - this.toggle = function() { - open ? this.hide() : this.show(); - }; + var object = arguments[0]; + var propertyName = arguments[1]; - this.show = function() { - toggleButton.innerHTML = name || "Hide Controls"; - resizeTo = openHeight; - clearTimeout(resizeTimeout); - beginResize(); - open = true; - } + // Have we already added this? + if (alreadyControlled(object, propertyName)) { + // GUI.error("Controller for \"" + propertyName+"\" already added."); + // return; + } - this.hide = function() { - toggleButton.innerHTML = name || "Show Controls"; - resizeTo = 0; - clearTimeout(resizeTimeout); - beginResize(); - open = false; - } - - this.name = function(n) { - name = n; - toggleButton.innerHTML = n; - } - - // used in saveURL - this.appearanceVars = function() { - return [open, width, openHeight, controllerContainer.scrollTop] - } - - 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'; - checkForOverflow(); - } - - // Load saved appearance: + var value = object[propertyName]; - if (GUI.guiIndex < GUI.savedAppearanceVars.length) { + // Does this value exist? Is it accessible? + if (value == undefined) { + GUI.error(object + " either has no property \""+propertyName+"\", or the property is inaccessible."); + return; + } - - width = parseInt(GUI.savedAppearanceVars[GUI.guiIndex][1]); - _this.domElement.style.width = width+"px"; - - openHeight = parseInt(GUI.savedAppearanceVars[GUI.guiIndex][2]); - explicitOpenHeight = true; - if (eval(GUI.savedAppearanceVars[GUI.guiIndex][0]) == true) { - curControllerContainerHeight = openHeight; - var t = GUI.savedAppearanceVars[GUI.guiIndex][3] - - // Hack. - setTimeout(function() { - controllerContainer.scrollTop = t; - }, 0); - - if (GUI.scrollTop > -1) { - document.body.scrollTop = GUI.scrollTop; - } - resizeTo = openHeight; - this.show(); - } + var type = typeof value; + var handler = handlerTypes[type]; - GUI.guiIndex++; - } + // Do we know how to deal with this data type? + if (handler == undefined) { + GUI.error("Cannot create controller for data type \""+type+"\""); + return; + } + + var args = [this]; // Set first arg (parent) to this + for (var j = 0; j < arguments.length; j++) { + args.push(arguments[j]); + } + + var controllerObject = construct(handler, args); + + // Were we able to make the controller? + if (!controllerObject) { + GUI.error("Error creating controller for \""+propertyName+"\"."); + return; + } - GUI.allGuis.push(this); + // 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. + checkForOverflow(); + + // Prevents checkForOverflow bug in which loaded gui appearance + // settings are not respected by presence of scrollbar. + if (!explicitOpenHeight) { + openHeight = controllerHeight; + } + + 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"; + } + }; + + var handlerTypes = { + "number": GUI.NumberController, + "string": GUI.StringController, + "boolean": GUI.BooleanController, + "function": GUI.FunctionController + }; + + var alreadyControlled = function(object, propertyName) { + for (var i in controllers) { + if (controllers[i].object == object && + controllers[i].propertyName == propertyName) { + return true; + } + } + return false; + }; + + var construct = function(constructor, args) { + + function F() { + return constructor.apply(this, args); + } + F.prototype = constructor.prototype; + return new F(); + }; + + this.reset = function() { + // TODO + } + + // GUI ... GUI + + this.toggle = function() { + open ? this.hide() : this.show(); + }; + + this.show = function() { + toggleButton.innerHTML = name || "Hide Controls"; + resizeTo = openHeight; + clearTimeout(resizeTimeout); + beginResize(); + open = true; + } + + this.hide = function() { + toggleButton.innerHTML = name || "Show Controls"; + resizeTo = 0; + clearTimeout(resizeTimeout); + beginResize(); + open = false; + } + + this.name = function(n) { + name = n; + toggleButton.innerHTML = n; + } + + // used in saveURL + this.appearanceVars = function() { + return [open, width, openHeight, controllerContainer.scrollTop] + } + + var beginResize = function() { + //console.log("Resizing from " + curControllerContainerHeight + " to " + resizeTo); + curControllerContainerHeight += (resizeTo - curControllerContainerHeight)*0.6; + if (Math.abs(curControllerContainerHeight-resizeTo) < 1) { + curControllerContainerHeight = resizeTo; + adaptToScrollbar(); + + } else { + resizeTimeout = setTimeout(beginResize, 1000/30); + } + controllerContainer.style.height = Math.round(curControllerContainerHeight)+'px'; + checkForOverflow(); + } + + var adaptToScrollbar = function() { + // Clears lingering slider column + _this.domElement.style.width = (width+1)+'px'; + setTimeout(function() { + _this.domElement.style.width = width+'px'; + }, 1); + }; + + // Load saved appearance: + + 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]); + explicitOpenHeight = true; + if (eval(GUI.savedAppearanceVars[GUI.guiIndex][0]) == true) { + curControllerContainerHeight = openHeight; + var t = GUI.savedAppearanceVars[GUI.guiIndex][3] + + // Hack. + setTimeout(function() { + controllerContainer.scrollTop = t; + }, 0); + + if (GUI.scrollTop > -1) { + document.body.scrollTop = GUI.scrollTop; + } + resizeTo = openHeight; + this.show(); + } + + GUI.guiIndex++; + } + + GUI.allGuis.push(this); }; @@ -467,27 +460,26 @@ GUI.autoPlaceContainer = null; GUI.allControllers = []; GUI.allGuis = []; -GUI.saveURL = function() { - title = window.location; - url = GUI.replaceGetVar("saveString", GUI.getSaveString()); - window.location = url; +GUI.saveURL = function() { + var url = GUI.replaceGetVar("saveString", GUI.getSaveString()); + window.location = url; }; GUI.scrollTop = -1; GUI.load = function(saveString) { - //GUI.savedAppearanceVars = []; - var vals = saveString.split(","); - var numGuis = parseInt(vals[0]); - GUI.scrollTop = parseInt(vals[1]); - for (var i = 0; i < numGuis; i++) { - var appr = vals.splice(2, 4); - GUI.savedAppearanceVars.push(appr); - } - - GUI.savedValues = vals.splice(2, vals.length); - + //GUI.savedAppearanceVars = []; + var vals = saveString.split(","); + var numGuis = parseInt(vals[0]); + GUI.scrollTop = parseInt(vals[1]); + for (var i = 0; i < numGuis; i++) { + var appr = vals.splice(2, 4); + GUI.savedAppearanceVars.push(appr); + } + + GUI.savedValues = vals.splice(2, vals.length); + }; GUI.savedValues = []; @@ -495,40 +487,41 @@ GUI.savedAppearanceVars = []; GUI.getSaveString = function() { - var vals = []; - - vals.push(GUI.allGuis.length); - vals.push(document.body.scrollTop); - - - for (var i in GUI.allGuis) { - var av = GUI.allGuis[i].appearanceVars(); - for (var j = 0; j < av.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); - - } - - return vals.join(','); - -} + var vals = [], + i; + + vals.push(GUI.allGuis.length); + vals.push(document.body.scrollTop); + + + for (i in GUI.allGuis) { + var av = GUI.allGuis[i].appearanceVars(); + for (var j = 0; j < av.length; j++) { + vals.push(av[j]); + } + } + + for (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); + + } + + return vals.join(','); + +}; GUI.getVarFromURL = function(v) { @@ -536,14 +529,14 @@ GUI.getVarFromURL = function(v) { var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { - hash = hashes[i].split("=") + hash = hashes[i].split("="); if (hash == undefined) continue; - if (hash[0] == v) { - return hash[1]; - } + if (hash[0] == v) { + return hash[1]; + } } - - return null; + + return null; }; @@ -554,69 +547,68 @@ GUI.replaceGetVar = function(varName, val) { var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { - hash = hashes[i].split("=") + hash = hashes[i].split("="); if (hash == undefined) continue; - if (hash[0] == varName) { - return loc.replace(hash[1], val); - } + if (hash[0] == varName) { + return loc.replace(hash[1], val); + } } - - if (window.location.href.indexOf('?') != -1) { - return loc + "&"+varName+"="+val; - } - - return loc+"?"+varName+"="+val; - + + if (window.location.href.indexOf('?') != -1) { + return loc + "&"+varName+"="+val; + } + + return loc+"?"+varName+"="+val; + }; GUI.saveIndex = 0; GUI.guiIndex = 0; GUI.showSaveString = function() { - alert(GUI.getSaveString()); -} + alert(GUI.getSaveString()); +}; // Util functions GUI.makeUnselectable = function(elem) { - elem.onselectstart = function() { return false; }; - elem.style.MozUserSelect = "none"; - elem.style.KhtmlUserSelect = "none"; - elem.unselectable = "on"; -} - + elem.onselectstart = function() { return false; }; + elem.style.MozUserSelect = "none"; + elem.style.KhtmlUserSelect = "none"; + elem.unselectable = "on"; +}; + GUI.makeSelectable = function(elem) { - elem.onselectstart = function() { }; - elem.style.MozUserSelect = "auto"; - elem.style.KhtmlUserSelect = "auto"; - elem.unselectable = "off"; -} + elem.onselectstart = function() { }; + elem.style.MozUserSelect = "auto"; + elem.style.KhtmlUserSelect = "auto"; + elem.unselectable = "off"; +}; GUI.map = function(v, i1, i2, o1, o2) { - var v = o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); - return v; -} + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +}; GUI.constrain = function (v, o1, o2) { - if (v < o1) v = o1; - else if (v > o2) v = o2; - return v; -} + if (v < o1) v = o1; + else if (v > o2) v = o2; + return v; +}; GUI.error = function(str) { - if (typeof console.error == 'function') { - console.error("[GUI ERROR] " + str); - } + if (typeof console.error == 'function') { + console.error("[GUI ERROR] " + str); + } }; GUI.roundToDecimal = function(n, decimals) { - var t = Math.pow(10, decimals); - return Math.round(n*t)/t; -} + var t = Math.pow(10, decimals); + return Math.round(n*t)/t; +}; GUI.extendController = function(clazz) { - clazz.prototype = new GUI.Controller(); - clazz.prototype.constructor = 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 +if (GUI.getVarFromURL('saveString') != null) GUI.load(GUI.getVarFromURL('saveString')); diff --git a/index.html b/index.html index fb2cd3f..11b8e86 100644 --- a/index.html +++ b/index.html @@ -1,34 +1,24 @@ - - - + gui-dat + - - - - - - - - - - + + + + + + + + + + + + @@ -116,10 +106,10 @@
- +
- +

GUI-DAT flag

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