diff --git a/src/definitions/globals/site.js b/src/definitions/globals/site.js
index 75718fdf19..f1de668fdc 100644
--- a/src/definitions/globals/site.js
+++ b/src/definitions/globals/site.js
@@ -448,7 +448,7 @@ $.site.settings = {
'modal',
'nag',
'popup',
- 'range',
+ 'slider',
'rating',
'shape',
'sidebar',
diff --git a/src/definitions/modules/range.js b/src/definitions/modules/range.js
deleted file mode 100644
index df9eabba99..0000000000
--- a/src/definitions/modules/range.js
+++ /dev/null
@@ -1,278 +0,0 @@
-/*!
- * # Semantic UI - Range
- * http://github.com/semantic-org/semantic-ui/
- *
- *
- * Released under the MIT license
- * http://opensource.org/licenses/MIT
- *
- */
-
-;(function ( $, window, document, undefined ) {
-
- "use strict";
-
- $.fn.range = function(parameters) {
-
- var
- $allModules = $(this),
-
- offset = 10,
-
- query = arguments[0],
- methodInvoked = (typeof query == 'string'),
- queryArguments = [].slice.call(arguments, 1)
- ;
-
- $allModules
- .each(function() {
-
- var
- settings = ( $.isPlainObject(parameters) )
- ? $.extend(true, {}, $.fn.range.settings, parameters)
- : $.extend({}, $.fn.range.settings),
-
- namespace = settings.namespace,
- min = settings.min,
- max = settings.max,
- step = settings.step,
- start = settings.start,
- input = settings.input,
-
- eventNamespace = '.' + namespace,
- moduleNamespace = 'module-' + namespace,
-
- $module = $(this),
-
- element = this,
- instance = $module.data(moduleNamespace),
-
- inner,
- thumb,
- trackLeft,
- precision,
-
- module
- ;
-
- module = {
-
- initialize: function() {
- module.instantiate();
- module.sanitize();
- },
-
- instantiate: function() {
- instance = module;
- $module
- .data(moduleNamespace, module)
- ;
- $(element).html("
");
- inner = $(element).children('.inner')[0];
- thumb = $(element).find('.thumb')[0];
- trackLeft = $(element).find('.track-fill')[0];
- // find precision of step, used in calculating the value
- module.determinePrecision();
- // set start location
- module.setValuePosition(settings.start);
- // event listeners
- $(element).find('.track, .thumb, .inner').on('mousedown', function(event) {
- event.stopImmediatePropagation();
- event.preventDefault();
- $(this).closest(".range").trigger('mousedown', event);
- });
- $(element).find('.track, .thumb, .inner').on('touchstart', function(event) {
- event.stopImmediatePropagation();
- event.preventDefault();
- $(this).closest(".range").trigger('touchstart', event);
- });
- $(element).on('mousedown', function(event, originalEvent) {
- module.rangeMousedown(event, false, originalEvent);
- });
- $(element).on('touchstart', function(event, originalEvent) {
- module.rangeMousedown(event, true, originalEvent);
- });
- module.addVisibilityListener(element);
- },
-
- sanitize: function() {
- if (typeof settings.min != 'number') {
- settings.min = parseInt(settings.min) || 0;
- }
- if (typeof settings.max != 'number') {
- settings.max = parseInt(settings.max) || false;
- }
- if (typeof settings.start != 'number') {
- settings.start = parseInt(settings.start) || 0;
- }
- },
-
- determinePrecision: function() {
- var split = String(settings.step).split('.');
- var decimalPlaces;
- if(split.length == 2) {
- decimalPlaces = split[1].length;
- } else {
- decimalPlaces = 0;
- }
- precision = Math.pow(10, decimalPlaces);
- },
-
- determineValue: function(startPos, endPos, currentPos) {
- var ratio = (currentPos - startPos) / (endPos - startPos);
- var range = settings.max - settings.min;
- var difference = Math.round(ratio * range / step) * step;
- // Use precision to avoid ugly Javascript floating point rounding issues
- // (like 35 * .01 = 0.35000000000000003)
- difference = Math.round(difference * precision) / precision;
- return difference + settings.min;
- },
-
- determinePosition: function(value) {
- var ratio = (value - settings.min) / (settings.max - settings.min);
- return Math.round(ratio * $(inner).width()) + $(trackLeft).position().left - offset;
- },
-
- setValue: function(newValue, triggeredByUser) {
- if(typeof triggeredByUser === 'undefined') {
- triggeredByUser = true;
- }
- if(settings.input) {
- $(settings.input).val(newValue);
- }
- if(settings.onChange) {
- settings.onChange(newValue, {triggeredByUser: triggeredByUser});
- }
- },
-
- setPosition: function(value) {
- $(thumb).css({left: String(value) + 'px'});
- $(trackLeft).css({width: String(value + offset) + 'px'});
- },
-
- rangeMousedown: function(mdEvent, isTouch, originalEvent) {
- if( !$(element).hasClass('disabled') ) {
- mdEvent.preventDefault();
- var left = $(inner).offset().left;
- var right = left + $(inner).width();
- var pageX;
- if(isTouch) {
- pageX = originalEvent.originalEvent.touches[0].pageX;
- } else {
- pageX = (typeof mdEvent.pageX != 'undefined') ? mdEvent.pageX : originalEvent.pageX;
- }
- var value = module.determineValue(left, right, pageX);
- if(pageX >= left && pageX <= right) {
- module.setPosition(pageX - left - offset);
- module.setValue(value);
- }
- var rangeMousemove = function(mmEvent) {
- mmEvent.preventDefault();
- if(isTouch) {
- pageX = mmEvent.originalEvent.touches[0].pageX;
- } else {
- pageX = mmEvent.pageX;
- }
- value = module.determineValue(left, right, pageX);
- if(pageX >= left && pageX <= right) {
- if(value >= settings.min && value <= settings.max) {
- module.setPosition(pageX - left - offset);
- module.setValue(value);
- }
- }
- }
- var rangeMouseup = function(muEvent) {
- if(isTouch) {
- $(document).off('touchmove', rangeMousemove);
- $(document).off('touchend', rangeMouseup);
- } else {
- $(document).off('mousemove', rangeMousemove);
- $(document).off('mouseup', rangeMouseup);
- }
- }
- if(isTouch) {
- $(document).on('touchmove', rangeMousemove);
- $(document).on('touchend', rangeMouseup);
- }
- else {
- $(document).on('mousemove', rangeMousemove);
- $(document).on('mouseup', rangeMouseup);
- }
- }
- },
-
- setValuePosition: function(val, triggeredByUser) {
- if(typeof triggeredByUser === 'undefined') {
- triggeredByUser = true;
- }
- var position = module.determinePosition(val);
- module.setPosition(position);
- module.setValue(val, triggeredByUser);
- },
-
- invoke: function(query) {
- switch(query) {
- case 'set value':
- if(queryArguments.length > 0) {
- instance.setValuePosition(queryArguments[0], false);
- }
- break;
- }
- },
-
- addVisibilityListener: function(elem) {
-
- // Add a mutation observer (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
- // to detect when root invisible element is behing shown in order to initialize the thumb correctly
- // when position and offets are available (https://stackoverflow.com/a/5974377)
-
- var observer = new MutationObserver(function(mutationList) {
- if ($(elem).is(':visible')) {
- observer.disconnect(); // Avoid infinite recursion because « module.setValuePosition » will trigger this observer
- module.setValuePosition(settings.start);
- }
- });
-
- var closestHiddenParent = $(elem).parentsUntil(':visible');
-
- if (closestHiddenParent.length != 0) {
- observer.observe(closestHiddenParent[closestHiddenParent.length - 1], {attributes: true});
- }
- },
-
- };
-
- if(methodInvoked) {
- if(instance === undefined) {
- module.initialize();
- }
- module.invoke(query);
- }
- else {
- module.initialize();
- }
-
- })
- ;
-
- return this;
-
- };
-
- $.fn.range.settings = {
-
- name : 'Range',
- namespace : 'range',
-
- min : 0,
- max : false,
- step : 1,
- start : 0,
- input : false,
-
- onChange : function(value){},
-
- };
-
-
-})( jQuery, window, document );
diff --git a/src/definitions/modules/range.less b/src/definitions/modules/range.less
deleted file mode 100644
index c7380f6b28..0000000000
--- a/src/definitions/modules/range.less
+++ /dev/null
@@ -1,207 +0,0 @@
-/*!
- * # Semantic UI - Range
- * http://github.com/semantic-org/semantic-ui/
- *
- *
- * Released under the MIT license
- * http://opensource.org/licenses/MIT
- *
- */
-
-
-/*******************************
- Theme
-*******************************/
-
-@type : 'module';
-@element : 'range';
-
-@import (multiple) '../../theme.config';
-
-/*******************************
- Range
-*******************************/
-
-.ui.range {
- height: @barHeight;
- width: @barWidth;
-}
-
-.ui.range .inner {
- margin: @innerMargin;
- height: @barHeight;
- position: relative;
-}
-
-.ui.range .inner:hover {
- cursor: @hoverCursor;
-}
-
-.ui.range .inner .track {
- position: absolute;
- height: @trackHeight;
- width: @trackWidth;
- border-radius: @trackBorderRadius;
- top: 9px;
- left: 0;
- background-color: @trackColor;
-}
-
-.ui.range .inner .track-fill {
- position: absolute;
- height: @trackHeight;
- width: 0;
- border-radius: @trackBorderRadius;
- top: 9px;
- left: 0;
- background-color: @trackFillColor;
-}
-
-.ui.range .inner .thumb {
- position: absolute;
- top: 0;
- left: 0;
- height: @thumbHeight;
- width: @thumbWidth;
- background: @thumbBackground;
- border-radius: @thumbBorderRadius;
- box-shadow: @thumbBoxShadow;
-}
-
-
-/*--------------
- Inverted
----------------*/
-
-.ui.inverted.range .inner .track {
- background-color: @invertedTrackColor;
-}
-
-.ui.inverted.range .inner .track-fill {
- background-color: @invertedTrackFillColor;
-}
-
-
-/*--------------
- Colors
----------------*/
-
-/* Red */
-.ui.red.range .inner .track-fill {
- background-color: @red;
-}
-.ui.red.inverted.range .inner .track-fill {
- background-color: @lightRed;
-}
-
-/* Orange */
-.ui.orange.range .inner .track-fill {
- background-color: @orange;
-}
-.ui.orange.inverted.range .inner .track-fill {
- background-color: @lightOrange;
-}
-
-/* Yellow */
-.ui.yellow.range .inner .track-fill {
- background-color: @yellow;
-}
-.ui.yellow.inverted.range .inner .track-fill {
- background-color: @lightYellow;
-}
-
-/* Olive */
-.ui.olive.range .inner .track-fill {
- background-color: @olive;
-}
-.ui.olive.inverted.range .inner .track-fill {
- background-color: @lightOlive;
-}
-
-/* Green */
-.ui.green.range .inner .track-fill {
- background-color: @green;
-}
-.ui.green.inverted.range .inner .track-fill {
- background-color: @lightGreen;
-}
-
-/* Teal */
-.ui.teal.range .inner .track-fill {
- background-color: @teal;
-}
-.ui.teal.inverted.range .inner .track-fill {
- background-color: @lightTeal;
-}
-
-/* Blue */
-.ui.blue.range .inner .track-fill {
- background-color: @blue;
-}
-.ui.blue.inverted.range .inner .track-fill {
- background-color: @lightBlue;
-}
-
-/* Violet */
-.ui.violet.range .inner .track-fill {
- background-color: @violet;
-}
-.ui.violet.inverted.range .inner .track-fill {
- background-color: @lightViolet;
-}
-
-/* Purple */
-.ui.purple.range .inner .track-fill {
- background-color: @purple;
-}
-.ui.purple.inverted.range .inner .track-fill {
- background-color: @lightPurple;
-}
-
-/* Pink */
-.ui.pink.range .inner .track-fill {
- background-color: @pink;
-}
-.ui.pink.inverted.range .inner .track-fill {
- background-color: @lightPink;
-}
-
-/* Brown */
-.ui.brown.range .inner .track-fill {
- background-color: @brown;
-}
-.ui.brown.inverted.range .inner .track-fill {
- background-color: @lightBrown;
-}
-
-/* Grey */
-.ui.grey.range .inner .track-fill {
- background-color: @grey;
-}
-.ui.grey.inverted.range .inner .track-fill {
- background-color: @lightGrey;
-}
-
-/* Black */
-.ui.black.range .inner .track-fill {
- background-color: @black;
-}
-.ui.black.inverted.range .inner .track-fill {
- background-color: @lightBlack;
-}
-
-
-/*--------------
- Disabled
----------------*/
-.ui.range.disabled {
- opacity: @disabledOpacity;
-}
-
-.ui.range.disabled .inner:hover {
- cursor: auto;
-}
-
-.ui.range.disabled .inner .track-fill {
- background: @disabledTrackFillColor;
-}
diff --git a/src/definitions/modules/slider.js b/src/definitions/modules/slider.js
new file mode 100644
index 0000000000..381a7147a3
--- /dev/null
+++ b/src/definitions/modules/slider.js
@@ -0,0 +1,1216 @@
+/*!
+ * # Semantic UI - Slider
+ * http://github.com/semantic-org/semantic-ui/
+ *
+ *
+ * Released under the MIT license
+ * http://opensource.org/licenses/MIT
+ *
+ */
+
+;(function ( $, window, document, undefined ) {
+
+"use strict";
+
+window = (typeof window != 'undefined' && window.Math == Math)
+ ? window
+ : (typeof self != 'undefined' && self.Math == Math)
+ ? self
+ : Function('return this')()
+;
+
+$.fn.slider = function(parameters) {
+
+ var
+ $allModules = $(this),
+
+ moduleSelector = $allModules.selector || '',
+
+ time = new Date().getTime(),
+ performance = [],
+
+ query = arguments[0],
+ methodInvoked = (typeof query == 'string'),
+ queryArguments = [].slice.call(arguments, 1),
+
+ alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
+
+ SINGLE_STEP = 1,
+ BIG_STEP = 2,
+ NO_STEP = 0,
+ SINGLE_BACKSTEP = -1,
+ BIG_BACKSTEP = -2,
+
+ // Used to manage document bound events.
+ // Use this so that we can distinguish between which document events are bound to which range.
+ currentRange = 0,
+
+ returnedValue
+ ;
+
+ $allModules
+ .each(function() {
+
+ var
+ settings = ( $.isPlainObject(parameters) )
+ ? $.extend(true, {}, $.fn.slider.settings, parameters)
+ : $.extend({}, $.fn.slider.settings),
+
+ className = settings.className,
+ metadata = settings.metadata,
+ namespace = settings.namespace,
+ error = settings.error,
+ keys = settings.keys,
+ interpretLabel = settings.interpretLabel,
+
+ isHover = false,
+ eventNamespace = '.' + namespace,
+ moduleNamespace = 'module-' + namespace,
+
+ $module = $(this),
+ $currThumb,
+ $thumb,
+ $secondThumb,
+ $track,
+ $trackFill,
+ $labels,
+
+ element = this,
+ instance = $module.data(moduleNamespace),
+
+ documentEventID,
+
+ value,
+ position,
+ secondPos,
+ offset,
+ precision,
+ isTouch,
+
+ module
+ ;
+
+ module = {
+
+ initialize: function() {
+ module.debug('Initializing slider', settings);
+
+ currentRange += 1;
+ documentEventID = currentRange;
+
+ isTouch = module.setup.testOutTouch();
+ module.setup.layout();
+ module.setup.labels();
+
+ if(!module.is.disabled()) {
+ module.bind.events();
+ }
+
+ module.read.metadata();
+ module.read.settings();
+
+ module.instantiate();
+ },
+
+ instantiate: function() {
+ module.verbose('Storing instance of slider', module);
+ instance = module;
+ $module
+ .data(moduleNamespace, module)
+ ;
+ },
+
+ destroy: function() {
+ module.verbose('Destroying previous slider for', $module);
+ clearInterval(instance.interval);
+ module.unbind.events();
+ module.unbind.slidingEvents();
+ $module.removeData(moduleNamespace);
+ instance = undefined;
+ },
+
+ setup: {
+ layout: function() {
+ if( $module.attr('tabindex') === undefined) {
+ $module.attr('tabindex', 0);
+ }
+ if($module.find('.inner').length == 0) {
+ $module.append(""
+ + "
"
+ + "
"
+ + "
"
+ + "
");
+ }
+ precision = module.get.precision();
+ $thumb = $module.find('.thumb:not(.second)');
+ $currThumb = $thumb;
+ if(module.is.range()) {
+ if($module.find('.thumb.second').length == 0) {
+ $module.find('.inner').append("");
+ }
+ $secondThumb = $module.find('.thumb.second');
+ }
+ $track = $module.find('.track');
+ $trackFill = $module.find('.track-fill');
+ offset = $thumb.width() / 2;
+ },
+ labels: function() {
+ if(module.is.labeled()) {
+ $labels = $module.find('.labels:not(.auto)');
+ if($labels.length != 0) {
+ module.setup.customLabel();
+ } else {
+ module.setup.autoLabel();
+ }
+
+ if (settings.showLabelTicks) {
+ $module.addClass(className.ticked)
+ }
+ }
+ },
+ testOutTouch: function() {
+ try {
+ document.createEvent('TouchEvent');
+ return true;
+ } catch (e) {
+ return false;
+ }
+ },
+ customLabel: function() {
+ var
+ $children = $labels.find('.label'),
+ numChildren = $children.length,
+ min = module.get.min(),
+ max = module.get.max(),
+ ratio
+ ;
+ $children.each(function(index) {
+ var
+ $child = $(this),
+ attrValue = $child.attr('data-value')
+ ;
+ if(attrValue) {
+ attrValue = attrValue > max ? max : attrValue < min ? min : attrValue;
+ ratio = (attrValue - min) / (max - min);
+ } else {
+ ratio = (index + 1) / (numChildren + 1);
+ }
+ module.update.labelPosition(ratio, $(this));
+ });
+ },
+ autoLabel: function() {
+ if(module.get.step() != 0) {
+ $labels = $module.find('.labels');
+ if($labels.length != 0) {
+ $labels.empty();
+ }
+ else {
+ $labels = $module.append('').find('.labels');
+ }
+ for(var i = 0, len = module.get.numLabels(); i <= len; i++) {
+ var
+ labelText = module.get.label(i),
+ $label = (labelText !== "") ? $('' + labelText + '') : null,
+ ratio = i / len
+ ;
+ if($label) {
+ module.update.labelPosition(ratio, $label);
+ $labels.append($label);
+ }
+ }
+ }
+ }
+ },
+
+ bind: {
+ events: function() {
+ module.bind.globalKeyboardEvents();
+ module.bind.keyboardEvents();
+ module.bind.mouseEvents();
+ if(module.is.touch()) {
+ module.bind.touchEvents();
+ }
+ },
+ keyboardEvents: function() {
+ module.verbose('Binding keyboard events');
+ $module.on('keydown' + eventNamespace, module.event.keydown);
+ },
+ globalKeyboardEvents: function() {
+ $(document).on('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
+ },
+ mouseEvents: function() {
+ module.verbose('Binding mouse events');
+ $module.find('.track, .thumb, .inner').on('mousedown' + eventNamespace, function(event) {
+ event.stopImmediatePropagation();
+ event.preventDefault();
+ module.event.down(event);
+ });
+ $module.on('mousedown' + eventNamespace, module.event.down);
+ $module.on('mouseenter' + eventNamespace, function(event) {
+ isHover = true;
+ });
+ $module.on('mouseleave' + eventNamespace, function(event) {
+ isHover = false;
+ });
+ },
+ touchEvents: function() {
+ module.verbose('Binding touch events');
+ $module.find('.track, .thumb, .inner').on('touchstart' + eventNamespace, function(event) {
+ event.stopImmediatePropagation();
+ event.preventDefault();
+ module.event.down(event);
+ });
+ $module.on('touchstart' + eventNamespace, module.event.down);
+ },
+ slidingEvents: function() {
+ // these don't need the identifier because we only ever want one of them to be registered with document
+ module.verbose('Binding page wide events while handle is being draged');
+ if(module.is.touch()) {
+ $(document).on('touchmove' + eventNamespace, module.event.move);
+ $(document).on('touchend' + eventNamespace, module.event.up);
+ }
+ else {
+ $(document).on('mousemove' + eventNamespace, module.event.move);
+ $(document).on('mouseup' + eventNamespace, module.event.up);
+ }
+ }
+ },
+
+ unbind: {
+ events: function() {
+ $module.find('.track, .thumb, .inner').off('mousedown' + eventNamespace);
+ $module.find('.track, .thumb, .inner').off('touchstart' + eventNamespace);
+ $module.off('mousedown' + eventNamespace);
+ $module.off('mouseenter' + eventNamespace);
+ $module.off('mouseleave' + eventNamespace);
+ $module.off('touchstart' + eventNamespace);
+ $module.off('keydown' + eventNamespace);
+ $module.off('focusout' + eventNamespace);
+ $(document).off('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
+ },
+ slidingEvents: function() {
+ if(module.is.touch()) {
+ $(document).off('touchmove' + eventNamespace);
+ $(document).off('touchend' + eventNamespace);
+ } else {
+ $(document).off('mousemove' + eventNamespace);
+ $(document).off('mouseup' + eventNamespace);
+ }
+ },
+ },
+
+ event: {
+ down: function(event, originalEvent) {
+ event.preventDefault();
+ if(module.is.range()) {
+ var
+ eventPos = module.determine.eventPos(event, originalEvent),
+ newPos = module.determine.pos(eventPos)
+ ;
+ $currThumb = module.determine.closestThumb(newPos);
+ }
+ if(!module.is.disabled()) {
+ module.bind.slidingEvents();
+ }
+ },
+ move: function(event, originalEvent) {
+ event.preventDefault();
+ var value = module.determine.valueFromEvent(event, originalEvent);
+ if(module.get.step() == 0 || module.is.smooth()) {
+ var
+ thumbVal = module.thumbVal,
+ secondThumbVal = module.secondThumbVal,
+ thumbSmoothVal = module.determine.smoothValueFromEvent(event, originalEvent)
+ ;
+ if(!$currThumb.hasClass('second')) {
+ thumbVal = value;
+ } else {
+ secondThumbVal = value;
+ }
+ value = Math.abs(thumbVal - (secondThumbVal || 0));
+ module.update.position(thumbSmoothVal);
+ settings.onMove.call(element, value, thumbVal, secondThumbVal);
+ } else {
+ module.update.value(value, function(value, thumbVal, secondThumbVal) {
+ settings.onMove.call(element, value, thumbVal, secondThumbVal);
+ });
+ }
+ },
+ up: function(event, originalEvent) {
+ event.preventDefault();
+ var value = module.determine.valueFromEvent(event, originalEvent);
+ module.set.value(value);
+ module.unbind.slidingEvents();
+ },
+ keydown: function(event, first) {
+ if(module.is.focused()) {
+ $(document).trigger(event);
+ }
+ if(first || module.is.focused()) {
+ var step = module.determine.keyMovement(event);
+ if(step != NO_STEP) {
+ event.preventDefault();
+ switch(step) {
+ case SINGLE_STEP:
+ module.takeStep();
+ break;
+ case BIG_STEP:
+ module.takeStep(module.get.multiplier());
+ break;
+ case SINGLE_BACKSTEP:
+ module.backStep();
+ break;
+ case BIG_BACKSTEP:
+ module.backStep(module.get.multiplier());
+ break;
+ }
+ }
+ }
+ },
+ activateFocus: function(event) {
+ if(!module.is.focused() && module.is.hover() && module.determine.keyMovement(event) != NO_STEP) {
+ event.preventDefault();
+ module.event.keydown(event, true);
+ $module.focus();
+ }
+ },
+ },
+
+ resync: function() {
+ module.verbose('Resyncing thumb position based on value');
+ if(module.is.range()) {
+ module.update.position(module.secondThumbVal, $secondThumb);
+ }
+ module.update.position(module.thumbVal, $thumb);
+ module.setup.labels();
+ },
+ takeStep: function(multiplier) {
+ var
+ multiplier = multiplier != undefined ? multiplier : 1,
+ step = module.get.step(),
+ currValue = module.get.currentThumbValue()
+ ;
+ module.verbose('Taking a step');
+ if(step > 0) {
+ module.set.value(currValue + step * multiplier);
+ } else if (step == 0){
+ var
+ precision = module.get.precision(),
+ newValue = currValue + (multiplier/precision)
+ ;
+ module.set.value(Math.round(newValue * precision) / precision);
+ }
+ },
+
+ backStep: function(multiplier) {
+ var
+ multiplier = multiplier != undefined ? multiplier : 1,
+ step = module.get.step(),
+ currValue = module.get.currentThumbValue()
+ ;
+ module.verbose('Going back a step');
+ if(step > 0) {
+ module.set.value(currValue - step * multiplier);
+ } else if (step == 0) {
+ var
+ precision = module.get.precision(),
+ newValue = currValue - (multiplier/precision)
+ ;
+ module.set.value(Math.round(newValue * precision) / precision);
+ }
+ },
+
+ is: {
+ range: function() {
+ return $module.hasClass(settings.className.range);
+ },
+ hover: function() {
+ return isHover;
+ },
+ focused: function() {
+ return $module.is(':focus');
+ },
+ disabled: function() {
+ return $module.hasClass(settings.className.disabled);
+ },
+ labeled: function() {
+ return $module.hasClass(settings.className.labeled);
+ },
+ reversed: function() {
+ return $module.hasClass(settings.className.reversed);
+ },
+ vertical: function() {
+ return $module.hasClass(settings.className.vertical);
+ },
+ smooth: function() {
+ return settings.smooth || $module.hasClass(settings.className.smooth);
+ },
+ touch: function() {
+ return isTouch;
+ }
+ },
+
+ get: {
+ trackOffset: function() {
+ if (module.is.vertical()) {
+ return $track.offset().top;
+ } else {
+ return $track.offset().left;
+ }
+ },
+ trackLength: function() {
+ if (module.is.vertical()) {
+ return $track.height();
+ } else {
+ return $track.width();
+ }
+ },
+ trackLeft: function() {
+ if (module.is.vertical()) {
+ return $track.position().top;
+ } else {
+ return $track.position().left;
+ }
+ },
+ trackStartPos: function() {
+ return module.is.reversed() ? module.get.trackLeft() + module.get.trackLength() : module.get.trackLeft();
+ },
+ trackEndPos: function() {
+ return module.is.reversed() ? module.get.trackLeft() : module.get.trackLeft() + module.get.trackLength();
+ },
+ trackStartMargin: function () {
+ var margin;
+ if (module.is.vertical()) {
+ margin = module.is.reversed() ? $module.css('padding-bottom') : $module.css('padding-top');
+ } else {
+ margin = module.is.reversed() ? $module.css('padding-right') : $module.css('padding-left');
+ }
+ return margin || '0px';
+ },
+ trackEndMargin: function () {
+ var margin;
+ if (module.is.vertical()) {
+ margin = module.is.reversed() ? $module.css('padding-top') : $module.css('padding-bottom');
+ } else {
+ margin = module.is.reversed() ? $module.css('padding-left') : $module.css('padding-right');
+ }
+ return margin || '0px';
+ },
+ precision: function() {
+ var
+ decimalPlaces,
+ step = module.get.step()
+ ;
+ if(step != 0) {
+ var split = String(step).split('.');
+ if(split.length == 2) {
+ decimalPlaces = split[1].length;
+ } else {
+ decimalPlaces = 0;
+ }
+ } else {
+ decimalPlaces = settings.decimalPlaces;
+ }
+ var precision = Math.pow(10, decimalPlaces);
+ module.debug('Precision determined', precision);
+ return precision;
+ },
+ min: function() {
+ return settings.min;
+ },
+ max: function() {
+ return settings.max;
+ },
+ step: function() {
+ return settings.step;
+ },
+ numLabels: function() {
+ var value = Math.round((module.get.max() - module.get.min()) / module.get.step());
+ module.debug('Determined that their should be ' + value + ' labels');
+ return value;
+ },
+ labelType: function() {
+ return settings.labelType;
+ },
+ label: function(value) {
+ if(interpretLabel) {
+ return interpretLabel(value);
+ }
+
+ switch (settings.labelType) {
+ case settings.labelTypes.number:
+ return (value * module.get.step()) + module.get.min();
+ case settings.labelTypes.letter:
+ return alphabet[(value) % 26];
+ default:
+ return value;
+ }
+ },
+ value: function() {
+ return value;
+ },
+ currentThumbValue: function() {
+ return $currThumb.hasClass('second') ? module.secondThumbVal : module.thumbVal;
+ },
+ thumbValue: function(which) {
+ switch(which) {
+ case 'second':
+ if(module.is.range()) {
+ return module.secondThumbVal;
+ }
+ else {
+ module.error(error.notrange);
+ break;
+ }
+ case 'first':
+ default:
+ return module.thumbVal;
+ }
+ },
+ multiplier: function() {
+ return settings.pageMultiplier;
+ },
+ thumbPosition: function(which) {
+ switch(which) {
+ case 'second':
+ if(module.is.range()) {
+ return secondPos;
+ }
+ else {
+ module.error(error.notrange);
+ break;
+ }
+ case 'first':
+ default:
+ return position;
+ }
+ }
+ },
+
+ determine: {
+ pos: function(pagePos) {
+ return module.is.reversed()
+ ?
+ module.get.trackStartPos() - pagePos + module.get.trackOffset()
+ :
+ pagePos - module.get.trackOffset() - module.get.trackStartPos()
+ ;
+ },
+ closestThumb: function(eventPos) {
+ var
+ thumbPos = parseFloat(module.determine.thumbPos($thumb)),
+ thumbDelta = Math.abs(eventPos - thumbPos),
+ secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
+ secondThumbDelta = Math.abs(eventPos - secondThumbPos)
+ ;
+ return thumbDelta <= secondThumbDelta ? $thumb : $secondThumb;
+ },
+ closestThumbPos: function(eventPos) {
+ var
+ thumbPos = parseFloat(module.determine.thumbPos($thumb)),
+ thumbDelta = Math.abs(eventPos - thumbPos),
+ secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
+ secondThumbDelta = Math.abs(eventPos - secondThumbPos)
+ ;
+ return thumbDelta <= secondThumbDelta ? thumbPos : secondThumbPos;
+ },
+ thumbPos: function($element) {
+ var pos =
+ module.is.vertical()
+ ?
+ module.is.reversed() ? $element.css('bottom') : $element.css('top')
+ :
+ module.is.reversed() ? $element.css('right') : $element.css('left')
+ ;
+ return pos;
+ },
+ positionFromValue: function(value) {
+ var
+ min = module.get.min(),
+ max = module.get.max(),
+ value = value > max ? max : value < min ? min : value,
+ trackLength = module.get.trackLength(),
+ ratio = (value - min) / (max - min),
+ position = Math.round(ratio * trackLength)
+ ;
+ module.verbose('Determined position: ' + position + ' from value: ' + value);
+ return position;
+ },
+ positionFromRatio: function(ratio) {
+ var
+ trackLength = module.get.trackLength(),
+ step = module.get.step(),
+ position = Math.round(ratio * trackLength),
+ adjustedPos = (step == 0) ? position : Math.round(position / step) * step
+ ;
+ return adjustedPos;
+ },
+ valueFromEvent: function(event, originalEvent) {
+ var
+ eventPos = module.determine.eventPos(event, originalEvent),
+ newPos = module.determine.pos(eventPos),
+ value
+ ;
+ if(eventPos < module.get.trackOffset()) {
+ value = module.is.reversed() ? module.get.max() : module.get.min();
+ } else if(eventPos > module.get.trackOffset() + module.get.trackLength()) {
+ value = module.is.reversed() ? module.get.min() : module.get.max();
+ } else {
+ value = module.determine.value(newPos);
+ }
+ return value;
+ },
+ smoothValueFromEvent: function(event, originalEvent) {
+ var
+ min = module.get.min(),
+ max = module.get.max(),
+ trackLength = module.get.trackLength(),
+ eventPos = module.determine.eventPos(event, originalEvent),
+ newPos = eventPos - module.get.trackOffset(),
+ ratio,
+ value
+ ;
+ newPos = newPos < 0 ? 0 : newPos > trackLength ? trackLength : newPos;
+ ratio = newPos / trackLength;
+ if (module.is.reversed()) {
+ ratio = 1 - ratio;
+ }
+ value = ratio * (max - min) + min;
+ return value;
+ },
+ eventPos: function(event, originalEvent) {
+ if(module.is.touch()) {
+ var
+ touchY = event.changedTouches[0].pageY || event.touches[0].pageY,
+ touchX = event.changedTouches[0].pageX || event.touches[0].pageX
+ ;
+ return module.is.vertical() ? touchY : touchX;
+ }
+ var
+ clickY = event.pageY || originalEvent.pageY,
+ clickX = event.pageX || originalEvent.pageX
+ ;
+ return module.is.vertical() ? clickY : clickX;
+ },
+ value: function(position) {
+ var
+ startPos = module.is.reversed() ? module.get.trackEndPos() : module.get.trackStartPos(),
+ endPos = module.is.reversed() ? module.get.trackStartPos() : module.get.trackEndPos(),
+ ratio = (position - startPos) / (endPos - startPos),
+ range = module.get.max() - module.get.min(),
+ step = module.get.step(),
+ value = (ratio * range),
+ difference = (step == 0) ? value : Math.round(value / step) * step
+ ;
+ module.verbose('Determined value based upon position: ' + position + ' as: ' + value);
+ if(value != difference) {
+ module.verbose('Rounding value to closest step: ' + difference);
+ }
+ // Use precision to avoid ugly Javascript floating point rounding issues
+ // (like 35 * .01 = 0.35000000000000003)
+ difference = Math.round(difference * precision) / precision;
+ module.verbose('Cutting off additional decimal places');
+ return difference + module.get.min();
+ },
+ keyMovement: function(event) {
+ var
+ key = event.which,
+ downArrow =
+ module.is.vertical()
+ ?
+ module.is.reversed() ? keys.downArrow : keys.upArrow
+ :
+ keys.downArrow
+ ,
+ upArrow =
+ module.is.vertical()
+ ?
+ module.is.reversed() ? keys.upArrow : keys.downArrow
+ :
+ keys.upArrow
+ ,
+ leftArrow =
+ !module.is.vertical()
+ ?
+ module.is.reversed() ? keys.rightArrow : keys.leftArrow
+ :
+ keys.leftArrow
+ ,
+ rightArrow =
+ !module.is.vertical()
+ ?
+ module.is.reversed() ? keys.leftArrow : keys.rightArrow
+ :
+ keys.rightArrow
+ ;
+ if(key == downArrow || key == leftArrow) {
+ return SINGLE_BACKSTEP;
+ } else if(key == upArrow || key == rightArrow) {
+ return SINGLE_STEP;
+ } else if (key == keys.pageDown) {
+ return BIG_BACKSTEP;
+ } else if (key == keys.pageUp) {
+ return BIG_STEP;
+ } else {
+ return NO_STEP;
+ }
+ }
+ },
+
+ handleNewValuePosition: function(val) {
+ var
+ min = module.get.min(),
+ max = module.get.max(),
+ newPos
+ ;
+ if (val <= min) {
+ val = min;
+ } else if (val >= max) {
+ val = max;
+ }
+ newPos = module.determine.positionFromValue(val);
+ return newPos;
+ },
+
+ set: {
+ value: function(newValue) {
+ module.update.value(newValue, function(value, thumbVal, secondThumbVal) {
+ settings.onChange.call(element, value, thumbVal, secondThumbVal);
+ settings.onMove.call(element, value, thumbVal, secondThumbVal);
+ });
+ },
+ rangeValue: function(first, second) {
+ if(module.is.range()) {
+ var
+ min = module.get.min(),
+ max = module.get.max()
+ ;
+ if (first <= min) {
+ first = min;
+ } else if(first >= max){
+ first = max;
+ }
+ if (second <= min) {
+ second = min;
+ } else if(second >= max){
+ second = max;
+ }
+ module.thumbVal = first;
+ module.secondThumbVal = second;
+ value = Math.abs(module.thumbVal - module.secondThumbVal);
+ module.update.position(module.thumbVal, $thumb);
+ module.update.position(module.secondThumbVal, $secondThumb);
+ settings.onChange.call(element, value, module.thumbVal, module.secondThumbVal);
+ settings.onMove.call(element, value, module.thumbVal, module.secondThumbVal);
+ } else {
+ module.error(error.notrange);
+ }
+ },
+ position: function(position, which) {
+ var thumbVal = module.determine.value(position);
+ switch (which) {
+ case 'second':
+ module.secondThumbVal = thumbVal;
+ module.update.position(thumbVal, $secondThumb);
+ break;
+ default:
+ module.thumbVal = thumbVal;
+ module.update.position(thumbVal, $thumb);
+ }
+ value = Math.abs(module.thumbVal - (module.secondThumbVal || 0));
+ module.set.value(value);
+ }
+ },
+
+ update: {
+ value: function(newValue, callback) {
+ var
+ min = module.get.min(),
+ max = module.get.max()
+ ;
+ if (newValue <= min) {
+ newValue = min;
+ } else if(newValue >= max){
+ newValue = max;
+ }
+ if(!module.is.range()) {
+ value = newValue;
+ module.thumbVal = value;
+ } else {
+ if(!$currThumb.hasClass('second')) {
+ module.thumbVal = newValue;
+ } else {
+ module.secondThumbVal = newValue;
+ }
+ value = Math.abs(module.thumbVal - module.secondThumbVal);
+ }
+ module.update.position(newValue);
+ module.debug('Setting slider value to ' + value);
+ if(typeof callback === 'function') {
+ callback(value, module.thumbVal, module.secondThumbVal);
+ }
+ },
+ position: function(newValue, $element) {
+ var
+ newPos = module.handleNewValuePosition(newValue),
+ $targetThumb = $element != undefined ? $element : $currThumb,
+ thumbVal = module.thumbVal || module.get.min(),
+ secondThumbVal = module.secondThumbVal || module.get.min()
+ ;
+ if(module.is.range()) {
+ if(!$targetThumb.hasClass('second')) {
+ position = newPos;
+ thumbVal = newValue;
+ } else {
+ secondPos = newPos;
+ secondThumbVal = newValue;
+ }
+ } else {
+ position = newPos;
+ thumbVal = newValue;
+ }
+ var
+ trackPosValue,
+ thumbPosValue,
+ min = module.get.min(),
+ max = module.get.max(),
+ thumbPosPercent = 100 * (newValue - min) / (max - min),
+ trackStartPosPercent = 100 * (Math.min(thumbVal, secondThumbVal) - min) / (max - min),
+ trackEndPosPercent = 100 * (1 - (Math.max(thumbVal, secondThumbVal) - min) / (max - min))
+ ;
+ if (module.is.vertical()) {
+ if (module.is.reversed()) {
+ thumbPosValue = {bottom: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', top: 'auto'};
+ trackPosValue = {bottom: trackStartPosPercent + '%', top: trackEndPosPercent + '%'};
+ }
+ else {
+ thumbPosValue = {top: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', bottom: 'auto'};
+ trackPosValue = {top: trackStartPosPercent + '%', bottom: trackEndPosPercent + '%'};
+ }
+ } else {
+ if (module.is.reversed()) {
+ thumbPosValue = {right: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', left: 'auto'};
+ trackPosValue = {right: trackStartPosPercent + '%', left: trackEndPosPercent + '%'};
+ }
+ else {
+ thumbPosValue = {left: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', right: 'auto'};
+ trackPosValue = {left: trackStartPosPercent + '%', right: trackEndPosPercent + '%'};
+ }
+ }
+ $targetThumb.css(thumbPosValue);
+ $trackFill.css(trackPosValue);
+ module.debug('Setting slider position to ' + newPos);
+ },
+ labelPosition: function (ratio, $label) {
+ var
+ startMargin = module.get.trackStartMargin(),
+ endMargin = module.get.trackEndMargin(),
+ posDir =
+ module.is.vertical()
+ ?
+ module.is.reversed() ? 'bottom' : 'top'
+ :
+ module.is.reversed() ? 'right' : 'left',
+ startMarginMod = module.is.reversed() && !module.is.vertical() ? ' - ' : ' + '
+ ;
+ var position = '(100% - ' + startMargin + ' - ' + endMargin + ') * ' + ratio;
+ $label.css(posDir, 'calc(' + position + startMarginMod + startMargin + ')');
+ }
+ },
+
+ goto: {
+ max: function() {
+ module.set.value(module.get.max());
+ },
+ min: function() {
+ module.set.value(module.get.min());
+ },
+ },
+
+ read: {
+ metadata: function() {
+ var
+ data = {
+ thumbVal : $module.data(metadata.thumbVal),
+ secondThumbVal : $module.data(metadata.secondThumbVal)
+ }
+ ;
+ if(data.thumbVal) {
+ if(module.is.range() && data.secondThumbVal) {
+ module.debug('Current value set from metadata', data.thumbVal, data.secondThumbVal);
+ module.set.rangeValue(data.thumbVal, data.secondThumbVal);
+ } else {
+ module.debug('Current value set from metadata', data.thumbVal);
+ module.set.value(data.thumbVal);
+ }
+ }
+ },
+ settings: function() {
+ if(settings.start !== false) {
+ if(module.is.range()) {
+ module.debug('Start position set from settings', settings.start, settings.end);
+ module.set.rangeValue(settings.start, settings.end);
+ } else {
+ module.debug('Start position set from settings', settings.start);
+ module.set.value(settings.start);
+ }
+ }
+ }
+ },
+
+ setting: function(name, value) {
+ module.debug('Changing setting', name, value);
+ if( $.isPlainObject(name) ) {
+ $.extend(true, settings, name);
+ }
+ else if(value !== undefined) {
+ if($.isPlainObject(settings[name])) {
+ $.extend(true, settings[name], value);
+ }
+ else {
+ settings[name] = value;
+ }
+ }
+ else {
+ return settings[name];
+ }
+ },
+ internal: function(name, value) {
+ if( $.isPlainObject(name) ) {
+ $.extend(true, module, name);
+ }
+ else if(value !== undefined) {
+ module[name] = value;
+ }
+ else {
+ return module[name];
+ }
+ },
+ debug: function() {
+ if(!settings.silent && settings.debug) {
+ if(settings.performance) {
+ module.performance.log(arguments);
+ }
+ else {
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
+ module.debug.apply(console, arguments);
+ }
+ }
+ },
+ verbose: function() {
+ if(!settings.silent && settings.verbose && settings.debug) {
+ if(settings.performance) {
+ module.performance.log(arguments);
+ }
+ else {
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
+ module.verbose.apply(console, arguments);
+ }
+ }
+ },
+ error: function() {
+ if(!settings.silent) {
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
+ module.error.apply(console, arguments);
+ }
+ },
+
+ performance: {
+ log: function(message) {
+ var
+ currentTime,
+ executionTime,
+ previousTime
+ ;
+ if(settings.performance) {
+ currentTime = new Date().getTime();
+ previousTime = time || currentTime;
+ executionTime = currentTime - previousTime;
+ time = currentTime;
+ performance.push({
+ 'Name' : message[0],
+ 'Arguments' : [].slice.call(message, 1) || '',
+ 'Element' : element,
+ 'Execution Time' : executionTime
+ });
+ }
+ clearTimeout(module.performance.timer);
+ module.performance.timer = setTimeout(module.performance.display, 500);
+ },
+ display: function() {
+ var
+ title = settings.name + ':',
+ totalTime = 0
+ ;
+ time = false;
+ clearTimeout(module.performance.timer);
+ $.each(performance, function(index, data) {
+ totalTime += data['Execution Time'];
+ });
+ title += ' ' + totalTime + 'ms';
+ if(moduleSelector) {
+ title += ' \'' + moduleSelector + '\'';
+ }
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
+ console.groupCollapsed(title);
+ if(console.table) {
+ console.table(performance);
+ }
+ else {
+ $.each(performance, function(index, data) {
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
+ });
+ }
+ console.groupEnd();
+ }
+ performance = [];
+ }
+ },
+
+ invoke: function(query, passedArguments, context) {
+ var
+ object = instance,
+ maxDepth,
+ found,
+ response
+ ;
+ passedArguments = passedArguments || queryArguments;
+ context = element || context;
+ if(typeof query == 'string' && object !== undefined) {
+ query = query.split(/[\. ]/);
+ maxDepth = query.length - 1;
+ $.each(query, function(depth, value) {
+ var camelCaseValue = (depth != maxDepth)
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
+ : query
+ ;
+ if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
+ object = object[camelCaseValue];
+ }
+ else if( object[camelCaseValue] !== undefined ) {
+ found = object[camelCaseValue];
+ return false;
+ }
+ else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
+ object = object[value];
+ }
+ else if( object[value] !== undefined ) {
+ found = object[value];
+ return false;
+ }
+ else {
+ module.error(error.method, query);
+ return false;
+ }
+ });
+ }
+ if ( $.isFunction( found ) ) {
+ response = found.apply(context, passedArguments);
+ }
+ else if(found !== undefined) {
+ response = found;
+ }
+ if($.isArray(returnedValue)) {
+ returnedValue.push(response);
+ }
+ else if(returnedValue !== undefined) {
+ returnedValue = [returnedValue, response];
+ }
+ else if(response !== undefined) {
+ returnedValue = response;
+ }
+ return found;
+ }
+ };
+
+ if(methodInvoked) {
+ if(instance === undefined) {
+ module.initialize();
+ }
+ module.invoke(query);
+ }
+ else {
+ if(instance !== undefined) {
+ instance.invoke('destroy');
+ }
+ module.initialize();
+ }
+ })
+ ;
+
+ return (returnedValue !== undefined)
+ ? returnedValue
+ : this
+ ;
+
+};
+
+$.fn.slider.settings = {
+
+ silent : false,
+ debug : false,
+ verbose : false,
+ performance : true,
+
+ name : 'Slider',
+ namespace : 'slider',
+
+ error : {
+ method : 'The method you called is not defined.',
+ notrange : 'This slider is not a range slider'
+ },
+
+ metadata: {
+ thumbVal : 'thumbVal',
+ secondThumbVal : 'secondThumbVal'
+ },
+
+ min : 0,
+ max : 20,
+ step : 1,
+ start : 0,
+ end : 20,
+ labelType : 'number',
+ showLabelTicks : false,
+ smooth : false,
+
+ //the decimal place to round to if step is undefined
+ decimalPlaces : 2,
+
+ // page up/down multiplier. How many more times the steps to take on page up/down press
+ pageMultiplier : 2,
+
+ selector: {
+
+ },
+
+ className : {
+ reversed : 'reversed',
+ disabled : 'disabled',
+ labeled : 'labeled',
+ ticked : 'ticked',
+ vertical : 'vertical',
+ range : 'range',
+ smooth : 'smooth'
+ },
+
+ keys : {
+ pageUp : 33,
+ pageDown : 34,
+ leftArrow : 37,
+ upArrow : 38,
+ rightArrow : 39,
+ downArrow : 40
+ },
+
+ labelTypes : {
+ number : 'number',
+ letter : 'letter'
+ },
+
+ onChange : function(value, thumbVal, secondThumbVal){},
+ onMove : function(value, thumbVal, secondThumbVal){},
+};
+
+
+})( jQuery, window, document );
diff --git a/src/definitions/modules/slider.less b/src/definitions/modules/slider.less
new file mode 100644
index 0000000000..e4e82e2c4f
--- /dev/null
+++ b/src/definitions/modules/slider.less
@@ -0,0 +1,455 @@
+ /*******************************
+ Theme
+ *******************************/
+
+ @type : 'module';
+ @element : 'slider';
+
+ @import (multiple) '../../theme.config';
+
+.ui.slider:not(.vertical) {
+ width: 100%;
+ padding: @padding;
+}
+
+.ui.slider {
+ position: relative;
+}
+
+.ui.slider:focus {
+ outline: 0;
+}
+
+.ui.slider .inner {
+ position: relative;
+ z-index: 2;
+}
+
+.ui.slider:not(.vertical) .inner {
+ height: @height;
+}
+
+.ui.slider .inner:hover {
+ cursor: @hoverPointer;
+}
+
+.ui.slider .inner .track {
+ position: absolute;
+ border-radius: @trackBorderRadius;
+ background-color: @trackColor;
+}
+
+.ui.slider:not(.vertical) .inner .track {
+ width: 100%;
+ height: @trackHeight;
+ top: @trackPositionTop;
+ left: 0;
+}
+
+.ui.slider .inner .track-fill {
+ position: absolute;
+ border-radius: @trackFillBorderRadius;
+ background-color: @trackFillColor;
+}
+
+.ui.slider:not(.vertical) .inner .track-fill {
+ height: @trackFillHeight;
+ top: @trackPositionTop;
+ left: 0;
+}
+
+.ui.slider .inner .thumb {
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: @thumbHeight;
+ width: @thumbHeight;
+ background: @thumbBackground;
+ border-radius: @thumbBorderRadius;
+ box-shadow: @thumbShadow;
+ transition: @thumbTransition;
+}
+
+.ui.slider:not(.disabled) .inner .thumb:hover {
+ cursor: @thumbHoverPointer;
+ background: @thumbHoverBackground;
+}
+
+.ui.slider:not(.disabled):focus .inner .thumb {
+ background: @thumbHoverBackground;
+}
+
+
+/*******************************
+ States
+*******************************/
+
+
+/*--------------
+ Disabled
+---------------*/
+
+.ui.disabled.slider {
+ opacity: @disabledOpactiy;
+}
+
+.ui.disabled.slider .inner:hover {
+ cursor: auto;
+}
+
+.ui.disabled.slider .inner .track-fill {
+ background: @disabledTrackFillColor;
+}
+
+/*--------------
+ Reversed
+---------------*/
+
+.ui.reversed.slider .inner .track-fill {
+ left: auto;
+ right: 0;
+}
+
+.ui.reversed.slider .inner .thumb {
+ left: auto;
+ right: 0;
+}
+
+.ui.labeled.reversed.slider > .labels .label {
+ transform: translate(-100%, -100%);
+}
+
+/*******************************
+ Variations
+*******************************/
+
+/*--------------
+ Vertical
+---------------*/
+
+.ui.vertical.slider {
+ height: 100%;
+ width: @height;
+ padding: @verticalPadding;
+}
+
+.ui.vertical.slider .inner {
+ height: 100%;
+}
+
+.ui.vertical.slider .inner .track {
+ height: 100%;
+ width: @trackHeight;
+ left: @trackPositionTop;
+ top: 0;
+}
+
+.ui.vertical.slider .inner .track-fill {
+ width: @trackFillHeight;
+ left: @trackPositionTop;
+ top: 0;
+}
+
+/* Vertical Reversed */
+.ui.vertical.reversed.slider .inner .thumb {
+ top: auto;
+ bottom: 0;
+}
+
+.ui.vertical.reversed.slider .inner .track-fill {
+ top: auto;
+ bottom: 0;
+}
+
+/*--------------
+ Labeled
+---------------*/
+
+.ui.labeled.slider > .labels {
+ height: @labelHeight;
+ width: auto;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+}
+
+.ui.labeled.slider:not(.vertical) > .labels {
+ transform: translateY(-50%);
+}
+
+.ui.labeled.slider > .labels .label {
+ display: inline-flex;
+ position: absolute;
+ transform: translate(-50%, -100%);
+}
+
+.ui.labeled.ticked.slider > .labels .label:after {
+ content: ' ';
+ height: @labelHeight;
+ width: @labelWidth;
+ background: @labelColor;
+ position: absolute;
+ top: 100%;
+ left: 50%;
+}
+
+/* Vertical Labels */
+
+.ui.labeled.vertical.slider > .labels {
+ width: @labelHeight;
+ height: auto;
+ left: 50%;
+ top: 0;
+ bottom: 0;
+ transform: translateX(-50%);
+}
+
+.ui.labeled.vertical.slider > .labels .label {
+ transform: translate(-100%, -50%);
+}
+
+.ui.labeled.vertical.slider > .labels .label:after {
+ width: @labelHeight;
+ height: @labelWidth;
+ left: 100%;
+ top: 50%;
+}
+
+/* Vertical Reversed Labels */
+.ui.labeled.vertical.reversed.slider > .labels .label {
+ transform: translate(-100%, 50%);
+}
+
+/*--------------
+ Hover
+---------------*/
+
+.ui.hover.slider .inner .thumb {
+ opacity: @hoverVarOpacity;
+ transition: @hoverOpacityTransition;
+}
+
+.ui.hover.slider:not(.disabled):hover .inner .thumb, .ui.hover.slider:not(.disabled):focus .inner .thumb {
+ opacity: @hoverVarHoverOpacity;
+}
+
+
+
+/*--------------
+ Inverted
+---------------*/
+
+.ui.inverted.slider .inner .track-fill {
+ background-color: @invertedTrackFillColor;
+}
+
+.ui.inverted.slider .inner .track {
+ background-color: @transparentWhite;
+}
+
+/*--------------
+ Colors
+---------------*/
+
+.addColor(@color, @lightColor, @hoverColor, @lightHoverColor) {
+ @_color: "@{color}";
+ @_lightColor: "@{lightColor}";
+ @_hoverColor: "@{hoverColor}";
+ @_lightHoverColor: "@{lightHoverColor}";
+
+ /* Standard */
+ .ui.@{color}.slider .inner .track-fill {
+ background-color: @@_color;
+ }
+ .ui.@{color}.inverted.slider .inner .track-fill {
+ background-color: @@_lightColor;
+ }
+
+ /* Basic */
+ .ui.@{color}.slider.basic .inner .thumb {
+ background-color: @@_color;
+ }
+ .ui.@{color}.slider.basic .inner .thumb:hover,
+ .ui.@{color}.slider.basic:focus .inner .thumb {
+ background-color: @@_hoverColor;
+ }
+
+ /* Basic Inverted */
+ .ui.@{color}.inverted.slider.basic .inner .thumb {
+ background-color: @@_lightColor;
+ }
+ .ui.@{color}.inverted.slider.basic .inner .thumb:hover,
+ .ui.@{color}.inverted.slider.basic:focus .inner .thumb {
+ background-color: @@_lightHoverColor;
+ }
+
+}
+
+/*--- Red ---*/
+.addColor(~"red", ~"lightRed", ~"redHover", ~"lightRedHover");
+
+/*--- Orange ---*/
+.addColor(~"orange", ~"lightOrange", ~"orangeHover", ~"lightOrangeHover");
+
+/*--- Yellow ---*/
+.addColor(~"yellow", ~"lightYellow", ~"yellowHover", ~"lightYellowHover");
+
+/*--- Olive ---*/
+.addColor(~"olive", ~"lightOlive", ~"oliveHover", ~"lightOliveHover");
+
+/*--- Green ---*/
+.addColor(~"green", ~"lightGreen", ~"greenHover", ~"lightGreenHover");
+
+/*--- Teal ---*/
+.addColor(~"teal", ~"lightTeal", ~"tealHover", ~"lightTealHover");
+
+/*--- Blue ---*/
+.addColor(~"blue", ~"lightBlue", ~"blueHover", ~"lightBlueHover");
+
+/*--- Violet ---*/
+.addColor(~"violet", ~"lightViolet", ~"violetHover", ~"lightVioletHover");
+
+/*--- Purple ---*/
+.addColor(~"purple", ~"lightPurple", ~"purpleHover", ~"lightPurpleHover");
+
+/*--- Pink ---*/
+.addColor(~"pink", ~"lightPink", ~"pinkHover", ~"lightPinkHover");
+
+/*--- Brown ---*/
+.addColor(~"brown", ~"lightBrown", ~"brownHover", ~"lightBrownHover");
+
+/*--- Grey ---*/
+.addColor(~"grey", ~"lightGrey", ~"greyHover", ~"lightGreyHover");
+
+/*--- Black ---*/
+.addColor(~"black", ~"lightBlack", ~"blackHover", ~"lightBlackHover");
+
+/*--------------
+ Basic
+---------------*/
+
+/* Standard */
+.ui.slider.basic .inner .thumb {
+ background-color: @trackFillColor;
+}
+.ui.slider.basic .inner .thumb:hover, .ui.slider.basic:focus .inner .thumb {
+ background-color: @trackFillColorFocus;
+}
+
+/*--------------
+ Basic Inverted
+---------------*/
+
+/* Standard */
+.ui.inverted.slider.basic .inner .thumb {
+ background-color: @invertedTrackFillColor;
+}
+.ui.inverted.slider.basic .inner .thumb:hover, .ui.inverted.slider.basic:focus .inner .thumb {
+ background-color: @invertedTrackFillColorFocus;
+}
+
+
+/*--------------
+ Sizing
+---------------*/
+
+/* Small */
+.ui.slider.small .inner .thumb {
+ height: @smallHeight;
+ width: @smallHeight;
+}
+.ui.slider.small:not(.vertical) .inner {
+ height: @smallHeight;
+}
+.ui.slider.small:not(.vertical) .inner .track,
+.ui.slider.small:not(.vertical) .inner .track-fill {
+ height: @smallTrackHeight;
+ top: @trackPositionTopSmall;
+}
+.ui.small.labeled.slider:not(.vertical) > .labels,
+.ui.small.labeled.slider:not(.vertical) > .labels .label:after {
+ height: @smallLabelHeight;
+}
+
+/* Small Vertical */
+.ui.slider.small.vertical .inner {
+ width: @smallHeight;
+}
+.ui.slider.small.vertical .inner .track,
+.ui.slider.small.vertical .inner .track-fill {
+ width: @smallTrackHeight;
+ left: @trackPositionTopSmall;
+}
+.ui.small.labeled.vertical.slider> .labels,
+.ui.small.labeled.vertical.slider> .labels .label:after {
+ width: @smallLabelHeight;
+}
+
+/* Large */
+.ui.slider.large .inner .thumb {
+ height: @largeHeight;
+ width: @largeHeight;
+}
+.ui.slider.large:not(.vertical) .inner {
+ height: @largeHeight;
+}
+.ui.slider.large:not(.vertical) .inner .track,
+.ui.slider.large:not(.vertical) .inner .track-fill {
+ height: @largeTrackHeight;
+ top: @trackPositionTopLarge;
+}
+.ui.large.labeled.slider:not(.vertical) > .labels,
+.ui.large.labeled.slider:not(.vertical) > .labels .label:after {
+ height: @largeLabelHeight;
+}
+
+/* Large Vertical */
+.ui.slider.large.vertical .inner {
+ width: @largeHeight;
+}
+.ui.slider.large.vertical .inner .track,
+.ui.slider.large.vertical .inner .track-fill {
+ width: @largeTrackHeight;
+ left: @trackPositionTopLarge;
+}
+.ui.large.labeled.vertical.slider> .labels,
+.ui.large.labeled.vertical.slider> .labels .label:after {
+ width: @largeLabelHeight;
+}
+
+/* Big */
+.ui.slider.big .inner .thumb {
+ height: @bigHeight;
+ width: @bigHeight;
+}
+.ui.slider.big:not(.vertical) .inner {
+ height: @bigHeight;
+}
+.ui.slider.big:not(.vertical) .inner .track,
+.ui.slider.big:not(.vertical) .inner .track-fill {
+ height: @bigTrackHeight;
+ top: @trackPositionTopBig;
+}
+.ui.big.labeled.slider:not(.vertical) > .labels,
+.ui.big.labeled.slider:not(.vertical) > .labels .label:after {
+ height: @bigLabelHeight;
+}
+
+/* Big Vertical */
+.ui.slider.big.vertical .inner {
+ width: @bigHeight;
+}
+.ui.slider.big.vertical .inner .track,
+.ui.slider.big.vertical .inner .track-fill {
+ width: @bigTrackHeight;
+ left: @trackPositionTopBig;
+}
+.ui.big.labeled.vertical.slider> .labels,
+.ui.big.labeled.vertical.slider> .labels .label:after {
+ width: @bigLabelHeight;
+}
+
+.loadUIOverrides();
diff --git a/src/semantic.less b/src/semantic.less
index 155ef9446a..aebcde5bb4 100644
--- a/src/semantic.less
+++ b/src/semantic.less
@@ -59,7 +59,7 @@
& { @import "definitions/modules/nag"; }
& { @import "definitions/modules/popup"; }
& { @import "definitions/modules/progress"; }
-& { @import "definitions/modules/range"; }
+& { @import "definitions/modules/slider"; }
& { @import "definitions/modules/rating"; }
& { @import "definitions/modules/search"; }
& { @import "definitions/modules/shape"; }
diff --git a/src/theme.config.example b/src/theme.config.example
index cebbc38a53..96c8bbeaaa 100644
--- a/src/theme.config.example
+++ b/src/theme.config.example
@@ -58,7 +58,7 @@
@nag : 'default';
@popup : 'default';
@progress : 'default';
-@range : 'default';
+@slider : 'default';
@rating : 'default';
@search : 'default';
@shape : 'default';
diff --git a/src/themes/default/modules/range.variables b/src/themes/default/modules/range.variables
deleted file mode 100644
index c5979a64ab..0000000000
--- a/src/themes/default/modules/range.variables
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************
- Range
-*******************************/
-
-@barHeight: 20px;
-@barWidth: 100%;
-
-@innerMargin: 0 10px 0 10px;
-
-@hoverCursor: pointer;
-
-@trackHeight: 4px;
-@trackWidth: 100%;
-@trackBorderRadius: @absoluteBorderRadius;
-@trackColor: rgba(0, 0, 0, .05);
-@trackFillColor: @black;
-
-@thumbHeight: 20px;
-@thumbWidth: 20px;
-@thumbBackground: #fff linear-gradient(transparent, rgba(0, 0, 0, 0.05));
-@thumbBorderRadius: 100%;
-@thumbBoxShadow: 0 1px 2px 0 rgba(34,36,38,.15),0 0 0 1px rgba(34,36,38,.15) inset;
-
-/* Inverted */
-@invertedTrackColor: rgba(255,255,255,.08);
-@invertedTrackFillColor: @lightBlack;
-
-/* Disabled */
-@disabledOpacity: .5;
-@disabledTrackFillColor: @grey;
diff --git a/src/themes/default/modules/range.overrides b/src/themes/default/modules/slider.overrides
similarity index 72%
rename from src/themes/default/modules/range.overrides
rename to src/themes/default/modules/slider.overrides
index 14fb0da124..e5b96d287f 100644
--- a/src/themes/default/modules/range.overrides
+++ b/src/themes/default/modules/slider.overrides
@@ -1,3 +1,3 @@
/*******************************
- Theme Overrides
+ Slider Overrides
*******************************/
diff --git a/src/themes/default/modules/slider.variables b/src/themes/default/modules/slider.variables
new file mode 100644
index 0000000000..9b7b5ec702
--- /dev/null
+++ b/src/themes/default/modules/slider.variables
@@ -0,0 +1,80 @@
+/*******************************
+ Slider Variables
+*******************************/
+
+/*-------------------
+ Element
+--------------------*/
+
+@height : 1.5em;
+@hoverPointer : auto;
+@padding : 1em .5em;
+
+/* Track */
+@trackHeight : .4em;
+@trackPositionTop : (@height / 2) - (@trackHeight / 2);
+@background : #ccc;
+@trackBorderRadius : 4px;
+@trackColor : @transparentBlack;
+
+/* Track Fill */
+@trackFillHeight : @trackHeight;
+@trackFillColor : @black;
+@trackFillColorFocus : @blackHover;
+@invertedTrackFillColor : @lightBlack;
+@invertedTrackFillColorFocus : @lightBlackHover;
+@trackFillBorderRadius : @trackBorderRadius;
+
+/* Thumb */
+@thumbHeight : @height;
+@thumbBorderRadius : 100%;
+@thumbBackground : @white @subtleGradient;
+@thumbShadow : @subtleShadow, 0 0 0 1px @borderColor inset;
+@thumbTransitionDuration : 0.3s;
+@thumbTransition : background @thumbTransitionDuration @defaultEasing;
+
+/* Thumb Hover */
+@thumbHoverPointer : pointer;
+@thumbHoverBackground : @whiteHover @subtleGradient;
+
+/*-------------------
+ States
+--------------------*/
+
+/* Disabled */
+@disabledOpactiy : .5;
+@disabledTrackFillColor : @background;
+
+/*-------------------
+ Variations
+--------------------*/
+
+/* Vertical */
+@verticalPadding : .5em 1em;
+
+/* Labeled */
+@labelHeight : @height;
+@labelWidth : 1px;
+@labelColor : @background;
+
+/* Hover */
+@hoverVarOpacity : 0;
+@hoverVarHoverOpacity : 1;
+@hoverOpacityTransitionDuration : 0.2s;
+@hoverOpacityTransition : opacity @hoverOpacityTransitionDuration linear;
+
+/* Sizing */
+@smallHeight : 1em;
+@smallLabelHeight : @smallHeight;
+@smallTrackHeight : 0.3em;
+@trackPositionTopSmall : (@smallHeight / 2) - (@smallTrackHeight / 2);
+
+@largeHeight : 2em;
+@largeLabelHeight : @largeHeight;
+@largeTrackHeight : 0.5em;
+@trackPositionTopLarge : (@largeHeight / 2) - (@largeTrackHeight / 2);
+
+@bigHeight : 2.5em;
+@bigLabelHeight : @bigHeight;
+@bigTrackHeight : 0.6em;
+@trackPositionTopBig : (@bigHeight / 2) - (@bigTrackHeight / 2);
diff --git a/tasks/config/admin/release.js b/tasks/config/admin/release.js
index 2c2397a480..7750c8ecf7 100644
--- a/tasks/config/admin/release.js
+++ b/tasks/config/admin/release.js
@@ -94,7 +94,7 @@ module.exports = {
'popup',
'progress',
'rail',
- 'range',
+ 'slider',
'rating',
'reset',
'reveal',
diff --git a/tasks/config/defaults.js b/tasks/config/defaults.js
index 57db781b67..c6c5f00e8d 100644
--- a/tasks/config/defaults.js
+++ b/tasks/config/defaults.js
@@ -92,7 +92,7 @@ module.exports = {
'nag',
'popup',
'progress',
- 'range',
+ 'slider',
'rating',
'search',
'shape',
diff --git a/tasks/config/project/install.js b/tasks/config/project/install.js
index e5813f7cfb..c7875f4424 100644
--- a/tasks/config/project/install.js
+++ b/tasks/config/project/install.js
@@ -393,7 +393,7 @@ module.exports = {
{ name: "placeholder", checked: true },
{ name: "popup", checked: true },
{ name: "progress", checked: true },
- { name: "range", checked: true },
+ { name: "slider", checked: true },
{ name: "rating", checked: true },
{ name: "search", checked: true },
{ name: "shape", checked: true },