Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare control panel for the rocket launch #13

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ var control = require('control-panel')
var panel = control([
{type: 'range', label: 'my range', min: 0, max: 100, initial: 20},
{type: 'range', label: 'log range', min: 0.1, max: 100, initial: 20, scale: 'log'},
{type: 'text', label: 'my text', initial: 'my cool setting'},
{type: 'text', label: 'my text', initial: 'my cool setting', help: 'why this is cool'},
{type: 'checkbox', label: 'my checkbox', initial: true},
{type: 'color', label: 'my color', format: 'rgb', initial: 'rgb(10,200,0)'},
{type: 'color', label: 'my color', format: 'rgb', initial: 'rgb(10,200,0)', input: function (value) {console.log(value);}},
{type: 'button', label: 'gimme an alert', action: function () {alert('hello!');}},
{type: 'select', label: 'select one', options: ['option 1', 'option 2'], initial: 'option 1'}
],
],
{theme: 'light', position: 'top-right'}
)
```
Expand All @@ -57,13 +57,13 @@ var panel = control([

#### `panel = control([input1, input2, ...], [opts])`

The first argument is a list of inputs. Each one must have a `type` and `label` property, and can have an `initial` property with an initial value. For example,
The first argument is a list of inputs. Each one must have a `type`, `label` and `help` property, and can have an `initial` property with an initial value. Also it may have an `input` callback, which will be invoked if value changed. For example,

```javascript
{type: 'checkbox', label: 'my checkbox', initial: true}
{type: 'checkbox', label: 'my checkbox', initial: true, input: function (value) {}}
```

Each `type` must be one of `range` • `input` • `checkbox` • `color` • `interval` • `select`. Each `label` must be unique.
Each `type` must be one of `range` • `input` • `checkbox` • `color` • `interval` • `select`. Each `label` must be unique.

Some types have additional properties:
- Inputs of type `range` can specify a `min`, `max`, and `step` (or integer `steps`). Scale can be either `'linear'` (default) or `'log'`. If a log scale, the sign of `min`, `max`, and `initial` must be the same and only `steps` is permitted (since the step size is not constant on a log scale).
Expand Down
6 changes: 3 additions & 3 deletions components/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ inherits(Button, EventEmitter)
function Button (root, opts, theme, uuid) {
if (!(this instanceof Button)) return new Button(root, opts, theme, uuid)

var container = require('./container')(root, opts.label)
var container = require('./container')(root, opts.label, opts.help)
require('./label')(container, '', theme)

var input = container.appendChild(document.createElement('button'))
Expand All @@ -23,8 +23,8 @@ function Button (root, opts, theme, uuid) {
css(input, {
position: 'absolute',
textAlign: 'center',
height: '20px',
width: '62%',
height: '2em',
width: '64%',
border: 'none',
cursor: 'pointer',
right: 0,
Expand Down
11 changes: 7 additions & 4 deletions components/checkbox.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var EventEmitter = require('events').EventEmitter
var inherits = require('inherits')
var format = require('param-case')

module.exports = Checkbox
inherits(Checkbox, EventEmitter)
Expand All @@ -9,17 +10,19 @@ function Checkbox (root, opts, theme, uuid) {
opts = opts || {}
var self = this

var container = require('./container')(root, opts.label)
require('./label')(container, opts.label, theme)
var id = 'checkbox-' + format(opts.label) + '-' + uuid

var container = require('./container')(root, opts.label, opts.help)
require('./label')(container, opts.label, theme, id)

var input = container.appendChild(document.createElement('input'))
input.id = 'checkbox-' + opts.label + uuid
input.id = id
input.type = 'checkbox'
input.checked = opts.initial
input.className = 'control-panel-checkbox-' + uuid

var label = container.appendChild(document.createElement('label'))
label.htmlFor = 'checkbox-' + opts.label + uuid
label.htmlFor = id
label.className = 'control-panel-checkbox-' + uuid

setTimeout(function () {
Expand Down
28 changes: 21 additions & 7 deletions components/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var ColorPicker = require('simple-color-picker')
var inherits = require('inherits')
var css = require('dom-css')
var tinycolor = require('tinycolor2')
var formatParam = require('param-case')

module.exports = Color
inherits(Color, EventEmitter)
Expand All @@ -14,13 +15,25 @@ function Color (root, opts, theme, uuid) {
opts.initial = opts.initial || '#123456'
var self = this

var container = require('./container')(root, opts.label)
require('./label')(container, opts.label, theme)
var id = 'control-panel-color-value-' + formatParam(opts.label) + '-' + uuid

var container = require('./container')(root, opts.label, opts.help)
require('./label')(container, opts.label, theme, id)

var icon = container.appendChild(document.createElement('span'))
icon.id = 'control-panel-color-' + uuid
icon.className = 'control-panel-color-' + uuid

var value = require('./value')(container, '', theme, '46%')
var value = require('./value')(container, {
initial: '',
theme: theme,
width: '50%',
uuid: uuid,
id: id,
change: function (v) {
picker.setColor(v)
}
})

icon.onmouseover = function () {
picker.$el.style.display = ''
Expand Down Expand Up @@ -50,16 +63,17 @@ function Color (root, opts, theme, uuid) {
})

css(picker.$el, {
marginTop: '20px',
marginTop: '2em',
display: 'none',
position: 'absolute'
})

css(icon, {
position: 'relative',
display: 'inline-block',
width: '12.5%',
height: '20px',
verticalAlign: 'top',
width: '13%',
height: '2em',
backgroundColor: picker.getHexString()
})

Expand All @@ -72,7 +86,7 @@ function Color (root, opts, theme, uuid) {
})

picker.onChange(function (hex) {
value.innerHTML = format(hex)
value.value = format(hex)
css(icon, {backgroundColor: hex})
self.emit('input', format(hex))
})
Expand Down
8 changes: 6 additions & 2 deletions components/container.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
var css = require('dom-css')
var format = require('param-case')

module.exports = function (root, label) {
module.exports = function (root, label, help) {
var container = root.appendChild(document.createElement('div'))
container.id = 'control-panel-' + format(label)
container.className = 'control-panel-container'
css(container, {
position: 'relative',
height: '25px'
minHeight: '2em',
lineHeight: '1.5',
marginBottom: '.5em'
})
if (help) container.setAttribute('data-help', help)
return container
}
53 changes: 35 additions & 18 deletions components/interval.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ var EventEmitter = require('events').EventEmitter
var inherits = require('inherits')
var isnumeric = require('is-numeric')
var css = require('dom-css')
var isMobile = require('is-mobile')()
var format = require('param-case')

module.exports = Range
inherits(Range, EventEmitter)
Expand All @@ -15,8 +17,9 @@ function Range (root, opts, theme, uuid) {
var self = this
var scaleValue, scaleValueInverse, logmin, logmax, logsign, panel, input, handle

var container = require('./container')(root, opts.label)
require('./label')(container, opts.label, theme)
var id = 'control-panel-interval-value-' + format(opts.label) + '-' + uuid
var container = require('./container')(root, opts.label, opts.help)
require('./label')(container, opts.label, theme, id)

if (!!opts.step && !!opts.steps) {
throw new Error('Cannot specify both step and steps. Got step = ' + opts.step + ', steps = ', opts.steps)
Expand All @@ -27,6 +30,7 @@ function Range (root, opts, theme, uuid) {
})

input = container.appendChild(document.createElement('span'))
input.id = 'control-panel-interval-' + uuid
input.className = 'control-panel-interval-' + uuid

handle = document.createElement('span')
Expand Down Expand Up @@ -121,15 +125,29 @@ function Range (root, opts, theme, uuid) {
setHandleCSS()

// Display the values:
var lValue = require('./value')(container, scaleValue(opts.initial[0]), theme, '11%', true)
var rValue = require('./value')(container, scaleValue(opts.initial[1]), theme, '11%')
var lValue = require('./value')(container, {
initial: scaleValue(opts.initial[0]),
theme: theme,
width: '13%',
type: 'text',
left: true,
id: id,
uuid: uuid
})
var rValue = require('./value')(container, {
initial: scaleValue(opts.initial[1]),
theme: theme,
width: '13%',
type: 'text',
uuid: uuid
})

// An index to track what's being dragged:
var activeIndex = -1

function mouseX (ev) {
// Get mouse position in page coords relative to the container:
return ev.pageX - input.getBoundingClientRect().left
// Get mouse/touch position in page coords relative to the container:
return (ev.touches && ev.touches[0] || ev).pageX - input.getBoundingClientRect().left
}

function setActiveValue (fraction) {
Expand Down Expand Up @@ -160,24 +178,23 @@ function Range (root, opts, theme, uuid) {
}

var mousemoveListener = function (ev) {
if (ev.target === input || ev.target === handle) ev.preventDefault()

var fraction = clamp(mouseX(ev) / input.offsetWidth, 0, 1)

setActiveValue(fraction)
}

var mouseupListener = function (ev) {
panel.classList.remove('control-panel-interval-dragging')
var fraction = clamp(mouseX(ev) / input.offsetWidth, 0, 1)

setActiveValue(fraction)

document.removeEventListener('mousemove', mousemoveListener)
document.removeEventListener('mouseup', mouseupListener)
document.removeEventListener(isMobile ? 'touchmove' : 'mousemove', mousemoveListener)
document.removeEventListener(isMobile ? 'touchend' : 'mouseup', mouseupListener)

activeIndex = -1
}

input.addEventListener('mousedown', function (ev) {
input.addEventListener(isMobile ? 'touchstart' : 'mousedown', function (ev) {
// Tweak control to make dragging experience a little nicer:
panel.classList.add('control-panel-interval-dragging')

Expand All @@ -201,23 +218,23 @@ function Range (root, opts, theme, uuid) {

// Attach this to *document* so that we can still drag if the mouse
// passes outside the container:
document.addEventListener('mousemove', mousemoveListener)
document.addEventListener('mouseup', mouseupListener)
document.addEventListener(isMobile ? 'touchmove' : 'mousemove', mousemoveListener)
document.addEventListener(isMobile ? 'touchend' : 'mouseup', mouseupListener)
})

setTimeout(function () {
var scaledLValue = scaleValue(value[0])
var scaledRValue = scaleValue(value[1])
lValue.innerHTML = scaledLValue
rValue.innerHTML = scaledRValue
lValue.value = scaledLValue
rValue.value = scaledRValue
self.emit('initialized', [scaledLValue, scaledRValue])
})

input.oninput = function () {
var scaledLValue = scaleValue(value[0])
var scaledRValue = scaleValue(value[1])
lValue.innerHTML = scaledLValue
rValue.innerHTML = scaledRValue
lValue.value = scaledLValue
rValue.value = scaledRValue
self.emit('input', [scaledLValue, scaledRValue])
}
}
11 changes: 7 additions & 4 deletions components/label.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
var css = require('dom-css')

module.exports = function (root, text, theme) {
var background = root.appendChild(document.createElement('div'))
module.exports = function (root, text, theme, id) {
var background = root.appendChild(document.createElement('label'))
background.htmlFor = id || text

css(background, {
left: 0,
width: '36%',
paddingTop: '.45em',
display: 'inline-block',
height: '20px',
lineHeight: '1.25',
paddingRight: '2%',
verticalAlign: 'top'
})
Expand All @@ -16,7 +19,7 @@ module.exports = function (root, text, theme) {
css(label, {
color: theme.text1,
display: 'inline-block',
verticalAlign: 'sub'
verticalAlign: 'top'
})
return label
}
28 changes: 23 additions & 5 deletions components/range.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var EventEmitter = require('events').EventEmitter
var inherits = require('inherits')
var isnumeric = require('is-numeric')
var css = require('dom-css')
var format = require('param-case')

module.exports = Range
inherits(Range, EventEmitter)
Expand All @@ -11,8 +12,10 @@ function Range (root, opts, theme, uuid) {
var self = this
var scaleValue, scaleValueInverse, logmin, logmax, logsign

var container = require('./container')(root, opts.label)
require('./label')(container, opts.label, theme)
var id = 'control-panel-range-value-' + format(opts.label) + '-' + uuid

var container = require('./container')(root, opts.label, opts.help)
require('./label')(container, opts.label, theme, id)

if (!!opts.step && !!opts.steps) {
throw new Error('Cannot specify both step and steps. Got step = ' + opts.step + ', steps = ', opts.steps)
Expand All @@ -21,6 +24,7 @@ function Range (root, opts, theme, uuid) {
var input = container.appendChild(document.createElement('input'))
input.type = 'range'
input.className = 'control-panel-range-' + uuid
input.id = 'control-panel-range-' + uuid

// Create scale functions for converting to/from the desired scale:
if (opts.scale === 'log') {
Expand Down Expand Up @@ -95,18 +99,32 @@ function Range (root, opts, theme, uuid) {
input.value = opts.initial

css(input, {
width: '47.5%'
width: '50%'
})

var value = require('./value')(container, scaleValue(opts.initial), theme, '11%')
var value = require('./value')(container, {
id: id,
initial: scaleValue(opts.initial),
theme: theme,
width: '13%',
type: opts.scale === 'log' ? 'text' : 'number',
uuid: uuid,
min: scaleValue(opts.min),
max: scaleValue(opts.max),
step: opts.step,
input: function (v) {
input.value = v
value.value = scaleValue(v)
}
})

setTimeout(function () {
self.emit('initialized', parseFloat(input.value))
})

input.oninput = function (data) {
var scaledValue = scaleValue(parseFloat(data.target.value))
value.innerHTML = scaledValue
value.value = scaledValue
self.emit('input', scaledValue)
}
}
Loading