boolean controller beginnings

This commit is contained in:
George Michael Brower 2014-08-23 03:05:22 -04:00
parent 6e09c30751
commit a4c6241d76
37 changed files with 1043 additions and 458 deletions

View File

@ -1,3 +1,3 @@
{ {
"directory": "../components" "directory": "../"
} }

132
README.md
View File

@ -1,8 +1,8 @@
# dat-gui # dat-gui
With very little code, dat gui creates an interface that you can use to modify variables. dat-gui creates an interface that you can use to modify variables with very little code.
## Basic Usage ### Basic Usage
Download the [minified library]( todo ) and include it in your html. Download the [minified library]( todo ) and include it in your html.
@ -10,23 +10,17 @@ Download the [minified library]( todo ) and include it in your html.
<script src="gui.js"></script> <script src="gui.js"></script>
``` ```
The following code makes a number box for the variable `object.someNumber`. Create controllers by adding objects and their properties. dat-gui chooses a controller based on the variable's initial value.
```javascript
var gui = new Gui();
gui.add( object, 'someNumber' );
```
dat-gui decides what type of controller to use based on the variable's initial value.
```javascript ```javascript
var gui = new Gui(); var gui = new Gui();
gui.add( object, 'numberProperty', 0, 1 ); // Slider
gui.add( object, 'stringProperty' ); // Text box gui.add( object, 'stringProperty' ); // Text box
gui.add( object, 'booleanProperty' ); // Check box gui.add( object, 'booleanProperty' ); // Check box
gui.add( object, 'functionProperty' ); // Button gui.add( object, 'functionProperty' ); // Button
``` ```
## Constraining Input ### Limiting Input
You can specify limits on numbers. A number with a min and max value becomes a slider. You can specify limits on numbers. A number with a min and max value becomes a slider.
@ -46,37 +40,27 @@ gui.add( text, 'message', [ 'pizza', 'chrome', 'hooray' ] );
gui.add( text, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 } ); gui.add( text, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 } );
``` ```
## Color Controllers ### Color Controllers
dat-gui has a color selector and understands many different representations of color. The following creates color controllers for color variables of different formats. dat-gui has a color selector and understands many different representations of color. The following creates color controllers for color variables of different formats.
```javascript ```javascript
var FizzyText = function() { text.color0 = "#ffae23"; // CSS string
text.color1 = [ 0, 128, 255 ]; // RGB array
text.color2 = [ 0, 128, 255, 0.3 ]; // RGB with alpha
text.color3 = { h: 350, s: 0.9, v: 0.3 }; // Hue, saturation, value
this.color0 = "#ffae23"; // CSS string var gui = new Gui();
this.color1 = [ 0, 128, 255 ]; // RGB array
this.color2 = [ 0, 128, 255, 0.3 ]; // RGB with alpha
this.color3 = { h: 350, s: 0.9, v: 0.3 }; // Hue, saturation, value
// Define render logic ... gui.addColor(text, 'color0');
gui.addColor(text, 'color1');
gui.addColor(text, 'color2');
gui.addColor(text, 'color3');
};
window.onload = function() {
var text = new FizzyText();
var gui = new Gui();
gui.addColor(text, 'color0');
gui.addColor(text, 'color1');
gui.addColor(text, 'color2');
gui.addColor(text, 'color3');
};
``` ```
## Events ### Events
You can listen for events on individual controllers using an event listener syntax. You can listen for events on individual controllers using an event listener syntax.
@ -93,9 +77,9 @@ controller.onFinishChange(function(value) {
}); });
``` ```
## Folders ### Folders & Comments
You can nest as many Gui's as you want. Nested Gui's act as collapsible folders. You can nest as many dat-gui as you want. Nested dat-gui act as collapsible folders.
```javascript ```javascript
var gui = new Gui(); var gui = new Gui();
@ -107,13 +91,17 @@ f1.add(text, 'noiseStrength');
var f2 = gui.addFolder('Letters'); var f2 = gui.addFolder('Letters');
f2.add(text, 'growthSpeed'); f2.add(text, 'growthSpeed');
f2.add(text, 'maxSize'); f2.add(text, 'maxSize');
f2.add(text, 'message');
f2.open(); f2.open();
``` ```
The comment method adds a tooltip to a controller.
## Saving Values ```javascript
f2.add(text, 'message').comment( 'This is the comment.' );
```
### Saving Values
Add a save menu to the interface by calling `gui.remember` on all the objects you've added to the Gui. Add a save menu to the interface by calling `gui.remember` on all the objects you've added to the Gui.
@ -126,20 +114,37 @@ gui.remember(fizzyText);
// Add controllers ... // Add controllers ...
``` ```
Click the gear icon to change your save settings. You can either save your Gui's values to localStorage, or by copying and pasting a JSON object into your source code as follows: Click the gear icon to change your save settings. You can either save your dat-gui values to localStorage, or by copying and pasting a JSON object into your source code as follows:
```javascript ```javascript
var fizzyText = new FizzyText(); var fizzyText = new FizzyText();
var gui = new Gui({ load: JSON }); var gui = new Gui( { load: JSON } );
gui.remember(fizzyText); gui.remember( fizzyText );
// Add controllers ... // Add controllers ...
``` ```
## Save to disk ### Presets
dat-gui comes with a node server that listens for changes to your Gui and saves them to disk. This way you don't have to worry about losing your local storage or copying and pasting a JSON string. The save menu also allows you to save all of your settings as presets. Click Save to modify the current preset, or New to create a new preset from existing settings. Clicking Revert will clear all unsaved changes to the current preset.
Switch between presets using the dropdown in the save menu. You can specify the default like this:
```javascript
var gui = new Gui({
load: JSON,
preset: 'Flow'
});
```
A word of caution about localStorage:
Paste the JSON save object into your source frequently. Using localStorage to save presets can make you faster, but its easy to lose your settings by clearing browsing data, changing browsers, or even by changing the URL of the page you're working on.
### Save to Disk
dat-gui comes with a node server that saves your settings to disk. This way you don't have to worry about losing your values to local storage or copying and pasting a JSON string.
First, run the node script: First, run the node script:
@ -147,20 +152,15 @@ First, run the node script:
$ node gui-server $ node gui-server
``` ```
Next, instantiate your Gui with a path to a JSON file to store settings. Next, instantiate your Gui with a path to a JSON file to store settings. dat-gui will read from this file on load and write to this file on change.
```javascript ```javascript
var gui = new Gui( { save: 'path/to/file.json' } ); var gui = new Gui( { load: 'path/to/file.json' } );
gui.remember( fizzyText );
// Add controllers ...
``` ```
## Custom Placement ### Custom Placement
By default, Gui panels are created with fixed position, and are automatically appended to the body. By default, Gui panels are created with fixed position, and are automatically appended to the body. You can change this behavior by setting the `autoPlace` parameter to `false`.
You can change this behavior by setting the `autoPlace` parameter to `false`.
```javascript ```javascript
var gui = new Gui( { autoPlace: false } ); var gui = new Gui( { autoPlace: false } );
@ -169,18 +169,16 @@ var customContainer = document.getElementById('my-gui-container');
customContainer.appendChild(gui.domElement); customContainer.appendChild(gui.domElement);
``` ```
## HTML Elements Since dat-gui is built using [Web Components]( todo ), you can also use HTML syntax to add controllers to the page.
Since dat-gui is built using [Web Components]( todo ), you can use HTML syntax to add controllers to the page.
```html ```html
<body> <body>
<controller-number id="my-controller" min="-2" max="2" step="1" value="0"></controller-number> <controller-number min="-2" max="2" step="1" value="0"></controller-number>
<script> <script>
var controller = document.getElementById( 'my-controller' ); var controller = document.querySelector( 'controller-number' );
controller.onChange( function() { controller.onChange( function() {
// react to UI changes ... // react to UI changes ...
@ -192,7 +190,8 @@ controller.onChange( function() {
</body> </body>
``` ```
## Defining Custom Controllers
### Defining Custom Controllers
dat-gui uses [Polymer]( todo ) under the hood to define custom elements. A dat-gui controller is just a [Polymer element]( todo ) with two important requirements: dat-gui uses [Polymer]( todo ) under the hood to define custom elements. A dat-gui controller is just a [Polymer element]( todo ) with two important requirements:
@ -215,9 +214,9 @@ Gui.register( 'controller-number', function( value ) {
} ); } );
``` ```
`Gui.register` takes an element name and a test function. The call to `Gui.register` tells dat-gui to add a `<controller-number>` to the panel when the user adds a variable whose type is `'number'`. `Gui.register` takes an element name and a test function. The test function tells dat-gui to add a `<controller-number>` to the panel when the user adds a variable whose type is `'number'`.
A test function takes a value added with `gui.add` and returns a boolean that determines if the controller is appropriate for the value. This example uses [duck typing]( todo ) to register `<vector-controller>` for values that have properties `x`, `y` and `z`. A test function determines if a controller is appropriate for a given value. This example registers `<vector-controller>` for values that have properties `x`, `y` and `z`.
```javascript ```javascript
Gui.register( 'vector-controller', function( value ) { Gui.register( 'vector-controller', function( value ) {
@ -229,6 +228,19 @@ Gui.register( 'vector-controller', function( value ) {
} ); } );
``` ```
## Publishing Custom Controllers ### Publishing Custom Controllers
You should use bower and format your plugin all nice and it should have a certain prefix yada yada. You should use [Bower]( todo ) and format your plugin all nice and it should have a certain prefix yada yada.
Installing third-party controllers ...
```sh
$ bower install gui-three
```
Include the source for the third-party controllers after dat-gui.
```html
<script src="gui.js"></script>
<script src="gui-three.js"></script>
```

10
TODO Normal file
View File

@ -0,0 +1,10 @@
- [ ] can gui-row be baked into base-controller somehow?
- [ ] folders
- [ ] string controller
- [ ] boolean controller
- [ ] function controller
- [ ] color controller

View File

@ -1,7 +1,7 @@
{ {
"name": "polymer-gui", "name": "polymer-gui",
"version": "0.0.0", "version": "0.0.0",
"description": "Attempt at revamping dat.gui with Polymyer.", "description": "Attempt at revamping dat.gui with Polymer.",
"keywords": [ "keywords": [
"gui" "gui"
], ],
@ -19,5 +19,8 @@
], ],
"dependencies": { "dependencies": {
"polymer": "Polymer/polymer#~0.3.5" "polymer": "Polymer/polymer#~0.3.5"
},
"devDependencies": {
"underscore": "~1.6.0"
} }
} }

File diff suppressed because one or more lines are too long

32
docs/examples.js Normal file
View File

@ -0,0 +1,32 @@
var examples = {};
examples[ 'default' ] = function() {
var gui = new Gui();
gui.anon( 'hi', 'todo' );
return gui;
}
// "basic-usage", "limiting-input", "color-controllers", "events", "folders-comments", "saving-values", "presets", "save-to-disk", "custom-placement", "defining-custom-controllers", "publishing-custom-controllers"
examples[ 'basic-usage' ] = function() {
var gui = new Gui();
var object = {
numberProperty: 0,
stringProperty: 'hey',
booleanProperty: false,
functionProperty: function() {
}
}
gui.add( object, 'numberProperty', 0, 1 ); // Slider
gui.add( object, 'stringProperty' ); // Text box
gui.add( object, 'booleanProperty' ); // Check box
gui.add( object, 'functionProperty' ); // Button
return gui;
};

132
docs/main.js Normal file
View File

@ -0,0 +1,132 @@
Gui.ready( init );
function init() {
var elements = document.querySelectorAll( '#readme h3' );
for ( var i = 0; i < elements.length; i++ ) {
var initExample = examples[ elements[i].id ] || examples['default'];
elements[i].example = initExample();
}
sticky( elements );
}
// Sticky headers
// -------------------------------
function sticky( elements ) {
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
el = elements[ i ];
el.sticky = el.cloneNode( true );
el.sticky.removeAttribute( 'id' );
el.sticky.style.position = 'fixed';
el.sticky.style.visibility = 'hidden';
el.sticky.style.zIndex = i;
el.sticky.classList.add( 'sticky' );
el.parentElement.insertBefore( el.sticky, el );
measure( el );
if ( i > 0 ) {
elements[ i - 1 ].next = el;
}
}
function measure( el ) {
el.top = el.offsetTop;
el.sticky.height = el.sticky.offsetHeight;
}
function resize() {
for ( var i = 0, l = elements.length; i < l; i++ ) {
measure( elements[ i ] );
}
}
function onScroll() {
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
el = elements[ i ];
var sticky = window.scrollY > el.top && window.scrollY <= el.next.top;
el.sticky.style.visibility = sticky ? 'visible' : 'hidden';
el.example.classList.toggle( 'sticky', sticky || el.bumped );
if ( el.next ) el.next.bumped = false;
if ( el.next && sticky ) {
var bottom = window.scrollY + el.sticky.height;
var bumped = bottom > el.next.top;
el.sticky.style.marginTop = Math.round( Math.min( 0, el.next.top - bottom ) ) + 'px';
el.sticky.classList.toggle( 'sticky-prev', bumped );
el.next.classList.toggle( 'sticky-next', bumped );
if ( bumped ) {
el.example.classList.remove( 'sticky' );
el.next.example.classList.add( 'sticky' );
el.next.bumped = true;
}
}
}
}
document.addEventListener( 'scroll', onScroll );
// should debounce
window.addEventListener( 'resize', function() {
resize();
onScroll();
});
onScroll();
}
// Smooth scroll
(function() {
var body = document.body, timer;
window.addEventListener('scroll', function() {
clearTimeout(timer);
if(!body.classList.contains('disable-hover')) {
body.classList.add('disable-hover')
}
timer = setTimeout(function(){
body.classList.remove('disable-hover')
}, 150);
}, false);
})();

78
docs/style.styl Normal file
View File

@ -0,0 +1,78 @@
@import '../elements/shared.styl';
unit = 18px
body-padding = unit * 2;
readme-margin = panel-width + body-padding;
* {
margin: 0;
}
body {
margin: body-padding;
line-height: 24px;
}
.disable-hover,
.disable-hover * {
pointer-events: none !important;
}
h1, h2, h3, h4, p, pre {
margin-bottom: unit;
}
pre {
width: 100%;
margin-bottom: unit * 2;
line-height: 20px;
}
h1 {
margin-bottom: unit * 3;
}
h3 {
padding: unit 0;
margin-bottom: unit * 2;
border-bottom: 1px solid rgba( 0, 0, 0, 0.2 );
transition: border-color 0.2s linear, color 0.2s linear;
&.sticky {
left: body-padding;
right: body-padding + readme-margin;
top: 0;
background: #fff;
&.sticky-prev {
color: #eee;
border-bottom: 1px solid rgba( 0, 0, 0, 0 );
}
}
}
#readme {
margin-right: readme-margin;
}
gui-panel {
position: fixed;
width: panel-width;
top: 0px;
right: unit;
z-index: 9999;
transition: transform 0.4s cubic-bezier(.5,1,0,1);
transform: translate3d( 0, -200px, 0 );
&.sticky {
transform: translate3d( 0, 0, 0 );
transition-delay: 400ms;
}
}

View File

@ -1,102 +1,25 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="utf-8">
<title>dat-gui</title> <title>dat-gui</title>
<style> <link rel="import" href="gui.html">
* { <link rel="stylesheet" href="docs/style.css">
margin: 0;
}
body {
margin: 18px;
}
h1, h2, h3, p, pre {
margin-bottom: 18px;
}
h1 {
margin-bottom: 36px;
}
h2 {
padding: 18px 0;
margin-top: 36px;
margin-bottom: 36px;
}
h2.sticky {
border-bottom: 1px solid rgba( 0, 0, 0, 0.25 );
left: 0;
right: 0;
top: 0;
padding: 18px;
background: #fff;
}
</style> </style>
</head> </head>
<body> <body>
<div id="readme"> <div id="readme"><!-- Replaced with contents of README.md --></div>
<!-- Replaced with contents of README.md -->
</div>
<script> <script src="../underscore/underscore.js"></script>
(function() {
var selector = '#readme h2';
var elements = document.querySelectorAll( selector );
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
el = elements[ i ]; <script src="docs/main.js"></script>
el.top = el.offsetTop; <script src="docs/examples.js"></script>
el.spacer = el.cloneNode( true );
el.spacer.id = '';
el.spacer.style.position = 'fixed';
el.spacer.style.visibility = 'hidden';
el.spacer.style.zIndex = i;
el.spacer.classList.add( 'sticky' );
el.parentElement.insertBefore( el.spacer, el );
el.spacer.height = el.spacer.offsetHeight;
if ( i > 0 ) {
elements[ i - 1 ].next = el;
}
}
function onScroll() {
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
el = elements[ i ];
var sticky = window.scrollY > el.top && window.scrollY <= el.next.top;
el.spacer.style.visibility = sticky ? 'visible' : 'hidden';
if ( el.next && sticky ) {
var bottom = window.scrollY + el.spacer.height;
var marginTop = Math.round( Math.min( 0, el.next.top - bottom ) );
el.spacer.style.marginTop = marginTop + 'px';
el.spacer.classList.toggle( -marginTop );
}
}
}
document.addEventListener( 'scroll', onScroll );
})();
</script>
</body> </body>
</html> </html>

View File

@ -1,22 +1,41 @@
(function( scope ) { (function( scope ) {
var Gui = function() { var ready = false;
var readyHandlers = [];
var controllers = {};
var Gui = function( params ) {
if ( !ready ) {
Gui.error( 'Gui not ready. Put your code inside Gui.ready()' );
}
params = params || {};
var panel = document.createElement( 'gui-panel' ); var panel = document.createElement( 'gui-panel' );
document.body.appendChild( panel );
panel.autoPlace = params.autoPlace !== false;
if ( panel.autoPlace ) {
document.body.appendChild( panel );
}
return panel; return panel;
}; };
// Register custom controllers // Register custom controllers
// ------------------------------- // -------------------------------
var controllers = {};
Gui.register = function( elementName, test ) { Gui.register = function( elementName, test ) {
controllers[ elementName ] = test; controllers[ elementName ] = test;
}; };
// Returns a controller based on a value // Returns a controller based on a value
// ------------------------------- // -------------------------------
@ -37,6 +56,43 @@
}; };
// Gui ready handler ... * shakes fist at polymer *
// -------------------------------
document.addEventListener( 'polymer-ready', function() {
ready = true;
readyHandlers.forEach( function( fnc ) {
fnc();
} );
} );
Gui.ready = function( fnc ) {
ready ? fnc() : readyHandlers.push( fnc );
};
// Error
// -------------------------------
Gui.error = function() {
var args = Array.prototype.slice.apply( arguments );
args.unshift( 'dat-gui ::' );
console.error.apply( console, args );
}
Gui.warn = function() {
var args = Array.prototype.slice.apply( arguments );
args.unshift( 'dat-gui ::' );
console.warn.apply( console, args );
}
// Old namespaces // Old namespaces
// ------------------------------- // -------------------------------

View File

@ -1,4 +1,4 @@
<link rel="import" href="../../../components/polymer/polymer.html"> <link rel="import" href="../../../polymer/polymer.html">
<script src="controller-base.js"></script> <script src="controller-base.js"></script>

View File

@ -70,7 +70,7 @@ Polymer('controller-base', {
listen: function() { listen: function() {
console.warn( 'controller.listen() is deprecated. All controllers are listened for free.' ); Gui.warn( 'controller.listen() is deprecated. All controllers are listened for free.' );
return this; return this;
}, },

View File

@ -0,0 +1,21 @@
<link rel="import" href="../../../polymer/polymer.html">
<link rel="import" href="../controller-base/controller-base.html">
<script src="controller-boolean.js"></script>
<polymer-element
name="controller-boolean"
extends="controller-base"
>
<template>
<link rel="stylesheet" href="controller-boolean.css">
<label for="input" id="container">
<input id="input" type="checkbox" checked?="{{ value }}" on-change="{{ change }}">
</label>
</template>
</polymer-element>

View File

@ -0,0 +1,22 @@
Gui.register( 'controller-boolean', function( value ) {
return typeof value == 'boolean';
} );
Polymer( 'controller-boolean', {
ready: function() {
},
change: function() {
this.value = this.$.input.checked;
}
});

View File

@ -0,0 +1,11 @@
@import '../shared';
#container, #input {
cursor: pointer;
}
#container {
display: block;
border: 1px solid blue;
height: row-height;
}

View File

@ -0,0 +1,20 @@
<link rel="import" href="../../../polymer/polymer.html">
<link rel="import" href="../controller-base/controller-base.html">
<script src="controller-function.js"></script>
<polymer-element
name="controller-function"
extends="controller-base"
>
<template>
<link rel="stylesheet" href="controller-function.css">
<div id="container">
</div>
</template>
</polymer-element>

View File

@ -0,0 +1,9 @@
Gui.register( 'controller-function', function( value ) {
return typeof value == 'function';
} );
Polymer( 'controller-function', {
} );

View File

@ -1,4 +1,4 @@
<link rel="import" href="../../../components/polymer/polymer.html"> <link rel="import" href="../../../polymer/polymer.html">
<link rel="import" href="../controller-base/controller-base.html"> <link rel="import" href="../controller-base/controller-base.html">
<script src="controller-number.js"></script> <script src="controller-number.js"></script>

View File

@ -1,7 +1,6 @@
/* /*
[ ] arrow keys [ ] arrow keys
[ ] min( ) max( ) step( ) commands of yore [ ] min( ) max( ) step( ) commands of yore
[x] only validate input box on blur, not on keydown [x] only validate input box on blur, not on keydown

View File

@ -76,8 +76,8 @@ knob-size = 6px
input { input {
font(); panel-font()
color: text-color;
height: track-height; height: track-height;
display: inline-block; display: inline-block;
@ -87,6 +87,7 @@ input {
.slider-true & { .slider-true & {
text-align: center;
margin-left: padding; margin-left: padding;
width: 100%; width: 100%;
width: 22%; width: 22%;
@ -102,8 +103,13 @@ input {
} }
.slider-false & {
// border-bottom: 1px solid number-color;
}
} }
input::selection { input::selection {
background-color: light; background-color: rgba( 255, 255, 255, 0.1 );
} }

View File

@ -0,0 +1,20 @@
<link rel="import" href="../../../polymer/polymer.html">
<link rel="import" href="../controller-base/controller-base.html">
<script src="controller-string.js"></script>
<polymer-element
name="controller-string"
extends="controller-base"
>
<template>
<link rel="stylesheet" href="controller-string.css">
<div id="container">
</div>
</template>
</polymer-element>

View File

@ -0,0 +1,9 @@
Gui.register( 'controller-string', function( value ) {
return typeof value == 'string';
} );
Polymer( 'controller-string', {
});

View File

@ -1,17 +1,19 @@
<link rel="import" href="../../../components/polymer/polymer.html"> <link rel="import" href="../../../polymer/polymer.html">
<link rel="import" href="../gui-row/gui-row.html"> <link rel="import" href="../gui-row/gui-row.html">
<polymer-element <polymer-element
name="gui-panel" name="gui-panel"
attributes="docked"> attributes="docked autoplace open">
<template> <template>
<link rel="stylesheet" href="gui-panel.css"> <link rel="stylesheet" href="gui-panel.css">
<div id="container" class="docked-{{ docked }}"> <div id="container" class="docked-{{ docked }} autoplace-{{ autoPlace }} open-{{ open }}">
<content></content> <div id="controllers">
<div id="closeButton" hidden?="{{ docked }}">&times;</div> <content></content>
</div>
<div id="closeButton" on-tap="{{ tapClose }}" hidden?="{{ docked }}">{{ open ? 'Close' : 'Open' }} Controls</div>
</div> </div>
</template> </template>

View File

@ -1,19 +1,32 @@
/*
[ ] kill horizontal scroll when docked
*/
Polymer('gui-panel', { Polymer('gui-panel', {
docked: false, docked: false,
open: true,
ready: function() { ready: function() {
this.anon.values = {}; this.anon.values = {};
window.addEventListener( 'resize', this.checkHeight.bind( this ) );
}, },
anon: function( name, initialValue ) { anon: function() {
if ( arguments.length == 1 ) { if ( arguments.length == 1 ) {
var name = arguments[ 0 ];
return this.anon.values[ name ]; return this.anon.values[ name ];
} }
var initialValue = arguments[ 0 ];
var name = arguments[ 1 ];
var args = [ this.anon.values, name ]; var args = [ this.anon.values, name ];
args = args.concat( Array.prototype.slice.call( arguments, 2 ) ); args = args.concat( Array.prototype.slice.call( arguments, 2 ) );
@ -30,7 +43,7 @@ Polymer('gui-panel', {
var value = Path.get( path ).getValueFrom( object ); var value = Path.get( path ).getValueFrom( object );
if ( value == null || value == undefined ) { if ( value == null || value == undefined ) {
return console.error( object + ' doesn\'t have a value for path "' + path + '".' ); return Gui.error( object + ' doesn\'t have a value for path "' + path + '".' );
} }
var args = Array.prototype.slice.call( arguments, 2 ); var args = Array.prototype.slice.call( arguments, 2 );
@ -38,7 +51,7 @@ Polymer('gui-panel', {
var controller = Gui.getController( value, args ); var controller = Gui.getController( value, args );
if ( !controller ) { if ( !controller ) {
return console.error( 'Unrecognized type: ', value ); return Gui.error( 'Unrecognized type:', value );
} }
controller.watch( object, path ) controller.watch( object, path )
@ -64,10 +77,45 @@ Polymer('gui-panel', {
}, },
openChanged: function() {
var y;
if ( this.open ) {
y = 0;
} else {
y = -this.$.controllers.offsetHeight + 'px';
}
this.$.container.style.transform = 'translate3d(0, ' + y + ', 0)';
},
// Events
// -------------------------------
tapClose: function() {
this.open = !this.open;
},
checkHeight: function() {
if ( window.innerHeight < this.$.controllers.offsetHeight ) {
this.docked = true;
} else {
this.docked = false;
}
},
// Legacy
// -------------------------------
listenAll: function() { listenAll: function() {
console.warn( 'controller.listenAll() is deprecated. All controllers are listened for free.' ); Gui.warn( 'controller.listenAll() is deprecated. All controllers are listened for free.' );
} },
// domElement
}); });

View File

@ -2,20 +2,26 @@
#closeButton { #closeButton {
font(); panel-font()
font-size: 14px;
color: text-color;
// font-size: 14px;
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
padding: padding*0.4 padding; padding: padding * 0.75 padding;
background: black;
} }
#container { #container {
background: #1a1a1a; background: panel-color;
position: fixed;
top: 0; &.autoplace-true {
width: 270px; width: panel-width;
position: fixed;
top: 0;
}
&.docked-false { &.docked-false {
right: 20px; right: 20px;
@ -24,6 +30,9 @@
&.docked-true { &.docked-true {
right: 0; right: 0;
bottom: 0; bottom: 0;
overflow: auto;
} }
transition: transform 0.4s cubic-bezier( 0, 0.8, 0, 1 );
} }

View File

@ -1,4 +1,4 @@
<link rel="import" href="../../../components/polymer/polymer.html"> <link rel="import" href="../../../polymer/polymer.html">
<polymer-element name="gui-row" attributes="name comment"> <polymer-element name="gui-row" attributes="name comment">

View File

@ -18,12 +18,10 @@ Polymer('gui-row', {
openComment: function() { openComment: function() {
this.commentOpen = true; this.commentOpen = true;
this.$.comment.style.height = this.$.commentInner.offsetHeight + 'px';
}, },
closeComment: function() { closeComment: function() {
this.commentOpen = false; this.commentOpen = false;
this.$.comment.style.height = '';
} }
}); });

View File

@ -8,12 +8,15 @@
width: 100%; width: 100%;
display: block; display: block;
font(); panel-font()
} }
#row { #row {
transition: background-color 0.2s linear;
&:hover {
background-color: #262626;
}
} }
#comment { #comment {
@ -36,7 +39,7 @@
pointer-events: none; pointer-events: none;
opacity: 0; opacity: 0;
transform: translate3d( 10px, 20px, 0 ); transform: translate3d( 0, 20px, 0 );
transition: all 0.2s ease; transition: all 0.2s ease;
@ -45,7 +48,8 @@
#comment.open-true { #comment.open-true {
opacity: 1; opacity: 1;
transform: translate3d( 10px, 0, 0 ); transition-delay: 200ms;
transform: translate3d( 0, 0, 0 );
} }

View File

@ -1,15 +1,19 @@
@import 'nib'; @import 'nib';
panel-width = 245px
font-color = #eee
panel-color = #1a1a1a
number-color = #25a0d8 number-color = #25a0d8
padding = 10px padding = 8px
ease = cubic-bezier( .25, .25, 0, 1 ) ease = cubic-bezier( .25, .25, 0, 1 )
light = rgba( 255, 255, 255, 0.25 ) light = rgba( 255, 255, 255, 0.25 )
dark = rgba( 0, 0, 0, 0.1 ); dark = rgba( 0, 0, 0, 0.1 );
font() panel-font()
font: 500 11px 'Roboto', sans-serif; font: 10px 'Lucida Grande', sans-serif;
color: #fff; color: font-color;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;

View File

@ -1,4 +1,4 @@
<link rel="import" href="../../../components/polymer/polymer.html"> <link rel="import" href="../../../polymer/polymer.html">
<link rel="import" href="../../elements/controller-number/controller-number.html"> <link rel="import" href="../../elements/controller-number/controller-number.html">
<polymer-element name="controller-vector" extends="controller-base"> <polymer-element name="controller-vector" extends="controller-base">

View File

@ -1,67 +1,67 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<!-- <link rel="import" href="build/gui.html"> --> <meta charset="utf-8">
<link rel="import" href="../gui.html"> <title>dat-gui kitchen sink</title>
<style type="text/css"> <script>
* { var src = '../gui.html';
margin: 0; if ( location.search == '?built' ) src = '../build/gui.html';
} document.write( '<link rel="import" href="'+src+'">' );
body, html { </script>
height: 100%;
font-size: 0; <style type="text/css">
} </style>
iframe {
height: 100%;
width: 50%;
}
</style>
</head> </head>
<body> <body>
<script> body content.
var object = {
"listen4Free": 332,
"zeroTo1": 0,
"step": 10,
"straddleZero": 0,
"maxIsNegative": -2,
"hasComment": 0
};
// How do we kill polymer-ready ... <script>
document.addEventListener( 'polymer-ready', function() {
var gui = new dat.GUI(); var object = {
"listen4Free": 332,
// gui.docked = true; "zeroTo1": 0,
"step": 10,
"straddleZero": 0,
"maxIsNegative": -2,
"hasComment": 0
};
gui.add( object, 'listen4Free' ); // How do we kill polymer-ready ...
gui.add( object, 'listen4Free' ); Gui.ready( function() {
gui.add( object, 'listen4Free' );
gui.add( object, 'zeroTo1', 0, 1 );
gui.add( object, 'hasComment' ).comment( 'Hi there.' );
gui.add( object, 'listen4Free' ).name( 'customName' ) gui = new dat.GUI();
gui.add( object, 'step', 0, 50, 5 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus, sed aliquet nulla fermentum nec. Sed massa felis, congue nec libero ut, condimentum hendrerit purus. Cras a cursus ante. Integer nec nibh vitae lacus convallis viverra in at urna. Donec hendrerit convallis lacus, nec condimentum neque aliquam ac. Sed suscipit leo vel ligula condimentum scelerisque. Aliquam fermentum sagittis nisi vitae accumsan. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In et dolor eros. Sed vel venenatis odio, quis porta mi. Ut sed commodo velit, in porta ante.' ); gui.add( gui, 'docked' );
gui.add( object, 'listen4Free' );
gui.add( object, 'listen4Free' );
gui.add( object, 'listen4Free' );
gui.add( object, 'straddleZero', -1, 1, 0.01 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus, sed aliquet nulla fermentum nec. ' ); gui.add( object, 'zeroTo1', 0, 1 );
gui.add( object, 'hasComment' ).comment( 'Hi there.' );
gui.add( object, 'maxIsNegative', -5, -2 ); gui.add( object, 'listen4Free' ).name( 'customName' )
gui.anon( 'anonymousSlider', 0, -1, 1 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus'); gui.add( object, 'step', 0, 50, 5 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus, sed aliquet nulla fermentum nec. Sed massa felis, congue nec libero ut, condimentum hendrerit purus. Cras a cursus ante. Integer nec nibh vitae lacus convallis viverra in at urna. Donec hendrerit convallis lacus, nec condimentum neque aliquam ac. Sed suscipit leo vel ligula condimentum scelerisque. Aliquam fermentum sagittis nisi vitae accumsan. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In et dolor eros. Sed vel venenatis odio, quis porta mi. Ut sed commodo velit, in porta ante.' );
// gui.add( 32, 'beats', 1, 64, 1 ).comment( 'The number of beats in the song.'); gui.add( object, 'straddleZero', -1, 1, 0.01 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus, sed aliquet nulla fermentum nec.' );
// gui.add( 0, 'loops', -2, 2, 1 ).comment( 'The number of times the gif loops in a cycle.' );
// gui.add( 0, 'start', -2, 2, 1 ).comment( 'The frame of the gif where the song should start.' );
}); gui.add( object, 'maxIsNegative', -5, -2 );
</script>
gui.anon( 0, 'anonymousSlider', -1, 1 ).comment( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper dui metus');
gui.anon( 32, 'beats', 1, 64, 1 ).comment( 'The number of beats in the song.');
gui.anon( 0, 'loops', -2, 2, 1 ).comment( 'The number of times the gif loops in a cycle.' );
gui.anon( 0, 'start', -2, 2, 1 ).comment( 'The frame of the gif where the song should start.' );
});
</script>
</body> </body>
</html> </html>

View File

@ -1,14 +1,14 @@
<!-- platform --> <script src="../platform/platform.js"></script>
<script src="../components/platform/platform.js"></script>
<!-- font -->
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto" type="text/css">
<!-- src --> <!-- src -->
<script src="elements/Gui.js"></script> <script src="elements/Gui.js"></script>
<!-- elements --> <!-- base elements -->
<link rel="import" href="elements/gui-panel/gui-panel.html"> <link rel="import" href="elements/gui-panel/gui-panel.html">
<link rel="import" href="elements/gui-row/gui-row.html"> <link rel="import" href="elements/gui-row/gui-row.html">
<link rel="import" href="elements/controller-number/controller-number.html"> <!-- controllers -->
<link rel="import" href="elements/controller-number/controller-number.html">
<link rel="import" href="elements/controller-string/controller-string.html">
<link rel="import" href="elements/controller-boolean/controller-boolean.html">
<link rel="import" href="elements/controller-function/controller-function.html">

View File

@ -13,14 +13,19 @@ var paths = {
css: 'elements/**/*.styl', css: 'elements/**/*.styl',
html: 'elements/**/*.html', html: 'elements/**/*.html',
js: 'elements/**/*.js', js: 'elements/**/*.js',
tests: 'tests/*' }
function stylus( src, dest ) {
gulp.src( src )
.pipe( $.stylus( { use: [ $.nib() ] } ) )
.pipe( gulp.dest( dest ) );
} }
gulp.task( 'css', function() { gulp.task( 'css', function() {
gulp.src( paths.css ) stylus( paths.css, 'elements' );
.pipe( $.stylus( { use: [ $.nib() ] } ) )
.pipe( gulp.dest( 'elements' ) );
} ); } );
@ -35,8 +40,9 @@ gulp.task( 'vulcanize', function() {
} ); } );
gulp.task( 'readme', function() { gulp.task( 'docs', function() {
stylus( 'docs/*.styl', 'docs' );
var content = { var content = {
readme: $.marked( fs.readFileSync( 'README.md', 'utf8' ) ) readme: $.marked( fs.readFileSync( 'README.md', 'utf8' ) )
@ -53,16 +59,15 @@ gulp.task( 'test', function() {
} ); } );
gulp.task( 'build', [ 'css', 'vulcanize', 'test' ] ); gulp.task( 'build', [ 'css', 'vulcanize', 'test', 'docs' ] );
gulp.task( 'default', function() { gulp.task( 'default', function() {
gulp.task( 'build' );
gulp.watch( [ paths.css ], [ 'css', 'vulcanize' ] ); gulp.watch( [ paths.css ], [ 'css', 'vulcanize' ] );
gulp.watch( [ paths.js, paths.main, paths.html ], [ 'vulcanize', 'test' ] ); gulp.watch( [ paths.js, paths.main, paths.html ], [ 'vulcanize', 'test' ] );
gulp.watch( [ 'README.md', 'docs/*' ], [ 'docs' ] );
// gulp.watch( [ paths.tests, 'test' ] ); // not working?
gulp.watch( [ 'README.md', 'docs/template.html' ], [ 'readme' ] );
} ); } );

View File

@ -1,64 +1,33 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="utf-8">
<title>dat-gui</title> <title>dat-gui</title>
<style> <link rel="import" href="gui.html">
* { <link rel="stylesheet" href="docs/style.css">
margin: 0;
}
body {
margin: 18px;
}
h1, h2, h3, p, pre {
margin-bottom: 18px;
}
h1 {
margin-bottom: 36px;
}
h2 {
padding: 18px 0;
margin-top: 36px;
margin-bottom: 36px;
}
h2.sticky {
border-bottom: 1px solid rgba( 0, 0, 0, 0.25 );
left: 0;
right: 0;
top: 0;
padding: 18px;
background: #fff;
}
</style> </style>
</head> </head>
<body> <body>
<div id="readme"><h1 id="dat-gui">dat-gui</h1> <div id="readme"><h1 id="dat-gui">dat-gui</h1>
<p>With very little code, dat gui creates an interface that you can use to modify variables.</p> <p>dat-gui creates an interface that you can use to modify variables with very little code. </p>
<h2 id="basic-usage">Basic Usage</h2> <h3 id="basic-usage">Basic Usage</h3>
<p>Download the <a href="todo">minified library</a> and include it in your html.</p> <p>Download the <a href="todo">minified library</a> and include it in your html.</p>
<pre><code class="lang-html">&lt;script src=&quot;gui.js&quot;&gt;&lt;/script&gt; <pre><code class="lang-html">&lt;script src=&quot;gui.js&quot;&gt;&lt;/script&gt;
</code></pre> </code></pre>
<p>The following code makes a number box for the variable <code>object.someNumber</code>.</p> <p>Create controllers by adding objects and their properties. dat-gui chooses a controller based on the variable&#39;s initial value.</p>
<pre><code class="lang-javascript">var gui = new Gui();
gui.add( object, &#39;someNumber&#39; );
</code></pre>
<p>dat-gui decides what type of controller to use based on the variable&#39;s initial value.</p>
<pre><code class="lang-javascript">var gui = new Gui(); <pre><code class="lang-javascript">var gui = new Gui();
gui.add( object, &#39;numberProperty&#39;, 0, 1 ); // Slider
gui.add( object, &#39;stringProperty&#39; ); // Text box gui.add( object, &#39;stringProperty&#39; ); // Text box
gui.add( object, &#39;booleanProperty&#39; ); // Check box gui.add( object, &#39;booleanProperty&#39; ); // Check box
gui.add( object, &#39;functionProperty&#39; ); // Button gui.add( object, &#39;functionProperty&#39; ); // Button
</code></pre> </code></pre>
<h2 id="constraining-input">Constraining Input</h2> <h3 id="limiting-input">Limiting Input</h3>
<p>You can specify limits on numbers. A number with a min and max value becomes a slider.</p> <p>You can specify limits on numbers. A number with a min and max value becomes a slider.</p>
<pre><code class="lang-javascript">gui.add( text, &#39;growthSpeed&#39;, -5, 5 ); // Min and max <pre><code class="lang-javascript">gui.add( text, &#39;growthSpeed&#39;, -5, 5 ); // Min and max
gui.add( text, &#39;noiseStrength&#39; ).step( 5 ); // Increment amount gui.add( text, &#39;noiseStrength&#39; ).step( 5 ); // Increment amount
@ -71,32 +40,21 @@ gui.add( text, &#39;message&#39;, [ &#39;pizza&#39;, &#39;chrome&#39;, &#39;hoor
// Choose from named values // Choose from named values
gui.add( text, &#39;speed&#39;, { Stopped: 0, Slow: 0.1, Fast: 5 } ); gui.add( text, &#39;speed&#39;, { Stopped: 0, Slow: 0.1, Fast: 5 } );
</code></pre> </code></pre>
<h2 id="color-controllers">Color Controllers</h2> <h3 id="color-controllers">Color Controllers</h3>
<p>dat-gui has a color selector and understands many different representations of color. The following creates color controllers for color variables of different formats.</p> <p>dat-gui has a color selector and understands many different representations of color. The following creates color controllers for color variables of different formats.</p>
<pre><code class="lang-javascript">var FizzyText = function() { <pre><code class="lang-javascript">text.color0 = &quot;#ffae23&quot;; // CSS string
text.color1 = [ 0, 128, 255 ]; // RGB array
text.color2 = [ 0, 128, 255, 0.3 ]; // RGB with alpha
text.color3 = { h: 350, s: 0.9, v: 0.3 }; // Hue, saturation, value
this.color0 = &quot;#ffae23&quot;; // CSS string var gui = new Gui();
this.color1 = [ 0, 128, 255 ]; // RGB array
this.color2 = [ 0, 128, 255, 0.3 ]; // RGB with alpha
this.color3 = { h: 350, s: 0.9, v: 0.3 }; // Hue, saturation, value
// Define render logic ... gui.addColor(text, &#39;color0&#39;);
gui.addColor(text, &#39;color1&#39;);
}; gui.addColor(text, &#39;color2&#39;);
gui.addColor(text, &#39;color3&#39;);
window.onload = function() {
var text = new FizzyText();
var gui = new Gui();
gui.addColor(text, &#39;color0&#39;);
gui.addColor(text, &#39;color1&#39;);
gui.addColor(text, &#39;color2&#39;);
gui.addColor(text, &#39;color3&#39;);
};
</code></pre> </code></pre>
<h2 id="events">Events</h2> <h3 id="events">Events</h3>
<p>You can listen for events on individual controllers using an event listener syntax.</p> <p>You can listen for events on individual controllers using an event listener syntax.</p>
<pre><code class="lang-javascript">var controller = gui.add(fizzyText, &#39;maxSize&#39;, 0, 10); <pre><code class="lang-javascript">var controller = gui.add(fizzyText, &#39;maxSize&#39;, 0, 10);
@ -109,8 +67,8 @@ controller.onFinishChange(function(value) {
alert(&quot;The new value is &quot; + value); alert(&quot;The new value is &quot; + value);
}); });
</code></pre> </code></pre>
<h2 id="folders">Folders</h2> <h3 id="folders-comments">Folders &amp; Comments</h3>
<p>You can nest as many Gui&#39;s as you want. Nested Gui&#39;s act as collapsible folders.</p> <p>You can nest as many dat-gui as you want. Nested dat-gui act as collapsible folders.</p>
<pre><code class="lang-javascript">var gui = new Gui(); <pre><code class="lang-javascript">var gui = new Gui();
var f1 = gui.addFolder(&#39;Flow Field&#39;); var f1 = gui.addFolder(&#39;Flow Field&#39;);
@ -120,11 +78,13 @@ f1.add(text, &#39;noiseStrength&#39;);
var f2 = gui.addFolder(&#39;Letters&#39;); var f2 = gui.addFolder(&#39;Letters&#39;);
f2.add(text, &#39;growthSpeed&#39;); f2.add(text, &#39;growthSpeed&#39;);
f2.add(text, &#39;maxSize&#39;); f2.add(text, &#39;maxSize&#39;);
f2.add(text, &#39;message&#39;);
f2.open(); f2.open();
</code></pre> </code></pre>
<h2 id="saving-values">Saving Values</h2> <p>The comment method adds a tooltip to a controller.</p>
<pre><code class="lang-javascript">f2.add(text, &#39;message&#39;).comment( &#39;This is the comment.&#39; );
</code></pre>
<h3 id="saving-values">Saving Values</h3>
<p>Add a save menu to the interface by calling <code>gui.remember</code> on all the objects you&#39;ve added to the Gui.</p> <p>Add a save menu to the interface by calling <code>gui.remember</code> on all the objects you&#39;ve added to the Gui.</p>
<pre><code class="lang-javascript">var fizzyText = new FizzyText(); <pre><code class="lang-javascript">var fizzyText = new FizzyText();
var gui = new Gui(); var gui = new Gui();
@ -133,42 +93,47 @@ gui.remember(fizzyText);
// Add controllers ... // Add controllers ...
</code></pre> </code></pre>
<p>Click the gear icon to change your save settings. You can either save your Gui&#39;s values to localStorage, or by copying and pasting a JSON object into your source code as follows:</p> <p>Click the gear icon to change your save settings. You can either save your dat-gui values to localStorage, or by copying and pasting a JSON object into your source code as follows:</p>
<pre><code class="lang-javascript">var fizzyText = new FizzyText(); <pre><code class="lang-javascript">var fizzyText = new FizzyText();
var gui = new Gui({ load: JSON }); var gui = new Gui( { load: JSON } );
gui.remember(fizzyText);
// Add controllers ...
</code></pre>
<h2 id="save-to-disk">Save to disk</h2>
<p>dat-gui comes with a node server that listens for changes to your Gui and saves them to disk. This way you don&#39;t have to worry about losing your local storage or copying and pasting a JSON string.</p>
<p>First, run the node script:</p>
<pre><code class="lang-sh">$ node gui-server
</code></pre>
<p>Next, instantiate your Gui with a path to a JSON file to store settings. </p>
<pre><code class="lang-javascript">var gui = new Gui( { save: &#39;path/to/file.json&#39; } );
gui.remember( fizzyText ); gui.remember( fizzyText );
// Add controllers ... // Add controllers ...
</code></pre> </code></pre>
<h2 id="custom-placement">Custom Placement</h2> <h3 id="presets">Presets</h3>
<p>By default, Gui panels are created with fixed position, and are automatically appended to the body.</p> <p>The save menu also allows you to save all of your settings as presets. Click Save to modify the current preset, or New to create a new preset from existing settings. Clicking Revert will clear all unsaved changes to the current preset.</p>
<p>You can change this behavior by setting the <code>autoPlace</code> parameter to <code>false</code>.</p> <p>Switch between presets using the dropdown in the save menu. You can specify the default like this:</p>
<pre><code class="lang-javascript">var gui = new Gui({
load: JSON,
preset: &#39;Flow&#39;
});
</code></pre>
<p>A word of caution about localStorage:</p>
<p>Paste the JSON save object into your source frequently. Using localStorage to save presets can make you faster, but its easy to lose your settings by clearing browsing data, changing browsers, or even by changing the URL of the page you&#39;re working on.</p>
<h3 id="save-to-disk">Save to Disk</h3>
<p>dat-gui comes with a node server that saves your settings to disk. This way you don&#39;t have to worry about losing your values to local storage or copying and pasting a JSON string.</p>
<p>First, run the node script:</p>
<pre><code class="lang-sh">$ node gui-server
</code></pre>
<p>Next, instantiate your Gui with a path to a JSON file to store settings. dat-gui will read from this file on load and write to this file on change.</p>
<pre><code class="lang-javascript">var gui = new Gui( { load: &#39;path/to/file.json&#39; } );
</code></pre>
<h3 id="custom-placement">Custom Placement</h3>
<p>By default, Gui panels are created with fixed position, and are automatically appended to the body. You can change this behavior by setting the <code>autoPlace</code> parameter to <code>false</code>.</p>
<pre><code class="lang-javascript">var gui = new Gui( { autoPlace: false } ); <pre><code class="lang-javascript">var gui = new Gui( { autoPlace: false } );
var customContainer = document.getElementById(&#39;my-gui-container&#39;); var customContainer = document.getElementById(&#39;my-gui-container&#39;);
customContainer.appendChild(gui.domElement); customContainer.appendChild(gui.domElement);
</code></pre> </code></pre>
<h2 id="html-elements">HTML Elements</h2> <p>Since dat-gui is built using <a href="todo">Web Components</a>, you can also use HTML syntax to add controllers to the page.</p>
<p>Since dat-gui is built using <a href="todo">Web Components</a>, you can use HTML syntax to add controllers to the page.</p>
<pre><code class="lang-html">&lt;body&gt; <pre><code class="lang-html">&lt;body&gt;
&lt;controller-number id=&quot;my-controller&quot; min=&quot;-2&quot; max=&quot;2&quot; step=&quot;1&quot; value=&quot;0&quot;&gt;&lt;/controller-number&gt; &lt;controller-number min=&quot;-2&quot; max=&quot;2&quot; step=&quot;1&quot; value=&quot;0&quot;&gt;&lt;/controller-number&gt;
&lt;script&gt; &lt;script&gt;
var controller = document.getElementById( &#39;my-controller&#39; ); var controller = document.querySelector( &#39;controller-number&#39; );
controller.onChange( function() { controller.onChange( function() {
// react to UI changes ... // react to UI changes ...
@ -179,7 +144,7 @@ controller.onChange( function() {
&lt;/body&gt; &lt;/body&gt;
</code></pre> </code></pre>
<h2 id="defining-custom-controllers">Defining Custom Controllers</h2> <h3 id="defining-custom-controllers">Defining Custom Controllers</h3>
<p>dat-gui uses <a href="todo">Polymer</a> under the hood to define custom elements. A dat-gui controller is just a <a href="todo">Polymer element</a> with two important requirements:</p> <p>dat-gui uses <a href="todo">Polymer</a> under the hood to define custom elements. A dat-gui controller is just a <a href="todo">Polymer element</a> with two important requirements:</p>
<ul> <ul>
<li>Controllers must extend <code>&lt;controller-base&gt;</code>.</li> <li>Controllers must extend <code>&lt;controller-base&gt;</code>.</li>
@ -198,8 +163,8 @@ Gui.register( &#39;controller-number&#39;, function( value ) {
} ); } );
</code></pre> </code></pre>
<p><code>Gui.register</code> takes an element name and a test function. The call to <code>Gui.register</code> tells dat-gui to add a <code>&lt;controller-number&gt;</code> to the panel when the user adds a variable whose type is <code>&#39;number&#39;</code>.</p> <p><code>Gui.register</code> takes an element name and a test function. The test function tells dat-gui to add a <code>&lt;controller-number&gt;</code> to the panel when the user adds a variable whose type is <code>&#39;number&#39;</code>.</p>
<p>A test function takes a value added with <code>gui.add</code> and returns a boolean that determines if the controller is appropriate for the value. This example uses <a href="todo">duck typing</a> to register <code>&lt;vector-controller&gt;</code> for values that have properties <code>x</code>, <code>y</code> and <code>z</code>.</p> <p>A test function determines if a controller is appropriate for a given value. This example registers <code>&lt;vector-controller&gt;</code> for values that have properties <code>x</code>, <code>y</code> and <code>z</code>.</p>
<pre><code class="lang-javascript">Gui.register( &#39;vector-controller&#39;, function( value ) { <pre><code class="lang-javascript">Gui.register( &#39;vector-controller&#39;, function( value ) {
return value.hasOwnProperty( &#39;x&#39; ) &amp;&amp; return value.hasOwnProperty( &#39;x&#39; ) &amp;&amp;
@ -208,62 +173,21 @@ Gui.register( &#39;controller-number&#39;, function( value ) {
} ); } );
</code></pre> </code></pre>
<h2 id="publishing-custom-controllers">Publishing Custom Controllers</h2> <h3 id="publishing-custom-controllers">Publishing Custom Controllers</h3>
<p>You should use bower and format your plugin all nice and it should have a certain prefix yada yada.</p> <p>You should use <a href="todo">Bower</a> and format your plugin all nice and it should have a certain prefix yada yada.</p>
<!-- Replaced with contents of README.md --> <p>Installing third-party controllers ... </p>
</div> <pre><code class="lang-sh">$ bower install gui-three
</code></pre>
<p>Include the source for the third-party controllers after dat-gui.</p>
<pre><code class="lang-html">&lt;script src=&quot;gui.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;gui-three.js&quot;&gt;&lt;/script&gt;
</code></pre>
<!-- Replaced with contents of README.md --></div>
<script> <script src="../underscore/underscore.js"></script>
(function() {
var selector = '#readme h2';
var elements = document.querySelectorAll( selector );
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
el = elements[ i ]; <script src="docs/main.js"></script>
el.top = el.offsetTop; <script src="docs/examples.js"></script>
el.spacer = el.cloneNode( true );
el.spacer.id = '';
el.spacer.style.position = 'fixed';
el.spacer.style.visibility = 'hidden';
el.spacer.style.zIndex = i;
el.spacer.classList.add( 'sticky' );
el.parentElement.insertBefore( el.spacer, el );
el.spacer.height = el.spacer.offsetHeight;
if ( i > 0 ) {
elements[ i - 1 ].next = el;
}
}
function onScroll() {
for ( var el, i = 0, l = elements.length; i < l; i++ ) {
el = elements[ i ];
var sticky = window.scrollY > el.top && window.scrollY <= el.next.top;
el.spacer.style.visibility = sticky ? 'visible' : 'hidden';
if ( el.next && sticky ) {
var bottom = window.scrollY + el.spacer.height;
var marginTop = Math.round( Math.min( 0, el.next.top - bottom ) );
el.spacer.style.marginTop = marginTop + 'px';
el.spacer.classList.toggle( -marginTop );
}
}
}
document.addEventListener( 'scroll', onScroll );
})();
</script>
</body> </body>
</html> </html>

35
test/runner.html Normal file
View File

@ -0,0 +1,35 @@
<!doctype html>
<html>
<head>
<title>dat-gui Test Runner (Mocha)</title>
<meta charset="utf-8">
<link rel="stylesheet" href="../../tools/test/mocha/mocha.css">
<link rel="import" href="../polymer.html">
</head>
<body>
<div id="mocha"></div>
<script>
mocha.setup({ui: 'tdd', slow: 1000, timeout: 10000, htmlbase: ''});
</script>
<!-- -->
<script src="js/marshall.js"></script>
<script src="js/oop.js"></script>
<script src="js/bindProperties.js"></script>
<script src="js/bindMDV.js"></script>
<script src="js/attrs.js"></script>
<script src="js/properties.js"></script>
<script src="js/register.js"></script>
<script src="js/prepare.js"></script>
<script src="js/events.js"></script>
<script src="js/styling.js"></script>
<script src="js/mdv-syntax.js"></script>
<script src="js/paths.js"></script>
<script src="js/utils.js"></script>
<!-- -->
<script>
document.addEventListener('polymer-ready', function() {
mocha.run();
});
</script>
</body>
</html>