diff --git a/dev/config.js b/dev/config.js index b19cc2c..6ef7b4d 100644 --- a/dev/config.js +++ b/dev/config.js @@ -31,6 +31,16 @@ module.exports = [ "placeholder": "Placeholder set with attributes" } }, + { + "type": "slider", + "appKey": "slider", + "defaultValue": 15, + "label": "Slider", + description: "This is the description for the slider", + "min": 10, + "max": 18, + "step": 0.5 + }, { "type": "toggle", "appKey": "cool_stuff", diff --git a/src/scripts/components/index.js b/src/scripts/components/index.js index 251aba8..18f8d00 100644 --- a/src/scripts/components/index.js +++ b/src/scripts/components/index.js @@ -11,5 +11,6 @@ module.exports = { toggle: require('./toggle'), radiogroup: require('./radiogroup'), checkboxgroup: require('./checkboxgroup'), - button: require('./button') + button: require('./button'), + slider: require('./slider') }; diff --git a/src/scripts/components/slider.js b/src/scripts/components/slider.js new file mode 100644 index 0000000..b63d29d --- /dev/null +++ b/src/scripts/components/slider.js @@ -0,0 +1,44 @@ +'use strict'; + +module.exports = { + name: 'slider', + template: require('../../templates/components/slider.tpl'), + style: require('../../styles/clay/components/slider.scss'), + manipulator: 'slider', + defaults: { + label: '', + description: '', + min: 0, + max: 100, + step: 1, + attributes: {} + }, + initialize: function() { + var self = this; + + var $value = self.$element.select('.value'); + var $valuePad = self.$element.select('.value-pad'); + + /** + * Sets the value display + * @return {void} + */ + function setValueDisplay() { + var value = self.get(); + $value.set('value', value); + $valuePad.set('innerHTML', value); + } + + self.on('change', setValueDisplay); + setValueDisplay(); + + $value.on('|keyup', function() { + $valuePad.set('innerHTML', this.get('value')); + }); + + $value.on('|change', function() { + self.set(this.get('value')); + setValueDisplay(); + }); + } +}; diff --git a/src/scripts/lib/manipulators.js b/src/scripts/lib/manipulators.js index f4798a1..d5e5ee3 100755 --- a/src/scripts/lib/manipulators.js +++ b/src/scripts/lib/manipulators.js @@ -85,6 +85,21 @@ module.exports = { hide: hide, show: show }, + slider: { + get: function() { + return parseFloat(this.$manipulatorTarget.get('value')); + }, + set: function(value) { + var initVal = this.get(); + this.$manipulatorTarget.set('value', value); + if (this.get() === initVal) { return this; } + return this.trigger('change'); + }, + disable: disable, + enable: enable, + hide: hide, + show: show + }, checked: { get: function() { return this.$manipulatorTarget.get('checked'); diff --git a/src/styles/clay/_base.scss b/src/styles/clay/_base.scss index caea5e5..ebc24fd 100644 --- a/src/styles/clay/_base.scss +++ b/src/styles/clay/_base.scss @@ -67,6 +67,12 @@ h6 { @include font-size(0.8); } +input { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + label { display: flex; justify-content: space-between; diff --git a/src/styles/clay/components/slider.scss b/src/styles/clay/components/slider.scss new file mode 100644 index 0000000..3ca800b --- /dev/null +++ b/src/styles/clay/components/slider.scss @@ -0,0 +1,127 @@ +@import "clay"; + +.component-slider { + + .section & { + padding: 0; + } + + label { + display: block; + } + + .label-container { + display: flex; + align-items: center; + width: 100%; + padding-bottom: $item-spacing-v; + } + + .label { + flex: 1; + min-width: 1rem; + display: block; + padding-right: $item-spacing-h; + } + + .value-wrap { + display: block; + position: relative; + } + + .value, + .value-pad { + display: block; + background: $color-gray-2; + border-radius: $border-radius; + padding: $item-spacing-v / 2 $item-spacing-h / 2; + border: none; + vertical-align: baseline; + color: $color-white; + text-align: right; + margin: 0; + min-width: 1rem; + } + + .value-pad { + visibility: hidden; + + &:before { + content: ' '; + display: inline-block; + } + } + + .value { + max-width: 100%; + position: absolute; + left:0; + top:0 + } + + .input-wrap { + padding: 0 $item-spacing-h $item-spacing-v; + } + + .input { + $track-height: rem(3px); + + display: block; + position: relative; + min-width: 100%; + height: $base-height; + overflow: hidden; + margin-left: 0; + + &:before { + content: ''; + display: block; + position: absolute; + height: $track-height; + background: $color-gray-6; + width: 100%; + top: $base-height / 2 - $track-height / 2; + } + + .slider { + display: block; + width: 100%; + appearance: none; + position: relative; + height: $base-height; + margin: 0; + background-color: transparent; + + &:focus { + outline: none; + } + + &::-webkit-slider-runnable-track { + border: none; + height: $base-height; + width: 100%; + background-color: transparent; + } + + &::-webkit-slider-thumb { + appearance: none; + position: relative; + height: $base-height; + width: $base-height; + background-color: $color-orange; + border-radius: 50%; + + &:before { + content: ""; + position: absolute; + left: -1000px; + top: $base-height / 2 - $track-height / 2; + height: $track-height; + width: 1001px; + background: $color-orange; + } + } + } + } + +} diff --git a/src/templates/components/slider.tpl b/src/templates/components/slider.tpl new file mode 100644 index 0000000..4ac8ef5 --- /dev/null +++ b/src/templates/components/slider.tpl @@ -0,0 +1,25 @@ +
diff --git a/test/spec/components/slider.js b/test/spec/components/slider.js new file mode 100644 index 0000000..1f78737 --- /dev/null +++ b/test/spec/components/slider.js @@ -0,0 +1,58 @@ +'use strict'; + +var assert = require('chai').assert; +var fixture = require('../../fixture'); + +describe('component - select', function() { + it('sets the value display to the correct value on set', function() { + var clayConfig = fixture.clayConfig(['slider']); + var sliderItem = clayConfig.getItemsByType('slider')[0]; + var $valueDisplay = sliderItem.$element.select('.value'); + var $valueDisplayPad = sliderItem.$element.select('.value-pad'); + + assert.strictEqual($valueDisplay.get('value'), '50'); + assert.strictEqual($valueDisplayPad.get('innerHTML'), '50'); + sliderItem.set(75); + assert.strictEqual($valueDisplay.get('value'), '75'); + assert.strictEqual($valueDisplayPad.get('innerHTML'), '75'); + }); + + it('sets the value display to the correct value on slider change', function() { + var clayConfig = fixture.clayConfig(['slider']); + var sliderItem = clayConfig.getItemsByType('slider')[0]; + var $valueDisplay = sliderItem.$element.select('.value'); + var $valueDisplayPad = sliderItem.$element.select('.value-pad'); + var $slider = sliderItem.$element.select('.slider'); + + assert.strictEqual($valueDisplay.get('value'), '50'); + assert.strictEqual($valueDisplayPad.get('innerHTML'), '50'); + $slider.set('value', 75).trigger('change'); + assert.strictEqual($valueDisplay.get('value'), '75'); + assert.strictEqual($valueDisplayPad.get('innerHTML'), '75'); + }); + + it('sets the value-pqd to the same value as the user is typing', function() { + var clayConfig = fixture.clayConfig(['slider']); + var sliderItem = clayConfig.getItemsByType('slider')[0]; + var $valueDisplay = sliderItem.$element.select('.value'); + var $valueDisplayPad = sliderItem.$element.select('.value-pad'); + + assert.strictEqual($valueDisplay.get('value'), '50'); + assert.strictEqual($valueDisplayPad.get('innerHTML'), '50'); + $valueDisplay.set('value', 75).trigger('keyup'); + assert.strictEqual($valueDisplay.get('value'), '75'); + assert.strictEqual($valueDisplayPad.get('innerHTML'), '75'); + }); + + it('sets the slider to the correct value on user input', function() { + var clayConfig = fixture.clayConfig(['slider']); + var sliderItem = clayConfig.getItemsByType('slider')[0]; + var $valueDisplay = sliderItem.$element.select('.value'); + var $slider = sliderItem.$element.select('.slider'); + + assert.strictEqual($valueDisplay.get('value'), '50'); + assert.strictEqual($slider.get('value'), '50'); + $valueDisplay.set('value', 75).trigger('change'); + assert.strictEqual($slider.get('value'), '75'); + }); +}); diff --git a/test/spec/lib/manipulators.js b/test/spec/lib/manipulators.js index cfb1cd8..af886c0 100644 --- a/test/spec/lib/manipulators.js +++ b/test/spec/lib/manipulators.js @@ -170,6 +170,26 @@ describe('manipulators', function() { testHide(type); }); + describe('slider', function() { + var type = { + type: 'slider', + min: 0, + max: 100, + step: 0.1 + }; + + testSetGet(type, '12', 12); + testSetGet(type, 12); + testSetGet(type, '12.3', 12.3); + testSetGet(type, 12.3); + testSetGet(type, 12.34, 12.3); + testSetGet(type, '12.34', 12.3); + testDisable(type); + testEnable(type); + testShow(type); + testHide(type); + }); + describe('checked', function() { var type = 'toggle'; testSetGet({type: type, defaultValue: false}, 1, true);