Skip to content

Instantly share code, notes, and snippets.

@frankieroberto
Last active December 21, 2015 04:19
Show Gist options
  • Save frankieroberto/6249026 to your computer and use it in GitHub Desktop.
Save frankieroberto/6249026 to your computer and use it in GitHub Desktop.
Number Widget

This is a widget that binds html input elements together, so that buttons and slider ranges can act as controls for other input elements.

<html>
<head>
<script src="number-controls.js"></script>
<link href="style.css" rel="stylesheet">
</head>
<body>
<div class="page">
<h1>Number Widget</h1>
<p>This bit of javascript lets you control input fields using separate buttons and sliders,
for improved usability.</p>
<p>Currently only works in browsers that support the <code>stepUp()</code> and <code>stepDown()</code> methods.</p>
<div>
<h2>Number input</h2>
<div class="number-widget">
<button class="number-control number-control-down">-</button>
<input type="number" class="number-input" value="12">
<button class="number-control number-control-up">+</button>
</div>
<h2>Number input with step, min, max</h2>
<div class="number-widget">
<input type="number" step="3" min="3" max="27" class="number-input" value="6">
<button class="number-control number-control-down">-</button>
<button class="number-control number-control-up">+</button>
</div>
<h2>Downdown-box (select)</h2>
<div class="number-widget">
<button class="number-control number-control-down">-</button>
<select class="number-input">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="5">5</option>
<option value="8">8</option>
<option value="13">13</option>
<option value="21">21</option>
<option value="34">24</option>
</select>
<button class="number-control number-control-up">+</button>
</div>
<h2>Datetime</h2>
<div class="number-widget">
<button class="number-control number-control-down">-</button>
<button class="number-control number-control-up">+</button>
<input type="date" class="number-input" value="2014-06-01">
</div>
<h2>Number input with buttons + slider</h2>
<div class="number-widget">
<button class="number-control number-control-down">-</button>
<input type="number" class="number-input" value="12" min="3" max="54" step="3">
<button class="number-control number-control-up">+</button>
<input type="range" class="number-control number-range-control" value="12" min="3" max="54" step="3">
</div>
<h2>Downdown-box with buttons and slider</h2>
<div class="number-widget">
<button class="number-control number-control-down">-</button>
<select class="number-input">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="5">5</option>
<option value="8">8</option>
<option value="13">13</option>
<option value="21">21</option>
<option value="34">24</option>
</select>
<button class="number-control number-control-up">+</button>
<input type="range" class="number-control number-range-control" value="0" min="0" max="7" step="1">
</div>
<h2>Buttons controlling two inputs</h2>
<div class="number-widget">
<button class="number-control number-control-down">-</button>
<input type="number" class="number-input" value="0" min="0" max="10" step="1">
<input type="number" class="number-input" value="0" min="0" max="100" step="10">
<button class="number-control number-control-up">+</button>
</div>
<h2>Multiple sliders controlling input</h2>
<div class="number-widget">
<input type="number" class="number-input" value="0" min="0" max="1000" step="1">
<input type="range" class="number-control number-range-control" value="0" min="0" max="1000" step="1">
<input type="range" class="number-control number-range-control" value="0" min="0" max="1000" step="10">
<input type="range" class="number-control number-range-control" value="0" min="0" max="1000" step="100">
</div>
</div>
</div>
</body>
</html>
function NumberWidget(widget_element) {
this.widget_element = widget_element;
this.initiateControlElements();
this.initiateInputElements();
}
NumberWidget.prototype.initiateControlElements = function() {
var control_elements = this.widget_element.getElementsByClassName('number-control');
for (var i = 0; i < control_elements.length; i++) {
var number_control = control_elements[i];
new ControlWidget(number_control, this);
}
}
NumberWidget.prototype.initiateInputElements = function() {
var input_elements = this.widget_element.getElementsByClassName('number-input');
for (var i = 0; i < input_elements.length; i++) {
var number_input = input_elements[i];
new InputWidget(number_input, this);
}
}
NumberWidget.prototype.stepValues = function(direction) {
var number_inputs = this.widget_element.getElementsByClassName('number-input');
for (var i = 0; i < number_inputs.length; i++) {
var number_input = number_inputs[i];
if (number_input.stepUp != undefined) {
if (direction == 'up') {
number_input.stepUp();
} else {
number_input.stepDown();
}
} else if (number_input.selectedIndex != undefined) {
var current_selected_index = number_input.selectedIndex;
var options_count = number_input.options.length;
if (direction == 'up' && current_selected_index < (options_count - 1)) {
number_input.selectedIndex = current_selected_index + 1;
} else if (current_selected_index > 0) {
number_input.selectedIndex = current_selected_index - 1;
}
}
number_input.dispatchEvent(new Event('change'));
}
}
NumberWidget.prototype.changeValues = function(value) {
var number_inputs = this.widget_element.getElementsByClassName('number-input');
for (var i = 0; i < number_inputs.length; i++) {
var number_input = number_inputs[i];
if (number_input.selectedIndex != undefined) {
number_input.selectedIndex = value;
} else {
number_input.value = value;
}
}
}
NumberWidget.prototype.updateRanges = function(value) {
var number_range_controls = this.widget_element.getElementsByClassName('number-range-control');
for (var i = 0; i < number_range_controls.length; i++) {
number_range_controls[i].value = value;
}
}
function ControlWidget(control_widget_element, number_widget) {
this.control_widget_element = control_widget_element;
this.number_widget = number_widget;
if (control_widget_element.classList.contains('number-range-control')) {
control_widget_element.addEventListener('change', this.processChange.bind(this));
} else {
control_widget_element.addEventListener('click', this.processClick.bind(this));
}
}
ControlWidget.prototype.processChange = function() {
this.number_widget.changeValues(this.control_widget_element.value)
this.number_widget.updateRanges(this.control_widget_element.value);
}
ControlWidget.prototype.processClick = function() {
if (this.control_widget_element.classList.contains('number-control-up')) {
this.number_widget.stepValues('up');
} else {
this.number_widget.stepValues('down');
}
}
function InputWidget(input_widget_element, number_widget) {
this.input_widget_element = input_widget_element;
this.number_widget = number_widget;
input_widget_element.addEventListener('change', this.processChange.bind(this));
}
InputWidget.prototype.processChange = function() {
this.number_widget.updateRanges(this.input_widget_element.value);
}
function initate_number_widgets() {
var number_widget_elements = document.getElementsByClassName('number-widget');
for (var i = 0; i < number_widget_elements.length; i++) {
new NumberWidget(number_widget_elements[i]);
}
}
window.addEventListener('DOMContentLoaded', initate_number_widgets);
body {
font-family: Helvetica, sans-serif;
color: #222;
}
.page {
margin: 20px;
}
h2 {
margin-top: 32px;
font-weight: 600;
font-size: 16px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment