From 545231de58f6df5d244128477e875454d659f390 Mon Sep 17 00:00:00 2001 From: Valentin Hervieu Date: Tue, 24 Nov 2015 19:55:06 +0100 Subject: [PATCH 1/5] Feature - Add a vertical option to display vertical sliders. --- demo/demo.css | 7 ++ demo/demo.js | 60 +++++++++++ demo/index.html | 52 +++++++--- dist/rzslider.css | 70 +++++++++++++ dist/rzslider.js | 224 +++++++++++++++++++++++++----------------- dist/rzslider.min.css | 4 +- dist/rzslider.min.js | 4 +- src/rzslider.js | 224 +++++++++++++++++++++++++----------------- src/rzslider.less | 81 +++++++++++++-- src/variables.less | 2 +- 10 files changed, 519 insertions(+), 209 deletions(-) diff --git a/demo/demo.css b/demo/demo.css index 9bc2ac7..41cd771 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -11,3 +11,10 @@ article { margin-bottom: 10px; } .field-title { width: 100px; } + +.vertical-sliders { + margin: 0; +} +.vertical-sliders > div { + height: 250px; +} diff --git a/demo/demo.js b/demo/demo.js index 6cc0c66..d97729a 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -118,6 +118,66 @@ app.controller('MainCtrl', function($scope, $rootScope, $timeout, $modal) { } }; + //Vertical sliders + $scope.verticalSlider1 = { + value: 0, + options: { + floor: 0, + ceil: 10, + vertical: true + } + }; + $scope.verticalSlider2 = { + minValue: 20, + maxValue: 80, + options: { + floor: 0, + ceil: 100, + vertical: true + } + }; + $scope.verticalSlider3 = { + value: 5, + options: { + floor: 0, + ceil: 10, + vertical: true, + showTicks: true + } + }; + $scope.verticalSlider4 = { + minValue: 1, + maxValue: 5, + options: { + floor: 0, + ceil: 6, + vertical: true, + showTicksValues: true + } + }; + $scope.verticalSlider5 = { + value: 50, + options: { + floor: 0, + ceil: 100, + vertical: true, + showSelectionBar: true + } + }; + $scope.verticalSlider6 = { + value: 6, + options: { + floor: 0, + ceil: 6, + vertical: true, + showSelectionBar: true, + showTicksValues: true, + ticksValuesTooltip: function(v) { + return 'Tooltip for ' + v; + } + } + }; + //Read-only slider $scope.read_only_slider = { value: 50, diff --git a/demo/index.html b/demo/index.html index fc58437..a4aa573 100644 --- a/demo/index.html +++ b/demo/index.html @@ -33,7 +33,7 @@

Range slider

rz-slider-model="minRangeSlider.minValue" rz-slider-high="minRangeSlider.maxValue" rz-slider-options="minRangeSlider.options" - > + >
@@ -41,7 +41,7 @@

Slider with visible selection bar

+ >
@@ -49,7 +49,7 @@

Slider with custom floor/ceil/step

+ >
@@ -61,7 +61,7 @@

Slider with callbacks on start, change and end

+ >
@@ -70,7 +70,7 @@

Slider with custom display function

rz-slider-model="slider_translate.minValue" rz-slider-high="slider_translate.maxValue" rz-slider-options="slider_translate.options" - > + >
@@ -78,7 +78,7 @@

Slider with Alphabet

+ >
@@ -86,7 +86,7 @@

Slider with ticks

+ >
@@ -94,7 +94,7 @@

Slider with ticks and values (and tooltips)

+ >
@@ -103,7 +103,7 @@

Range slider with ticks and values

rz-slider-model="range_slider_ticks_values.minValue" rz-slider-high="range_slider_ticks_values.maxValue" rz-slider-options="range_slider_ticks_values.options" - > + >
@@ -112,7 +112,33 @@

Slider with draggable range

rz-slider-model="slider_draggable_range.minValue" rz-slider-high="slider_draggable_range.maxValue" rz-slider-options="slider_draggable_range.options" - > + > +
+ +
+

Vertical sliders

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
@@ -121,7 +147,7 @@

Disabled slider

+ >
@@ -130,7 +156,7 @@

Read-only slider

+ >
@@ -194,7 +220,7 @@

Slider with all options demo

rz-slider-model="slider_all_options.minValue" rz-slider-high="slider_all_options.maxValue" rz-slider-options="slider_all_options.options" - > + >
diff --git a/dist/rzslider.css b/dist/rzslider.css index 2ade56d..7a1cba0 100644 --- a/dist/rzslider.css +++ b/dist/rzslider.css @@ -161,4 +161,74 @@ rzslider .rz-ticks .tick .tick-value { position: absolute; top: -30px; transform: translate(-50%, 0); +} + +rzslider.vertical { + position: relative; + width: 4px; + height: 100%; + padding: 0; + margin: 0 20px; + vertical-align: baseline; +} + +rzslider.vertical .rz-base { + width: 100%; + height: 100%; + padding: 0; +} + +rzslider.vertical .rz-bar-wrapper { + top: auto; + left: 0; + width: 32px; + height: 100%; + padding: 0 0 0 16px; + margin: 0 0 0 -16px; +} + +rzslider.vertical .rz-bar { + bottom: 0; + left: initial; + width: 4px; + height: 100%; +} + +rzslider.vertical .rz-pointer { + top: auto; + bottom: 0; + left: -14px !important; +} + +rzslider.vertical .rz-bubble { + bottom: 0; + left: 16px !important; + margin-left: 3px; +} + +rzslider.vertical .rz-bubble.rz-selection { + top: auto; + left: 16px !important; +} + +rzslider.vertical .rz-ticks { + top: 0; + left: -3px; + z-index: 1; + width: auto; + height: 100%; + padding: 11px 0; + -webkit-flex-direction: column-reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; +} + +rzslider.vertical .rz-ticks .tick { + vertical-align: middle; +} + +rzslider.vertical .rz-ticks .tick .tick-value { + top: auto; + right: -30px; + transform: translate(0, -28%); } \ No newline at end of file diff --git a/dist/rzslider.js b/dist/rzslider.js index a89a036..c3ac27d 100644 --- a/dist/rzslider.js +++ b/dist/rzslider.js @@ -49,6 +49,7 @@ showTicks: false, showTicksValues: false, ticksValuesTooltip: null, + vertical: false, scale: 1, onStart: null, onChange: null, @@ -171,18 +172,30 @@ }; /** - * Half of the width of the slider handles + * property that handle position (defaults to left for horizontal) + * @type {string} + */ + this.positionProperty = 'left'; + + /** + * property that handle dimension (defaults to width for horizontal) + * @type {string} + */ + this.dimensionProperty = 'width'; + + /** + * Half of the width or height of the slider handles * * @type {number} */ - this.handleHalfWidth = 0; + this.handleHalfDim = 0; /** - * Maximum left the slider handle can have + * Maximum position the slider handle can have * * @type {number} */ - this.maxLeft = 0; + this.maxPos = 0; /** * Precision @@ -285,6 +298,9 @@ // Recalculate stuff if view port dimensions have changed angular.element($window).on('resize', calcDimFn); + if (this.options.vertical) + this.sliderElem.addClass('vertical'); + this.initHasRun = true; // Watch for changes to the model @@ -368,12 +384,18 @@ this.customTrFn = function(value) { return this.options.stepsArray[value]; }; - } else if (this.options.translate) + } + else if (this.options.translate) this.customTrFn = this.options.translate; else this.customTrFn = function(value) { return String(value); }; + + if (this.options.vertical) { + this.positionProperty = 'bottom'; + this.dimensionProperty = 'height'; + } }, /** @@ -440,14 +462,14 @@ }, this); // Initialize offset cache properties - this.selBar.rzsl = 0; - this.minH.rzsl = 0; - this.maxH.rzsl = 0; - this.flrLab.rzsl = 0; - this.ceilLab.rzsl = 0; - this.minLab.rzsl = 0; - this.maxLab.rzsl = 0; - this.cmbLab.rzsl = 0; + this.selBar.rzsp = 0; + this.minH.rzsp = 0; + this.maxH.rzsp = 0; + this.flrLab.rzsp = 0; + this.ceilLab.rzsp = 0; + this.minLab.rzsp = 0; + this.maxLab.rzsp = 0; + this.cmbLab.rzsp = 0; }, /** Update each elements style based on options @@ -554,18 +576,18 @@ useCustomTr = useCustomTr === undefined ? true : useCustomTr; var valStr = String((useCustomTr ? this.customTrFn(value, this.options.id) : value)), - getWidth = false; + getDimension = false; - if (label.rzsv === undefined || label.rzsv.length !== valStr.length || (label.rzsv.length > 0 && label.rzsw === 0)) { - getWidth = true; + if (label.rzsv === undefined || label.rzsv.length !== valStr.length || (label.rzsv.length > 0 && label.rzsd === 0)) { + getDimension = true; label.rzsv = valStr; } label.text(valStr); // Update width only when length of the label have changed - if (getWidth) { - this.getWidth(label); + if (getDimension) { + this.getDimension(label); } }, @@ -612,15 +634,15 @@ * @returns {undefined} */ calcViewDimensions: function() { - var handleWidth = this.getWidth(this.minH); + var handleWidth = this.getDimension(this.minH); - this.handleHalfWidth = handleWidth / 2; - this.barWidth = this.getWidth(this.fullBar); + this.handleHalfDim = handleWidth / 2; + this.barDimension = this.getDimension(this.fullBar); - this.maxLeft = this.barWidth - handleWidth; + this.maxPos = this.barDimension - handleWidth; - this.getWidth(this.sliderElem); - this.sliderElem.rzsl = this.sliderElem[0].getBoundingClientRect().left; + this.getDimension(this.sliderElem); + this.sliderElem.rzsp = this.sliderElem[0].getBoundingClientRect()[this.positionProperty]; if (this.initHasRun) { this.updateFloorLab(); @@ -648,6 +670,8 @@ var tooltip = ''; if (this.options.ticksValuesTooltip) { tooltip = 'uib-tooltip="' + this.options.ticksValuesTooltip(value) + '"'; + if(this.options.vertical) + tooltip += ' tooltip-placement="right"' } positions += '' + this.getDisplayValue(value) + ''; } @@ -673,8 +697,8 @@ */ updateCeilLab: function() { this.translateFn(this.maxValue, this.ceilLab); - this.setLeft(this.ceilLab, this.barWidth - this.ceilLab.rzsw); - this.getWidth(this.ceilLab); + this.setPosition(this.ceilLab, this.barDimension - this.ceilLab.rzsd); + this.getDimension(this.ceilLab); }, /** @@ -684,7 +708,7 @@ */ updateFloorLab: function() { this.translateFn(this.minValue, this.flrLab); - this.getWidth(this.flrLab); + this.getDimension(this.flrLab); }, /** @@ -773,10 +797,10 @@ * @returns {undefined} */ updateLowHandle: function(newOffset) { - this.setLeft(this.minH, newOffset); + this.setPosition(this.minH, newOffset); this.translateFn(this.scope.rzSliderModel, this.minLab); - var left = Math.min(Math.max(newOffset - this.minLab.rzsw / 2 + this.handleHalfWidth, 0), this.barWidth - this.ceilLab.rzsw); - this.setLeft(this.minLab, left); + var pos = Math.min(Math.max(newOffset - this.minLab.rzsd / 2 + this.handleHalfDim, 0), this.barDimension - this.ceilLab.rzsd); + this.setPosition(this.minLab, pos); this.shFloorCeil(); }, @@ -788,10 +812,10 @@ * @returns {undefined} */ updateHighHandle: function(newOffset) { - this.setLeft(this.maxH, newOffset); + this.setPosition(this.maxH, newOffset); this.translateFn(this.scope.rzSliderHigh, this.maxLab); - var left = Math.min((newOffset - this.maxLab.rzsw / 2 + this.handleHalfWidth), (this.barWidth - this.ceilLab.rzsw)); - this.setLeft(this.maxLab, left); + var pos = Math.min((newOffset - this.maxLab.rzsd / 2 + this.handleHalfDim), (this.barDimension - this.ceilLab.rzsd)); + this.setPosition(this.maxLab, pos); this.shFloorCeil(); }, @@ -805,7 +829,7 @@ var flHidden = false, clHidden = false; - if (this.minLab.rzsl <= this.flrLab.rzsl + this.flrLab.rzsw + 5) { + if (this.minLab.rzsp <= this.flrLab.rzsp + this.flrLab.rzsd + 5) { flHidden = true; this.hideEl(this.flrLab); } else { @@ -813,7 +837,7 @@ this.showEl(this.flrLab); } - if (this.minLab.rzsl + this.minLab.rzsw >= this.ceilLab.rzsl - this.handleHalfWidth - 10) { + if (this.minLab.rzsp + this.minLab.rzsd >= this.ceilLab.rzsp - this.handleHalfDim - 10) { clHidden = true; this.hideEl(this.ceilLab); } else { @@ -822,14 +846,14 @@ } if (this.range) { - if (this.maxLab.rzsl + this.maxLab.rzsw >= this.ceilLab.rzsl - 10) { + if (this.maxLab.rzsp + this.maxLab.rzsd >= this.ceilLab.rzsp - 10) { this.hideEl(this.ceilLab); } else if (!clHidden) { this.showEl(this.ceilLab); } // Hide or show floor label - if (this.maxLab.rzsl <= this.flrLab.rzsl + this.flrLab.rzsw + this.handleHalfWidth) { + if (this.maxLab.rzsp <= this.flrLab.rzsp + this.flrLab.rzsd + this.handleHalfDim) { this.hideEl(this.flrLab); } else if (!flHidden) { this.showEl(this.flrLab); @@ -843,8 +867,8 @@ * @returns {undefined} */ updateSelectionBar: function() { - this.setWidth(this.selBar, Math.abs(this.maxH.rzsl - this.minH.rzsl) + this.handleHalfWidth); - this.setLeft(this.selBar, this.range ? this.minH.rzsl + this.handleHalfWidth : 0); + this.setDimension(this.selBar, Math.abs(this.maxH.rzsp - this.minH.rzsp) + this.handleHalfDim); + this.setPosition(this.selBar, this.range ? this.minH.rzsp + this.handleHalfDim : 0); }, /** @@ -855,13 +879,13 @@ updateCmbLabel: function() { var lowTr, highTr; - if (this.minLab.rzsl + this.minLab.rzsw + 10 >= this.maxLab.rzsl) { + if (this.minLab.rzsp + this.minLab.rzsd + 10 >= this.maxLab.rzsp) { lowTr = this.getDisplayValue(this.scope.rzSliderModel); highTr = this.getDisplayValue(this.scope.rzSliderHigh); this.translateFn(lowTr + ' - ' + highTr, this.cmbLab, false); - var left = Math.min(Math.max((this.selBar.rzsl + this.selBar.rzsw / 2 - this.cmbLab.rzsw / 2),0),(this.barWidth - this.cmbLab.rzsw)); - this.setLeft(this.cmbLab, left); + var pos = Math.min(Math.max((this.selBar.rzsp + this.selBar.rzsd / 2 - this.cmbLab.rzsd / 2), 0), (this.barDimension - this.cmbLab.rzsd)); + this.setPosition(this.cmbLab, pos); this.hideEl(this.minLab); this.hideEl(this.maxLab); this.showEl(this.cmbLab); @@ -925,45 +949,48 @@ }, /** - * Set element left offset + * Set element left/top offset depending on whether slider is horizontal or vertical * * @param {jqLite} elem The jqLite wrapped DOM element - * @param {number} left + * @param {number} pos * @returns {number} */ - setLeft: function(elem, left) { - elem.rzsl = left; - elem.css({ - left: left + 'px' - }); - return left; + setPosition: function(elem, pos) { + elem.rzsp = pos; + var css = {}; + css[this.positionProperty] = pos + 'px'; + elem.css(css); + return pos; }, /** - * Get element width + * Get element width/height depending on whether slider is horizontal or vertical * * @param {jqLite} elem The jqLite wrapped DOM element * @returns {number} */ - getWidth: function(elem) { + getDimension: function(elem) { var val = elem[0].getBoundingClientRect(); - elem.rzsw = (val.right - val.left) * this.options.scale; - return elem.rzsw; + if (this.options.vertical) + elem.rzsd = (val.bottom - val.top) * this.options.scale; + else + elem.rzsd = (val.right - val.left) * this.options.scale; + return elem.rzsd; }, /** - * Set element width + * Set element width/height depending on whether slider is horizontal or vertical * * @param {jqLite} elem The jqLite wrapped DOM element - * @param {number} width + * @param {number} dim * @returns {number} */ - setWidth: function(elem, width) { - elem.rzsw = width; - elem.css({ - width: width + 'px' - }); - return width; + setDimension: function(elem, dim) { + elem.rzsd = dim; + var css = {}; + css[this.dimensionProperty] = dim + 'px'; + elem.css(css); + return dim; }, /** @@ -973,7 +1000,7 @@ * @returns {number} */ valueToOffset: function(val) { - return (this.sanitizeOffsetValue(val) - this.minValue) * this.maxLeft / this.valueRange || 0; + return (this.sanitizeOffsetValue(val) - this.minValue) * this.maxPos / this.valueRange || 0; }, /** @@ -993,26 +1020,42 @@ * @returns {number} */ offsetToValue: function(offset) { - return (offset / this.maxLeft) * this.valueRange + this.minValue; + return (offset / this.maxPos) * this.valueRange + this.minValue; }, // Events /** - * Get the X-coordinate of an event + * Get the X-coordinate or Y-coordinate of an event * * @param {Object} event The event * @returns {number} */ - getEventX: function(event) { + getEventXY: function(event) { /* http://stackoverflow.com/a/12336075/282882 */ //noinspection JSLint - if ('clientX' in event) { - return event.clientX; + var clientXY = this.options.vertical ? 'clientY' : 'clientX'; + if (clientXY in event) { + return event[clientXY]; } return event.originalEvent === undefined ? - event.touches[0].clientX : event.originalEvent.touches[0].clientX; + event.touches[0][clientXY] : event.originalEvent.touches[0][clientXY]; + }, + + /** + * Compute the event position depending on whether the slider is horizontal or vertical + * @param event + * @returns {number} + */ + getEventPosition: function(event) { + var sliderPos = this.sliderElem.rzsp, + eventPos = 0; + if (this.options.vertical) + eventPos = -this.getEventXY(event) + sliderPos; + else + eventPos = this.getEventXY(event) - sliderPos; + return (eventPos - this.handleHalfDim) * this.options.scale; }, /** @@ -1025,8 +1068,8 @@ if (!this.range) { return this.minH; } - var offset = (this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth) * this.options.scale; - return Math.abs(offset - this.minH.rzsl) < Math.abs(offset - this.maxH.rzsl) ? this.minH : this.maxH; + var offset = this.getEventPosition(event); + return Math.abs(offset - this.minH.rzsp) < Math.abs(offset - this.maxH.rzsp) ? this.minH : this.maxH; }, /** @@ -1132,22 +1175,19 @@ * @returns {undefined} */ onMove: function(pointer, event) { - var eventX = this.getEventX(event), - sliderLO, newOffset, newValue; - - sliderLO = this.sliderElem.rzsl; - newOffset = (eventX - sliderLO - this.handleHalfWidth) * this.options.scale; + var newOffset = this.getEventPosition(event), + newValue; if (newOffset <= 0) { - if (pointer.rzsl === 0) + if (pointer.rzsp === 0) return; newValue = this.minValue; newOffset = 0; - } else if (newOffset >= this.maxLeft) { - if (pointer.rzsl === this.maxLeft) + } else if (newOffset >= this.maxPos) { + if (pointer.rzsp === this.maxPos) return; newValue = this.maxValue; - newOffset = this.maxLeft; + newOffset = this.maxPos; } else { newValue = this.offsetToValue(newOffset); newValue = this.roundStep(newValue); @@ -1167,14 +1207,14 @@ * @returns {undefined} */ onDragStart: function(pointer, ref, event) { - var offset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth; + var offset = this.getEventPosition(event); this.dragging = { active: true, value: this.offsetToValue(offset), difference: this.scope.rzSliderHigh - this.scope.rzSliderModel, offset: offset, - lowDist: offset - this.minH.rzsl, - highDist: this.maxH.rzsl - offset + lowDist: offset - this.minH.rzsp, + highDist: this.maxH.rzsp - offset }; this.minH.addClass('rz-active'); this.maxH.addClass('rz-active'); @@ -1192,24 +1232,24 @@ * @returns {undefined} */ onDragMove: function(pointer, event) { - var newOffset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth, + var newOffset = this.getEventPosition(event), newMinOffset, newMaxOffset, newMinValue, newMaxValue; if (newOffset <= this.dragging.lowDist) { - if (pointer.rzsl === this.dragging.lowDist) { + if (pointer.rzsp === this.dragging.lowDist) { return; } newMinValue = this.minValue; newMinOffset = 0; newMaxValue = this.minValue + this.dragging.difference; newMaxOffset = this.valueToOffset(newMaxValue); - } else if (newOffset >= this.maxLeft - this.dragging.highDist) { - if (pointer.rzsl === this.dragging.highDist) { + } else if (newOffset >= this.maxPos - this.dragging.highDist) { + if (pointer.rzsp === this.dragging.highDist) { return; } newMaxValue = this.maxValue; - newMaxOffset = this.maxLeft; + newMaxOffset = this.maxPos; newMinValue = this.maxValue - this.dragging.difference; newMinOffset = this.valueToOffset(newMinValue); } else { @@ -1251,7 +1291,7 @@ /* This is to check if we need to switch the min and max handles*/ if (this.tracking === 'rzSliderModel' && newValue >= this.scope.rzSliderHigh) { this.scope[this.tracking] = this.scope.rzSliderHigh; - this.updateHandles(this.tracking, this.maxH.rzsl); + this.updateHandles(this.tracking, this.maxH.rzsp); this.tracking = 'rzSliderHigh'; this.minH.removeClass('rz-active'); this.maxH.addClass('rz-active'); @@ -1260,7 +1300,7 @@ this.callOnChange(); } else if (this.tracking === 'rzSliderHigh' && newValue <= this.scope.rzSliderModel) { this.scope[this.tracking] = this.scope.rzSliderModel; - this.updateHandles(this.tracking, this.minH.rzsl); + this.updateHandles(this.tracking, this.minH.rzsp); this.tracking = 'rzSliderModel'; this.maxH.removeClass('rz-active'); this.minH.addClass('rz-active'); @@ -1371,8 +1411,8 @@ /** * @name jqLite * - * @property {number|undefined} rzsl rzslider label left offset - * @property {number|undefined} rzsw rzslider element width + * @property {number|undefined} rzsp rzslider label position offset + * @property {number|undefined} rzsd rzslider element dimension * @property {string|undefined} rzsv rzslider label value/text * @property {Function} css * @property {Function} text diff --git a/dist/rzslider.min.css b/dist/rzslider.min.css index 8d72d24..ffd3c62 100644 --- a/dist/rzslider.min.css +++ b/dist/rzslider.min.css @@ -1,2 +1,2 @@ -/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-23 */ -rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:35px 0 15px 0;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}rzslider[disabled]{cursor:not-allowed}rzslider[disabled] .rz-pointer{cursor:not-allowed;background-color:#d8e0f3}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider .rz-base{width:100%;height:100%;padding:0}rzslider .rz-bar-wrapper{left:0;z-index:1;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider .rz-bar-wrapper.rz-draggable{cursor:move}rzslider .rz-bar{left:0;z-index:1;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-bar.rz-selection{z-index:2;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-pointer{top:-14px;z-index:3;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider .rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider .rz-pointer:hover:after{background-color:#fff}rzslider .rz-pointer.rz-active:after{background-color:#451aff}rzslider .rz-bubble{bottom:16px;padding:1px 3px;color:#55637d;cursor:default}rzslider .rz-bubble.rz-selection{top:16px}rzslider .rz-bubble.rz-limit{color:#55637d}rzslider .rz-ticks{position:absolute;top:-3px;left:0;z-index:1;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;padding:0 11px;margin:0;list-style:none;box-sizing:border-box;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}rzslider .rz-ticks .tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .tick.selected{background:#0db9f0}rzslider .rz-ticks .tick .tick-value{position:absolute;top:-30px;transform:translate(-50%,0)} \ No newline at end of file +/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-24 */ +rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:35px 0 15px 0;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}rzslider[disabled]{cursor:not-allowed}rzslider[disabled] .rz-pointer{cursor:not-allowed;background-color:#d8e0f3}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider .rz-base{width:100%;height:100%;padding:0}rzslider .rz-bar-wrapper{left:0;z-index:1;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider .rz-bar-wrapper.rz-draggable{cursor:move}rzslider .rz-bar{left:0;z-index:1;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-bar.rz-selection{z-index:2;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-pointer{top:-14px;z-index:3;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider .rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider .rz-pointer:hover:after{background-color:#fff}rzslider .rz-pointer.rz-active:after{background-color:#451aff}rzslider .rz-bubble{bottom:16px;padding:1px 3px;color:#55637d;cursor:default}rzslider .rz-bubble.rz-selection{top:16px}rzslider .rz-bubble.rz-limit{color:#55637d}rzslider .rz-ticks{position:absolute;top:-3px;left:0;z-index:1;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;padding:0 11px;margin:0;list-style:none;box-sizing:border-box;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}rzslider .rz-ticks .tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .tick.selected{background:#0db9f0}rzslider .rz-ticks .tick .tick-value{position:absolute;top:-30px;transform:translate(-50%,0)}rzslider.vertical{position:relative;width:4px;height:100%;padding:0;margin:0 20px;vertical-align:baseline}rzslider.vertical .rz-base{width:100%;height:100%;padding:0}rzslider.vertical .rz-bar-wrapper{top:auto;left:0;width:32px;height:100%;padding:0 0 0 16px;margin:0 0 0 -16px}rzslider.vertical .rz-bar{bottom:0;left:initial;width:4px;height:100%}rzslider.vertical .rz-pointer{top:auto;bottom:0;left:-14px!important}rzslider.vertical .rz-bubble{bottom:0;left:16px!important;margin-left:3px}rzslider.vertical .rz-bubble.rz-selection{top:auto;left:16px!important}rzslider.vertical .rz-ticks{top:0;left:-3px;z-index:1;width:auto;height:100%;padding:11px 0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}rzslider.vertical .rz-ticks .tick{vertical-align:middle}rzslider.vertical .rz-ticks .tick .tick-value{top:auto;right:-30px;transform:translate(0,-28%)} \ No newline at end of file diff --git a/dist/rzslider.min.js b/dist/rzslider.min.js index be0389a..f2c185a 100644 --- a/dist/rzslider.min.js +++ b/dist/rzslider.min.js @@ -1,2 +1,2 @@ -/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-23 */ -!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):"object"==typeof module&&module.exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){"use strict";var b=a.module("rzModule",[]).factory("RzSliderOptions",function(){var b={floor:0,ceil:null,step:1,precision:0,id:null,translate:null,stepsArray:null,draggableRange:!1,showSelectionBar:!1,hideLimitLabels:!1,readOnly:!1,disabled:!1,interval:350,showTicks:!1,showTicksValues:!1,ticksValuesTooltip:null,scale:1,onStart:null,onChange:null,onEnd:null},c={},d={};return d.options=function(b){a.extend(c,b)},d.getOptions=function(d){return a.extend({},b,c,d)},d}).value("rzThrottle",function(a,b,c){var d,e,f,g=Date.now||function(){return(new Date).getTime()},h=null,i=0;c=c||{};var j=function(){i=c.leading===!1?0:g(),h=null,f=a.apply(d,e),d=e=null};return function(){var k=g();i||c.leading!==!1||(i=k);var l=b-(k-i);return d=this,e=arguments,0>=l?(clearTimeout(h),h=null,i=k,f=a.apply(d,e),d=e=null):h||c.trailing===!1||(h=setTimeout(j,l)),f}}).factory("RzSlider",["$timeout","$document","$window","$compile","RzSliderOptions","rzThrottle",function(b,c,d,e,f,g){var h=function(a,b){this.scope=a,this.sliderElem=b,this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.dragging={active:!1,value:0,difference:0,offset:0,lowDist:0,highDist:0},this.handleHalfWidth=0,this.maxLeft=0,this.precision=0,this.step=0,this.tracking="",this.minValue=0,this.maxValue=0,this.valueRange=0,this.initHasRun=!1,this.fullBar=null,this.selBar=null,this.minH=null,this.maxH=null,this.flrLab=null,this.ceilLab=null,this.minLab=null,this.maxLab=null,this.cmbLab=null,this.ticks=null,this.init()};return h.prototype={init:function(){var c,e,f=a.bind(this,this.calcViewDimensions),h=this;this.applyOptions(),this.initElemHandles(),this.manageElementsStyle(),this.addAccessibility(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions(),this.setMinAndMax(),b(function(){h.updateCeilLab(),h.updateFloorLab(),h.initHandles(),h.bindEvents()}),this.scope.$on("reCalcViewDimensions",f),a.element(d).on("resize",f),this.initHasRun=!0,c=g(function(){h.setMinAndMax(),h.updateLowHandle(h.valueToOffset(h.scope.rzSliderModel)),h.updateSelectionBar(),h.updateTicksScale(),h.range&&h.updateCmbLabel()},h.options.interval),e=g(function(){h.setMinAndMax(),h.updateHighHandle(h.valueToOffset(h.scope.rzSliderHigh)),h.updateSelectionBar(),h.updateTicksScale(),h.updateCmbLabel()},h.options.interval),this.scope.$on("rzSliderForceRender",function(){h.resetLabelsValue(),c(),h.range&&e(),h.resetSlider()}),this.scope.$watch("rzSliderModel",function(a,b){a!==b&&c()}),this.scope.$watch("rzSliderHigh",function(a,b){a!==b&&(null!=a&&e(),(h.range&&null==a||!h.range&&null!=a)&&(h.applyOptions(),h.resetSlider()))}),this.scope.$watch("rzSliderOptions",function(a,b){a!==b&&(h.applyOptions(),h.resetSlider())},!0),this.scope.$on("$destroy",function(){h.unbindEvents(),a.element(d).off("resize",f)})},applyOptions:function(){this.options=f.getOptions(this.scope.rzSliderOptions),this.options.step<=0&&(this.options.step=1),this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.options.draggableRange=this.range&&this.options.draggableRange,this.options.showTicks=this.options.showTicks||this.options.showTicksValues,this.options.stepsArray?(this.options.floor=0,this.options.ceil=this.options.stepsArray.length-1,this.options.step=1,this.customTrFn=function(a){return this.options.stepsArray[a]}):this.options.translate?this.customTrFn=this.options.translate:this.customTrFn=function(a){return String(a)}},resetSlider:function(){this.manageElementsStyle(),this.setMinAndMax(),this.updateCeilLab(),this.updateFloorLab(),this.unbindEvents(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions()},initElemHandles:function(){a.forEach(this.sliderElem.children(),function(b,c){var d=a.element(b);switch(c){case 0:this.fullBar=d;break;case 1:this.selBar=d;break;case 2:this.minH=d;break;case 3:this.maxH=d;break;case 4:this.flrLab=d;break;case 5:this.ceilLab=d;break;case 6:this.minLab=d;break;case 7:this.maxLab=d;break;case 8:this.cmbLab=d;break;case 9:this.ticks=d}},this),this.selBar.rzsl=0,this.minH.rzsl=0,this.maxH.rzsl=0,this.flrLab.rzsl=0,this.ceilLab.rzsl=0,this.minLab.rzsl=0,this.maxLab.rzsl=0,this.cmbLab.rzsl=0},manageElementsStyle:function(){this.range?this.maxH.css("display",null):this.maxH.css("display","none"),this.alwaysHide(this.flrLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.ceilLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.minLab,this.options.showTicksValues),this.alwaysHide(this.maxLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.cmbLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.selBar,!this.range&&!this.options.showSelectionBar),this.options.showTicks||this.ticks.html(""),this.options.draggableRange?this.selBar.addClass("rz-draggable"):this.selBar.removeClass("rz-draggable")},alwaysHide:function(a,b){a.rzAlwaysHide=b,b?this.hideEl(a):this.showEl(a)},manageEventsBindings:function(){this.options.disabled||this.options.readOnly?this.unbindEvents():this.options.disabled&&this.options.readOnly||this.bindEvents()},setDisabledState:function(){this.options.disabled?this.sliderElem.attr("disabled","disabled"):this.sliderElem.attr("disabled",null)},resetLabelsValue:function(){this.minLab.rzsv=void 0,this.maxLab.rzsv=void 0},initHandles:function(){this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.range&&this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateSelectionBar(),this.range&&this.updateCmbLabel(),this.updateTicksScale()},translateFn:function(a,b,c){c=void 0===c?!0:c;var d=String(c?this.customTrFn(a,this.options.id):a),e=!1;(void 0===b.rzsv||b.rzsv.length!==d.length||b.rzsv.length>0&&0===b.rzsw)&&(e=!0,b.rzsv=d),b.text(d),e&&this.getWidth(b)},setMinAndMax:function(){this.step=+this.options.step,this.precision=+this.options.precision,this.scope.rzSliderModel=this.roundStep(this.scope.rzSliderModel),this.range&&(this.scope.rzSliderHigh=this.roundStep(this.scope.rzSliderHigh)),this.minValue=this.roundStep(+this.options.floor),null!=this.options.ceil?this.maxValue=this.roundStep(+this.options.ceil):this.maxValue=this.options.ceil=this.range?this.scope.rzSliderHigh:this.scope.rzSliderModel,this.valueRange=this.maxValue-this.minValue},addAccessibility:function(){this.sliderElem.attr("role","slider")},calcViewDimensions:function(){var a=this.getWidth(this.minH);this.handleHalfWidth=a/2,this.barWidth=this.getWidth(this.fullBar),this.maxLeft=this.barWidth-a,this.getWidth(this.sliderElem),this.sliderElem.rzsl=this.sliderElem[0].getBoundingClientRect().left,this.initHasRun&&(this.updateFloorLab(),this.updateCeilLab(),this.initHandles())},updateTicksScale:function(){if(this.options.showTicks&&this.step){for(var a="",b=Math.round((this.maxValue-this.minValue)/this.step)+1,c=0;b>c;c++){var d=this.roundStep(this.minValue+c*this.step),f=this.isTickSelected(d)?"selected":"";if(a+='
  • ',this.options.showTicksValues){var g="";this.options.ticksValuesTooltip&&(g='uib-tooltip="'+this.options.ticksValuesTooltip(d)+'"'),a+="'+this.getDisplayValue(d)+""}a+="
  • "}this.ticks.html(a),this.options.ticksValuesTooltip&&e(this.ticks.contents())(this.scope)}},isTickSelected:function(a){return!this.range&&this.options.showSelectionBar&&a<=this.scope.rzSliderModel?!0:this.range&&a>=this.scope.rzSliderModel&&a<=this.scope.rzSliderHigh?!0:!1},updateCeilLab:function(){this.translateFn(this.maxValue,this.ceilLab),this.setLeft(this.ceilLab,this.barWidth-this.ceilLab.rzsw),this.getWidth(this.ceilLab)},updateFloorLab:function(){this.translateFn(this.minValue,this.flrLab),this.getWidth(this.flrLab)},callOnStart:function(){if(this.options.onStart){var a=this;b(function(){a.options.onStart(a.options.id)})}},callOnChange:function(){if(this.options.onChange){var a=this;b(function(){a.options.onChange(a.options.id)})}},callOnEnd:function(){if(this.options.onEnd){var a=this;b(function(){a.options.onEnd(a.options.id)})}},updateHandles:function(a,b){return"rzSliderModel"===a?(this.updateLowHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void(this.range&&this.updateCmbLabel())):"rzSliderHigh"===a?(this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void(this.range&&this.updateCmbLabel())):(this.updateLowHandle(b),this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void this.updateCmbLabel())},updateLowHandle:function(a){this.setLeft(this.minH,a),this.translateFn(this.scope.rzSliderModel,this.minLab);var b=Math.min(Math.max(a-this.minLab.rzsw/2+this.handleHalfWidth,0),this.barWidth-this.ceilLab.rzsw);this.setLeft(this.minLab,b),this.shFloorCeil()},updateHighHandle:function(a){this.setLeft(this.maxH,a),this.translateFn(this.scope.rzSliderHigh,this.maxLab);var b=Math.min(a-this.maxLab.rzsw/2+this.handleHalfWidth,this.barWidth-this.ceilLab.rzsw);this.setLeft(this.maxLab,b),this.shFloorCeil()},shFloorCeil:function(){var a=!1,b=!1;this.minLab.rzsl<=this.flrLab.rzsl+this.flrLab.rzsw+5?(a=!0,this.hideEl(this.flrLab)):(a=!1,this.showEl(this.flrLab)),this.minLab.rzsl+this.minLab.rzsw>=this.ceilLab.rzsl-this.handleHalfWidth-10?(b=!0,this.hideEl(this.ceilLab)):(b=!1,this.showEl(this.ceilLab)),this.range&&(this.maxLab.rzsl+this.maxLab.rzsw>=this.ceilLab.rzsl-10?this.hideEl(this.ceilLab):b||this.showEl(this.ceilLab),this.maxLab.rzsl<=this.flrLab.rzsl+this.flrLab.rzsw+this.handleHalfWidth?this.hideEl(this.flrLab):a||this.showEl(this.flrLab))},updateSelectionBar:function(){this.setWidth(this.selBar,Math.abs(this.maxH.rzsl-this.minH.rzsl)+this.handleHalfWidth),this.setLeft(this.selBar,this.range?this.minH.rzsl+this.handleHalfWidth:0)},updateCmbLabel:function(){var a,b;if(this.minLab.rzsl+this.minLab.rzsw+10>=this.maxLab.rzsl){a=this.getDisplayValue(this.scope.rzSliderModel),b=this.getDisplayValue(this.scope.rzSliderHigh),this.translateFn(a+" - "+b,this.cmbLab,!1);var c=Math.min(Math.max(this.selBar.rzsl+this.selBar.rzsw/2-this.cmbLab.rzsw/2,0),this.barWidth-this.cmbLab.rzsw);this.setLeft(this.cmbLab,c),this.hideEl(this.minLab),this.hideEl(this.maxLab),this.showEl(this.cmbLab)}else this.showEl(this.maxLab),this.showEl(this.minLab),this.hideEl(this.cmbLab)},getDisplayValue:function(a){return this.customTrFn(a,this.options.id)},roundStep:function(a){var b=this.step,c=+((a-this.minValue)%b).toFixed(3),d=c>b/2?a+b-c:a-c;return d=d.toFixed(this.precision),+d},hideEl:function(a){return a.css({opacity:0})},showEl:function(a){return a.rzAlwaysHide?a:a.css({opacity:1})},setLeft:function(a,b){return a.rzsl=b,a.css({left:b+"px"}),b},getWidth:function(a){var b=a[0].getBoundingClientRect();return a.rzsw=(b.right-b.left)*this.options.scale,a.rzsw},setWidth:function(a,b){return a.rzsw=b,a.css({width:b+"px"}),b},valueToOffset:function(a){return(this.sanitizeOffsetValue(a)-this.minValue)*this.maxLeft/this.valueRange||0},sanitizeOffsetValue:function(a){return Math.min(Math.max(a,this.minValue),this.maxValue)},offsetToValue:function(a){return a/this.maxLeft*this.valueRange+this.minValue},getEventX:function(a){return"clientX"in a?a.clientX:void 0===a.originalEvent?a.touches[0].clientX:a.originalEvent.touches[0].clientX},getNearestHandle:function(a){if(!this.range)return this.minH;var b=(this.getEventX(a)-this.sliderElem.rzsl-this.handleHalfWidth)*this.options.scale;return Math.abs(b-this.minH.rzsl)=d){if(0===a.rzsl)return;e=this.minValue,d=0}else if(d>=this.maxLeft){if(a.rzsl===this.maxLeft)return;e=this.maxValue,d=this.maxLeft}else e=this.offsetToValue(d),e=this.roundStep(e),d=this.valueToOffset(e);this.positionTrackingHandle(e,d)},onDragStart:function(a,b,c){var d=this.getEventX(c)-this.sliderElem.rzsl-this.handleHalfWidth;this.dragging={active:!0,value:this.offsetToValue(d),difference:this.scope.rzSliderHigh-this.scope.rzSliderModel,offset:d,lowDist:d-this.minH.rzsl,highDist:this.maxH.rzsl-d},this.minH.addClass("rz-active"),this.maxH.addClass("rz-active"),this.onStart(a,b,c)},onDragMove:function(a,b){var c,d,e,f,g=this.getEventX(b)-this.sliderElem.rzsl-this.handleHalfWidth;if(g<=this.dragging.lowDist){if(a.rzsl===this.dragging.lowDist)return;e=this.minValue,c=0,f=this.minValue+this.dragging.difference,d=this.valueToOffset(f)}else if(g>=this.maxLeft-this.dragging.highDist){if(a.rzsl===this.dragging.highDist)return;f=this.maxValue,d=this.maxLeft,e=this.maxValue-this.dragging.difference,c=this.valueToOffset(e)}else e=this.offsetToValue(g-this.dragging.lowDist),e=this.roundStep(e),c=this.valueToOffset(e),f=e+this.dragging.difference,d=this.valueToOffset(f);this.positionTrackingBar(e,f,c,d)},positionTrackingBar:function(a,b,c,d){this.scope.rzSliderModel=a,this.scope.rzSliderHigh=b,this.updateHandles("rzSliderModel",c),this.updateHandles("rzSliderHigh",d),this.scope.$apply(),this.callOnChange()},positionTrackingHandle:function(a,b){this.range&&("rzSliderModel"===this.tracking&&a>=this.scope.rzSliderHigh?(this.scope[this.tracking]=this.scope.rzSliderHigh,this.updateHandles(this.tracking,this.maxH.rzsl),this.tracking="rzSliderHigh",this.minH.removeClass("rz-active"),this.maxH.addClass("rz-active"),this.scope.$apply(),this.callOnChange()):"rzSliderHigh"===this.tracking&&a<=this.scope.rzSliderModel&&(this.scope[this.tracking]=this.scope.rzSliderModel,this.updateHandles(this.tracking,this.minH.rzsl),this.tracking="rzSliderModel",this.maxH.removeClass("rz-active"),this.minH.addClass("rz-active"),this.scope.$apply(),this.callOnChange())),this.scope[this.tracking]!==a&&(this.scope[this.tracking]=a,this.updateHandles(this.tracking,b),this.scope.$apply(),this.callOnChange())},onEnd:function(a,b){var d=this.getEventNames(b).moveEvent;this.minH.removeClass("rz-active"),this.maxH.removeClass("rz-active"),c.off(d,a),this.scope.$emit("slideEnded"),this.tracking="",this.dragging.active=!1,this.callOnEnd()},getEventNames:function(a){var b={moveEvent:"",endEvent:""};return a.touches||void 0!==a.originalEvent&&a.originalEvent.touches?(b.moveEvent="touchmove",b.endEvent="touchend"):(b.moveEvent="mousemove",b.endEvent="mouseup"),b}},h}]).directive("rzslider",["RzSlider",function(a){return{restrict:"E",scope:{rzSliderModel:"=?",rzSliderHigh:"=?",rzSliderOptions:"=?",rzSliderTplUrl:"@"},templateUrl:function(a,b){return b.rzSliderTplUrl||"rzSliderTpl.html"},link:function(b,c){return new a(b,c)}}}]);return b.run(["$templateCache",function(a){a.put("rzSliderTpl.html",'
      ')}]),b}); \ No newline at end of file +/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-24 */ +!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):"object"==typeof module&&module.exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){"use strict";var b=a.module("rzModule",[]).factory("RzSliderOptions",function(){var b={floor:0,ceil:null,step:1,precision:0,id:null,translate:null,stepsArray:null,draggableRange:!1,showSelectionBar:!1,hideLimitLabels:!1,readOnly:!1,disabled:!1,interval:350,showTicks:!1,showTicksValues:!1,ticksValuesTooltip:null,vertical:!1,scale:1,onStart:null,onChange:null,onEnd:null},c={},d={};return d.options=function(b){a.extend(c,b)},d.getOptions=function(d){return a.extend({},b,c,d)},d}).value("rzThrottle",function(a,b,c){var d,e,f,g=Date.now||function(){return(new Date).getTime()},h=null,i=0;c=c||{};var j=function(){i=c.leading===!1?0:g(),h=null,f=a.apply(d,e),d=e=null};return function(){var k=g();i||c.leading!==!1||(i=k);var l=b-(k-i);return d=this,e=arguments,0>=l?(clearTimeout(h),h=null,i=k,f=a.apply(d,e),d=e=null):h||c.trailing===!1||(h=setTimeout(j,l)),f}}).factory("RzSlider",["$timeout","$document","$window","$compile","RzSliderOptions","rzThrottle",function(b,c,d,e,f,g){var h=function(a,b){this.scope=a,this.sliderElem=b,this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.dragging={active:!1,value:0,difference:0,offset:0,lowDist:0,highDist:0},this.positionProperty="left",this.dimensionProperty="width",this.handleHalfDim=0,this.maxPos=0,this.precision=0,this.step=0,this.tracking="",this.minValue=0,this.maxValue=0,this.valueRange=0,this.initHasRun=!1,this.fullBar=null,this.selBar=null,this.minH=null,this.maxH=null,this.flrLab=null,this.ceilLab=null,this.minLab=null,this.maxLab=null,this.cmbLab=null,this.ticks=null,this.init()};return h.prototype={init:function(){var c,e,f=a.bind(this,this.calcViewDimensions),h=this;this.applyOptions(),this.initElemHandles(),this.manageElementsStyle(),this.addAccessibility(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions(),this.setMinAndMax(),b(function(){h.updateCeilLab(),h.updateFloorLab(),h.initHandles(),h.bindEvents()}),this.scope.$on("reCalcViewDimensions",f),a.element(d).on("resize",f),this.options.vertical&&this.sliderElem.addClass("vertical"),this.initHasRun=!0,c=g(function(){h.setMinAndMax(),h.updateLowHandle(h.valueToOffset(h.scope.rzSliderModel)),h.updateSelectionBar(),h.updateTicksScale(),h.range&&h.updateCmbLabel()},h.options.interval),e=g(function(){h.setMinAndMax(),h.updateHighHandle(h.valueToOffset(h.scope.rzSliderHigh)),h.updateSelectionBar(),h.updateTicksScale(),h.updateCmbLabel()},h.options.interval),this.scope.$on("rzSliderForceRender",function(){h.resetLabelsValue(),c(),h.range&&e(),h.resetSlider()}),this.scope.$watch("rzSliderModel",function(a,b){a!==b&&c()}),this.scope.$watch("rzSliderHigh",function(a,b){a!==b&&(null!=a&&e(),(h.range&&null==a||!h.range&&null!=a)&&(h.applyOptions(),h.resetSlider()))}),this.scope.$watch("rzSliderOptions",function(a,b){a!==b&&(h.applyOptions(),h.resetSlider())},!0),this.scope.$on("$destroy",function(){h.unbindEvents(),a.element(d).off("resize",f)})},applyOptions:function(){this.options=f.getOptions(this.scope.rzSliderOptions),this.options.step<=0&&(this.options.step=1),this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.options.draggableRange=this.range&&this.options.draggableRange,this.options.showTicks=this.options.showTicks||this.options.showTicksValues,this.options.stepsArray?(this.options.floor=0,this.options.ceil=this.options.stepsArray.length-1,this.options.step=1,this.customTrFn=function(a){return this.options.stepsArray[a]}):this.options.translate?this.customTrFn=this.options.translate:this.customTrFn=function(a){return String(a)},this.options.vertical&&(this.positionProperty="bottom",this.dimensionProperty="height")},resetSlider:function(){this.manageElementsStyle(),this.setMinAndMax(),this.updateCeilLab(),this.updateFloorLab(),this.unbindEvents(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions()},initElemHandles:function(){a.forEach(this.sliderElem.children(),function(b,c){var d=a.element(b);switch(c){case 0:this.fullBar=d;break;case 1:this.selBar=d;break;case 2:this.minH=d;break;case 3:this.maxH=d;break;case 4:this.flrLab=d;break;case 5:this.ceilLab=d;break;case 6:this.minLab=d;break;case 7:this.maxLab=d;break;case 8:this.cmbLab=d;break;case 9:this.ticks=d}},this),this.selBar.rzsp=0,this.minH.rzsp=0,this.maxH.rzsp=0,this.flrLab.rzsp=0,this.ceilLab.rzsp=0,this.minLab.rzsp=0,this.maxLab.rzsp=0,this.cmbLab.rzsp=0},manageElementsStyle:function(){this.range?this.maxH.css("display",null):this.maxH.css("display","none"),this.alwaysHide(this.flrLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.ceilLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.minLab,this.options.showTicksValues),this.alwaysHide(this.maxLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.cmbLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.selBar,!this.range&&!this.options.showSelectionBar),this.options.showTicks||this.ticks.html(""),this.options.draggableRange?this.selBar.addClass("rz-draggable"):this.selBar.removeClass("rz-draggable")},alwaysHide:function(a,b){a.rzAlwaysHide=b,b?this.hideEl(a):this.showEl(a)},manageEventsBindings:function(){this.options.disabled||this.options.readOnly?this.unbindEvents():this.options.disabled&&this.options.readOnly||this.bindEvents()},setDisabledState:function(){this.options.disabled?this.sliderElem.attr("disabled","disabled"):this.sliderElem.attr("disabled",null)},resetLabelsValue:function(){this.minLab.rzsv=void 0,this.maxLab.rzsv=void 0},initHandles:function(){this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.range&&this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateSelectionBar(),this.range&&this.updateCmbLabel(),this.updateTicksScale()},translateFn:function(a,b,c){c=void 0===c?!0:c;var d=String(c?this.customTrFn(a,this.options.id):a),e=!1;(void 0===b.rzsv||b.rzsv.length!==d.length||b.rzsv.length>0&&0===b.rzsd)&&(e=!0,b.rzsv=d),b.text(d),e&&this.getDimension(b)},setMinAndMax:function(){this.step=+this.options.step,this.precision=+this.options.precision,this.scope.rzSliderModel=this.roundStep(this.scope.rzSliderModel),this.range&&(this.scope.rzSliderHigh=this.roundStep(this.scope.rzSliderHigh)),this.minValue=this.roundStep(+this.options.floor),null!=this.options.ceil?this.maxValue=this.roundStep(+this.options.ceil):this.maxValue=this.options.ceil=this.range?this.scope.rzSliderHigh:this.scope.rzSliderModel,this.valueRange=this.maxValue-this.minValue},addAccessibility:function(){this.sliderElem.attr("role","slider")},calcViewDimensions:function(){var a=this.getDimension(this.minH);this.handleHalfDim=a/2,this.barDimension=this.getDimension(this.fullBar),this.maxPos=this.barDimension-a,this.getDimension(this.sliderElem),this.sliderElem.rzsp=this.sliderElem[0].getBoundingClientRect()[this.positionProperty],this.initHasRun&&(this.updateFloorLab(),this.updateCeilLab(),this.initHandles())},updateTicksScale:function(){if(this.options.showTicks&&this.step){for(var a="",b=Math.round((this.maxValue-this.minValue)/this.step)+1,c=0;b>c;c++){var d=this.roundStep(this.minValue+c*this.step),f=this.isTickSelected(d)?"selected":"";if(a+='
    • ',this.options.showTicksValues){var g="";this.options.ticksValuesTooltip&&(g='uib-tooltip="'+this.options.ticksValuesTooltip(d)+'"',this.options.vertical&&(g+=' tooltip-placement="right"')),a+="'+this.getDisplayValue(d)+""}a+="
    • "}this.ticks.html(a),this.options.ticksValuesTooltip&&e(this.ticks.contents())(this.scope)}},isTickSelected:function(a){return!this.range&&this.options.showSelectionBar&&a<=this.scope.rzSliderModel?!0:this.range&&a>=this.scope.rzSliderModel&&a<=this.scope.rzSliderHigh?!0:!1},updateCeilLab:function(){this.translateFn(this.maxValue,this.ceilLab),this.setPosition(this.ceilLab,this.barDimension-this.ceilLab.rzsd),this.getDimension(this.ceilLab)},updateFloorLab:function(){this.translateFn(this.minValue,this.flrLab),this.getDimension(this.flrLab)},callOnStart:function(){if(this.options.onStart){var a=this;b(function(){a.options.onStart(a.options.id)})}},callOnChange:function(){if(this.options.onChange){var a=this;b(function(){a.options.onChange(a.options.id)})}},callOnEnd:function(){if(this.options.onEnd){var a=this;b(function(){a.options.onEnd(a.options.id)})}},updateHandles:function(a,b){return"rzSliderModel"===a?(this.updateLowHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void(this.range&&this.updateCmbLabel())):"rzSliderHigh"===a?(this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void(this.range&&this.updateCmbLabel())):(this.updateLowHandle(b),this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void this.updateCmbLabel())},updateLowHandle:function(a){this.setPosition(this.minH,a),this.translateFn(this.scope.rzSliderModel,this.minLab);var b=Math.min(Math.max(a-this.minLab.rzsd/2+this.handleHalfDim,0),this.barDimension-this.ceilLab.rzsd);this.setPosition(this.minLab,b),this.shFloorCeil()},updateHighHandle:function(a){this.setPosition(this.maxH,a),this.translateFn(this.scope.rzSliderHigh,this.maxLab);var b=Math.min(a-this.maxLab.rzsd/2+this.handleHalfDim,this.barDimension-this.ceilLab.rzsd);this.setPosition(this.maxLab,b),this.shFloorCeil()},shFloorCeil:function(){var a=!1,b=!1;this.minLab.rzsp<=this.flrLab.rzsp+this.flrLab.rzsd+5?(a=!0,this.hideEl(this.flrLab)):(a=!1,this.showEl(this.flrLab)),this.minLab.rzsp+this.minLab.rzsd>=this.ceilLab.rzsp-this.handleHalfDim-10?(b=!0,this.hideEl(this.ceilLab)):(b=!1,this.showEl(this.ceilLab)),this.range&&(this.maxLab.rzsp+this.maxLab.rzsd>=this.ceilLab.rzsp-10?this.hideEl(this.ceilLab):b||this.showEl(this.ceilLab),this.maxLab.rzsp<=this.flrLab.rzsp+this.flrLab.rzsd+this.handleHalfDim?this.hideEl(this.flrLab):a||this.showEl(this.flrLab))},updateSelectionBar:function(){this.setDimension(this.selBar,Math.abs(this.maxH.rzsp-this.minH.rzsp)+this.handleHalfDim),this.setPosition(this.selBar,this.range?this.minH.rzsp+this.handleHalfDim:0)},updateCmbLabel:function(){var a,b;if(this.minLab.rzsp+this.minLab.rzsd+10>=this.maxLab.rzsp){a=this.getDisplayValue(this.scope.rzSliderModel),b=this.getDisplayValue(this.scope.rzSliderHigh),this.translateFn(a+" - "+b,this.cmbLab,!1);var c=Math.min(Math.max(this.selBar.rzsp+this.selBar.rzsd/2-this.cmbLab.rzsd/2,0),this.barDimension-this.cmbLab.rzsd);this.setPosition(this.cmbLab,c),this.hideEl(this.minLab),this.hideEl(this.maxLab),this.showEl(this.cmbLab)}else this.showEl(this.maxLab),this.showEl(this.minLab),this.hideEl(this.cmbLab)},getDisplayValue:function(a){return this.customTrFn(a,this.options.id)},roundStep:function(a){var b=this.step,c=+((a-this.minValue)%b).toFixed(3),d=c>b/2?a+b-c:a-c;return d=d.toFixed(this.precision),+d},hideEl:function(a){return a.css({opacity:0})},showEl:function(a){return a.rzAlwaysHide?a:a.css({opacity:1})},setPosition:function(a,b){a.rzsp=b;var c={};return c[this.positionProperty]=b+"px",a.css(c),b},getDimension:function(a){var b=a[0].getBoundingClientRect();return this.options.vertical?a.rzsd=(b.bottom-b.top)*this.options.scale:a.rzsd=(b.right-b.left)*this.options.scale,a.rzsd},setDimension:function(a,b){a.rzsd=b;var c={};return c[this.dimensionProperty]=b+"px",a.css(c),b},valueToOffset:function(a){return(this.sanitizeOffsetValue(a)-this.minValue)*this.maxPos/this.valueRange||0},sanitizeOffsetValue:function(a){return Math.min(Math.max(a,this.minValue),this.maxValue)},offsetToValue:function(a){return a/this.maxPos*this.valueRange+this.minValue},getEventXY:function(a){var b=this.options.vertical?"clientY":"clientX";return b in a?a[b]:void 0===a.originalEvent?a.touches[0][b]:a.originalEvent.touches[0][b]},getEventPosition:function(a){var b=this.sliderElem.rzsp,c=0;return c=this.options.vertical?-this.getEventXY(a)+b:this.getEventXY(a)-b,(c-this.handleHalfDim)*this.options.scale},getNearestHandle:function(a){if(!this.range)return this.minH;var b=this.getEventPosition(a);return Math.abs(b-this.minH.rzsp)=d){if(0===a.rzsp)return;c=this.minValue,d=0}else if(d>=this.maxPos){if(a.rzsp===this.maxPos)return;c=this.maxValue,d=this.maxPos}else c=this.offsetToValue(d),c=this.roundStep(c),d=this.valueToOffset(c);this.positionTrackingHandle(c,d)},onDragStart:function(a,b,c){var d=this.getEventPosition(c);this.dragging={active:!0,value:this.offsetToValue(d),difference:this.scope.rzSliderHigh-this.scope.rzSliderModel,offset:d,lowDist:d-this.minH.rzsp,highDist:this.maxH.rzsp-d},this.minH.addClass("rz-active"),this.maxH.addClass("rz-active"),this.onStart(a,b,c)},onDragMove:function(a,b){var c,d,e,f,g=this.getEventPosition(b);if(g<=this.dragging.lowDist){if(a.rzsp===this.dragging.lowDist)return;e=this.minValue,c=0,f=this.minValue+this.dragging.difference,d=this.valueToOffset(f)}else if(g>=this.maxPos-this.dragging.highDist){if(a.rzsp===this.dragging.highDist)return;f=this.maxValue,d=this.maxPos,e=this.maxValue-this.dragging.difference,c=this.valueToOffset(e)}else e=this.offsetToValue(g-this.dragging.lowDist),e=this.roundStep(e),c=this.valueToOffset(e),f=e+this.dragging.difference,d=this.valueToOffset(f);this.positionTrackingBar(e,f,c,d)},positionTrackingBar:function(a,b,c,d){this.scope.rzSliderModel=a,this.scope.rzSliderHigh=b,this.updateHandles("rzSliderModel",c),this.updateHandles("rzSliderHigh",d),this.scope.$apply(),this.callOnChange()},positionTrackingHandle:function(a,b){this.range&&("rzSliderModel"===this.tracking&&a>=this.scope.rzSliderHigh?(this.scope[this.tracking]=this.scope.rzSliderHigh,this.updateHandles(this.tracking,this.maxH.rzsp),this.tracking="rzSliderHigh",this.minH.removeClass("rz-active"),this.maxH.addClass("rz-active"),this.scope.$apply(),this.callOnChange()):"rzSliderHigh"===this.tracking&&a<=this.scope.rzSliderModel&&(this.scope[this.tracking]=this.scope.rzSliderModel,this.updateHandles(this.tracking,this.minH.rzsp),this.tracking="rzSliderModel",this.maxH.removeClass("rz-active"),this.minH.addClass("rz-active"),this.scope.$apply(),this.callOnChange())),this.scope[this.tracking]!==a&&(this.scope[this.tracking]=a,this.updateHandles(this.tracking,b),this.scope.$apply(),this.callOnChange())},onEnd:function(a,b){var d=this.getEventNames(b).moveEvent;this.minH.removeClass("rz-active"),this.maxH.removeClass("rz-active"),c.off(d,a),this.scope.$emit("slideEnded"),this.tracking="",this.dragging.active=!1,this.callOnEnd()},getEventNames:function(a){var b={moveEvent:"",endEvent:""};return a.touches||void 0!==a.originalEvent&&a.originalEvent.touches?(b.moveEvent="touchmove",b.endEvent="touchend"):(b.moveEvent="mousemove",b.endEvent="mouseup"),b}},h}]).directive("rzslider",["RzSlider",function(a){return{restrict:"E",scope:{rzSliderModel:"=?",rzSliderHigh:"=?",rzSliderOptions:"=?",rzSliderTplUrl:"@"},templateUrl:function(a,b){return b.rzSliderTplUrl||"rzSliderTpl.html"},link:function(b,c){return new a(b,c)}}}]);return b.run(["$templateCache",function(a){a.put("rzSliderTpl.html",'
        ')}]),b}); \ No newline at end of file diff --git a/src/rzslider.js b/src/rzslider.js index b35d3b8..5d14970 100644 --- a/src/rzslider.js +++ b/src/rzslider.js @@ -49,6 +49,7 @@ showTicks: false, showTicksValues: false, ticksValuesTooltip: null, + vertical: false, scale: 1, onStart: null, onChange: null, @@ -171,18 +172,30 @@ }; /** - * Half of the width of the slider handles + * property that handle position (defaults to left for horizontal) + * @type {string} + */ + this.positionProperty = 'left'; + + /** + * property that handle dimension (defaults to width for horizontal) + * @type {string} + */ + this.dimensionProperty = 'width'; + + /** + * Half of the width or height of the slider handles * * @type {number} */ - this.handleHalfWidth = 0; + this.handleHalfDim = 0; /** - * Maximum left the slider handle can have + * Maximum position the slider handle can have * * @type {number} */ - this.maxLeft = 0; + this.maxPos = 0; /** * Precision @@ -285,6 +298,9 @@ // Recalculate stuff if view port dimensions have changed angular.element($window).on('resize', calcDimFn); + if (this.options.vertical) + this.sliderElem.addClass('vertical'); + this.initHasRun = true; // Watch for changes to the model @@ -368,12 +384,18 @@ this.customTrFn = function(value) { return this.options.stepsArray[value]; }; - } else if (this.options.translate) + } + else if (this.options.translate) this.customTrFn = this.options.translate; else this.customTrFn = function(value) { return String(value); }; + + if (this.options.vertical) { + this.positionProperty = 'bottom'; + this.dimensionProperty = 'height'; + } }, /** @@ -440,14 +462,14 @@ }, this); // Initialize offset cache properties - this.selBar.rzsl = 0; - this.minH.rzsl = 0; - this.maxH.rzsl = 0; - this.flrLab.rzsl = 0; - this.ceilLab.rzsl = 0; - this.minLab.rzsl = 0; - this.maxLab.rzsl = 0; - this.cmbLab.rzsl = 0; + this.selBar.rzsp = 0; + this.minH.rzsp = 0; + this.maxH.rzsp = 0; + this.flrLab.rzsp = 0; + this.ceilLab.rzsp = 0; + this.minLab.rzsp = 0; + this.maxLab.rzsp = 0; + this.cmbLab.rzsp = 0; }, /** Update each elements style based on options @@ -554,18 +576,18 @@ useCustomTr = useCustomTr === undefined ? true : useCustomTr; var valStr = String((useCustomTr ? this.customTrFn(value, this.options.id) : value)), - getWidth = false; + getDimension = false; - if (label.rzsv === undefined || label.rzsv.length !== valStr.length || (label.rzsv.length > 0 && label.rzsw === 0)) { - getWidth = true; + if (label.rzsv === undefined || label.rzsv.length !== valStr.length || (label.rzsv.length > 0 && label.rzsd === 0)) { + getDimension = true; label.rzsv = valStr; } label.text(valStr); // Update width only when length of the label have changed - if (getWidth) { - this.getWidth(label); + if (getDimension) { + this.getDimension(label); } }, @@ -612,15 +634,15 @@ * @returns {undefined} */ calcViewDimensions: function() { - var handleWidth = this.getWidth(this.minH); + var handleWidth = this.getDimension(this.minH); - this.handleHalfWidth = handleWidth / 2; - this.barWidth = this.getWidth(this.fullBar); + this.handleHalfDim = handleWidth / 2; + this.barDimension = this.getDimension(this.fullBar); - this.maxLeft = this.barWidth - handleWidth; + this.maxPos = this.barDimension - handleWidth; - this.getWidth(this.sliderElem); - this.sliderElem.rzsl = this.sliderElem[0].getBoundingClientRect().left; + this.getDimension(this.sliderElem); + this.sliderElem.rzsp = this.sliderElem[0].getBoundingClientRect()[this.positionProperty]; if (this.initHasRun) { this.updateFloorLab(); @@ -648,6 +670,8 @@ var tooltip = ''; if (this.options.ticksValuesTooltip) { tooltip = 'uib-tooltip="' + this.options.ticksValuesTooltip(value) + '"'; + if(this.options.vertical) + tooltip += ' tooltip-placement="right"' } positions += '' + this.getDisplayValue(value) + ''; } @@ -673,8 +697,8 @@ */ updateCeilLab: function() { this.translateFn(this.maxValue, this.ceilLab); - this.setLeft(this.ceilLab, this.barWidth - this.ceilLab.rzsw); - this.getWidth(this.ceilLab); + this.setPosition(this.ceilLab, this.barDimension - this.ceilLab.rzsd); + this.getDimension(this.ceilLab); }, /** @@ -684,7 +708,7 @@ */ updateFloorLab: function() { this.translateFn(this.minValue, this.flrLab); - this.getWidth(this.flrLab); + this.getDimension(this.flrLab); }, /** @@ -773,10 +797,10 @@ * @returns {undefined} */ updateLowHandle: function(newOffset) { - this.setLeft(this.minH, newOffset); + this.setPosition(this.minH, newOffset); this.translateFn(this.scope.rzSliderModel, this.minLab); - var left = Math.min(Math.max(newOffset - this.minLab.rzsw / 2 + this.handleHalfWidth, 0), this.barWidth - this.ceilLab.rzsw); - this.setLeft(this.minLab, left); + var pos = Math.min(Math.max(newOffset - this.minLab.rzsd / 2 + this.handleHalfDim, 0), this.barDimension - this.ceilLab.rzsd); + this.setPosition(this.minLab, pos); this.shFloorCeil(); }, @@ -788,10 +812,10 @@ * @returns {undefined} */ updateHighHandle: function(newOffset) { - this.setLeft(this.maxH, newOffset); + this.setPosition(this.maxH, newOffset); this.translateFn(this.scope.rzSliderHigh, this.maxLab); - var left = Math.min((newOffset - this.maxLab.rzsw / 2 + this.handleHalfWidth), (this.barWidth - this.ceilLab.rzsw)); - this.setLeft(this.maxLab, left); + var pos = Math.min((newOffset - this.maxLab.rzsd / 2 + this.handleHalfDim), (this.barDimension - this.ceilLab.rzsd)); + this.setPosition(this.maxLab, pos); this.shFloorCeil(); }, @@ -805,7 +829,7 @@ var flHidden = false, clHidden = false; - if (this.minLab.rzsl <= this.flrLab.rzsl + this.flrLab.rzsw + 5) { + if (this.minLab.rzsp <= this.flrLab.rzsp + this.flrLab.rzsd + 5) { flHidden = true; this.hideEl(this.flrLab); } else { @@ -813,7 +837,7 @@ this.showEl(this.flrLab); } - if (this.minLab.rzsl + this.minLab.rzsw >= this.ceilLab.rzsl - this.handleHalfWidth - 10) { + if (this.minLab.rzsp + this.minLab.rzsd >= this.ceilLab.rzsp - this.handleHalfDim - 10) { clHidden = true; this.hideEl(this.ceilLab); } else { @@ -822,14 +846,14 @@ } if (this.range) { - if (this.maxLab.rzsl + this.maxLab.rzsw >= this.ceilLab.rzsl - 10) { + if (this.maxLab.rzsp + this.maxLab.rzsd >= this.ceilLab.rzsp - 10) { this.hideEl(this.ceilLab); } else if (!clHidden) { this.showEl(this.ceilLab); } // Hide or show floor label - if (this.maxLab.rzsl <= this.flrLab.rzsl + this.flrLab.rzsw + this.handleHalfWidth) { + if (this.maxLab.rzsp <= this.flrLab.rzsp + this.flrLab.rzsd + this.handleHalfDim) { this.hideEl(this.flrLab); } else if (!flHidden) { this.showEl(this.flrLab); @@ -843,8 +867,8 @@ * @returns {undefined} */ updateSelectionBar: function() { - this.setWidth(this.selBar, Math.abs(this.maxH.rzsl - this.minH.rzsl) + this.handleHalfWidth); - this.setLeft(this.selBar, this.range ? this.minH.rzsl + this.handleHalfWidth : 0); + this.setDimension(this.selBar, Math.abs(this.maxH.rzsp - this.minH.rzsp) + this.handleHalfDim); + this.setPosition(this.selBar, this.range ? this.minH.rzsp + this.handleHalfDim : 0); }, /** @@ -855,13 +879,13 @@ updateCmbLabel: function() { var lowTr, highTr; - if (this.minLab.rzsl + this.minLab.rzsw + 10 >= this.maxLab.rzsl) { + if (this.minLab.rzsp + this.minLab.rzsd + 10 >= this.maxLab.rzsp) { lowTr = this.getDisplayValue(this.scope.rzSliderModel); highTr = this.getDisplayValue(this.scope.rzSliderHigh); this.translateFn(lowTr + ' - ' + highTr, this.cmbLab, false); - var left = Math.min(Math.max((this.selBar.rzsl + this.selBar.rzsw / 2 - this.cmbLab.rzsw / 2),0),(this.barWidth - this.cmbLab.rzsw)); - this.setLeft(this.cmbLab, left); + var pos = Math.min(Math.max((this.selBar.rzsp + this.selBar.rzsd / 2 - this.cmbLab.rzsd / 2), 0), (this.barDimension - this.cmbLab.rzsd)); + this.setPosition(this.cmbLab, pos); this.hideEl(this.minLab); this.hideEl(this.maxLab); this.showEl(this.cmbLab); @@ -925,45 +949,48 @@ }, /** - * Set element left offset + * Set element left/top offset depending on whether slider is horizontal or vertical * * @param {jqLite} elem The jqLite wrapped DOM element - * @param {number} left + * @param {number} pos * @returns {number} */ - setLeft: function(elem, left) { - elem.rzsl = left; - elem.css({ - left: left + 'px' - }); - return left; + setPosition: function(elem, pos) { + elem.rzsp = pos; + var css = {}; + css[this.positionProperty] = pos + 'px'; + elem.css(css); + return pos; }, /** - * Get element width + * Get element width/height depending on whether slider is horizontal or vertical * * @param {jqLite} elem The jqLite wrapped DOM element * @returns {number} */ - getWidth: function(elem) { + getDimension: function(elem) { var val = elem[0].getBoundingClientRect(); - elem.rzsw = (val.right - val.left) * this.options.scale; - return elem.rzsw; + if (this.options.vertical) + elem.rzsd = (val.bottom - val.top) * this.options.scale; + else + elem.rzsd = (val.right - val.left) * this.options.scale; + return elem.rzsd; }, /** - * Set element width + * Set element width/height depending on whether slider is horizontal or vertical * * @param {jqLite} elem The jqLite wrapped DOM element - * @param {number} width + * @param {number} dim * @returns {number} */ - setWidth: function(elem, width) { - elem.rzsw = width; - elem.css({ - width: width + 'px' - }); - return width; + setDimension: function(elem, dim) { + elem.rzsd = dim; + var css = {}; + css[this.dimensionProperty] = dim + 'px'; + elem.css(css); + return dim; }, /** @@ -973,7 +1000,7 @@ * @returns {number} */ valueToOffset: function(val) { - return (this.sanitizeOffsetValue(val) - this.minValue) * this.maxLeft / this.valueRange || 0; + return (this.sanitizeOffsetValue(val) - this.minValue) * this.maxPos / this.valueRange || 0; }, /** @@ -993,26 +1020,42 @@ * @returns {number} */ offsetToValue: function(offset) { - return (offset / this.maxLeft) * this.valueRange + this.minValue; + return (offset / this.maxPos) * this.valueRange + this.minValue; }, // Events /** - * Get the X-coordinate of an event + * Get the X-coordinate or Y-coordinate of an event * * @param {Object} event The event * @returns {number} */ - getEventX: function(event) { + getEventXY: function(event) { /* http://stackoverflow.com/a/12336075/282882 */ //noinspection JSLint - if ('clientX' in event) { - return event.clientX; + var clientXY = this.options.vertical ? 'clientY' : 'clientX'; + if (clientXY in event) { + return event[clientXY]; } return event.originalEvent === undefined ? - event.touches[0].clientX : event.originalEvent.touches[0].clientX; + event.touches[0][clientXY] : event.originalEvent.touches[0][clientXY]; + }, + + /** + * Compute the event position depending on whether the slider is horizontal or vertical + * @param event + * @returns {number} + */ + getEventPosition: function(event) { + var sliderPos = this.sliderElem.rzsp, + eventPos = 0; + if (this.options.vertical) + eventPos = -this.getEventXY(event) + sliderPos; + else + eventPos = this.getEventXY(event) - sliderPos; + return (eventPos - this.handleHalfDim) * this.options.scale; }, /** @@ -1025,8 +1068,8 @@ if (!this.range) { return this.minH; } - var offset = (this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth) * this.options.scale; - return Math.abs(offset - this.minH.rzsl) < Math.abs(offset - this.maxH.rzsl) ? this.minH : this.maxH; + var offset = this.getEventPosition(event); + return Math.abs(offset - this.minH.rzsp) < Math.abs(offset - this.maxH.rzsp) ? this.minH : this.maxH; }, /** @@ -1132,22 +1175,19 @@ * @returns {undefined} */ onMove: function(pointer, event) { - var eventX = this.getEventX(event), - sliderLO, newOffset, newValue; - - sliderLO = this.sliderElem.rzsl; - newOffset = (eventX - sliderLO - this.handleHalfWidth) * this.options.scale; + var newOffset = this.getEventPosition(event), + newValue; if (newOffset <= 0) { - if (pointer.rzsl === 0) + if (pointer.rzsp === 0) return; newValue = this.minValue; newOffset = 0; - } else if (newOffset >= this.maxLeft) { - if (pointer.rzsl === this.maxLeft) + } else if (newOffset >= this.maxPos) { + if (pointer.rzsp === this.maxPos) return; newValue = this.maxValue; - newOffset = this.maxLeft; + newOffset = this.maxPos; } else { newValue = this.offsetToValue(newOffset); newValue = this.roundStep(newValue); @@ -1167,14 +1207,14 @@ * @returns {undefined} */ onDragStart: function(pointer, ref, event) { - var offset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth; + var offset = this.getEventPosition(event); this.dragging = { active: true, value: this.offsetToValue(offset), difference: this.scope.rzSliderHigh - this.scope.rzSliderModel, offset: offset, - lowDist: offset - this.minH.rzsl, - highDist: this.maxH.rzsl - offset + lowDist: offset - this.minH.rzsp, + highDist: this.maxH.rzsp - offset }; this.minH.addClass('rz-active'); this.maxH.addClass('rz-active'); @@ -1192,24 +1232,24 @@ * @returns {undefined} */ onDragMove: function(pointer, event) { - var newOffset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth, + var newOffset = this.getEventPosition(event), newMinOffset, newMaxOffset, newMinValue, newMaxValue; if (newOffset <= this.dragging.lowDist) { - if (pointer.rzsl === this.dragging.lowDist) { + if (pointer.rzsp === this.dragging.lowDist) { return; } newMinValue = this.minValue; newMinOffset = 0; newMaxValue = this.minValue + this.dragging.difference; newMaxOffset = this.valueToOffset(newMaxValue); - } else if (newOffset >= this.maxLeft - this.dragging.highDist) { - if (pointer.rzsl === this.dragging.highDist) { + } else if (newOffset >= this.maxPos - this.dragging.highDist) { + if (pointer.rzsp === this.dragging.highDist) { return; } newMaxValue = this.maxValue; - newMaxOffset = this.maxLeft; + newMaxOffset = this.maxPos; newMinValue = this.maxValue - this.dragging.difference; newMinOffset = this.valueToOffset(newMinValue); } else { @@ -1251,7 +1291,7 @@ /* This is to check if we need to switch the min and max handles*/ if (this.tracking === 'rzSliderModel' && newValue >= this.scope.rzSliderHigh) { this.scope[this.tracking] = this.scope.rzSliderHigh; - this.updateHandles(this.tracking, this.maxH.rzsl); + this.updateHandles(this.tracking, this.maxH.rzsp); this.tracking = 'rzSliderHigh'; this.minH.removeClass('rz-active'); this.maxH.addClass('rz-active'); @@ -1260,7 +1300,7 @@ this.callOnChange(); } else if (this.tracking === 'rzSliderHigh' && newValue <= this.scope.rzSliderModel) { this.scope[this.tracking] = this.scope.rzSliderModel; - this.updateHandles(this.tracking, this.minH.rzsl); + this.updateHandles(this.tracking, this.minH.rzsp); this.tracking = 'rzSliderModel'; this.maxH.removeClass('rz-active'); this.minH.addClass('rz-active'); @@ -1371,8 +1411,8 @@ /** * @name jqLite * - * @property {number|undefined} rzsl rzslider label left offset - * @property {number|undefined} rzsw rzslider element width + * @property {number|undefined} rzsp rzslider label position offset + * @property {number|undefined} rzsd rzslider element dimension * @property {string|undefined} rzsv rzslider label value/text * @property {Function} css * @property {Function} text diff --git a/src/rzslider.less b/src/rzslider.less index dfdc855..9d06575 100644 --- a/src/rzslider.less +++ b/src/rzslider.less @@ -9,10 +9,9 @@ @import 'variables.less'; rzslider { - display: inline-block; position: relative; - height: @barHeight; + height: @barDimension; width: 100%; margin: 35px 0 15px 0; vertical-align: middle; @@ -57,15 +56,15 @@ rzslider { .rz-bar { left: 0; width: 100%; - height: @barHeight; + height: @barDimension; z-index: 1; background: @barNormalColor; - .rounded(@barHeight/2); + .rounded(@barDimension/2); &.rz-selection { z-index: 2; background: @barFillColor; - .rounded(@barHeight/2); + .rounded(@barDimension/2); } } @@ -73,7 +72,7 @@ rzslider { cursor: pointer; width: @handleSize; height: @handleSize; - top: -@handleSize/2 + @barHeight/2; + top: -@handleSize/2 + @barDimension/2; background-color: @handleBgColor; z-index: 3; .rounded(@handleSize/2); @@ -118,7 +117,7 @@ rzslider { width: 100%; position: absolute; left: 0; - top: -(@ticksHeight - @barHeight) / 2; + top: -(@ticksHeight - @barDimension) / 2; margin: 0; padding: 0 (@handleSize - @ticksWidth) / 2; z-index: 1; @@ -147,4 +146,72 @@ rzslider { } } } + + &.vertical { + position: relative; + width: @barDimension; + height: 100%; + margin: 0 20px; + padding: 0; + vertical-align: baseline; + + .rz-base { + width: 100%; + height: 100%; + padding: 0; + } + + .rz-bar-wrapper { + top: auto; + left: 0; + margin: 0 0 0 -@handleSize / 2; + padding: 0 0 0 @handleSize / 2; + height: 100%; + width: @handleSize; + } + + .rz-bar { + bottom: 0; + left: initial; + width: @barDimension; + height: 100%; + } + + .rz-pointer { + left: -@handleSize/2 + @barDimension/2 !important; + top: auto; + bottom: 0; + } + + .rz-bubble { + left: @handleSize/2 !important; + margin-left: 3px; + bottom: 0; + &.rz-selection { + left: @handleSize/2 !important; + top: auto; + } + } + + .rz-ticks { + height: 100%; + width: auto; + left: -(@ticksHeight - @barDimension) / 2; + top: 0; + padding: (@handleSize - @ticksWidth) / 2 0; + z-index: 1; + -webkit-flex-direction: column-reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; + + .tick { + vertical-align: middle; + .tick-value { + right: @ticksValuePosition; + top: auto; + transform: translate(0, -28%); + } + } + } + } } diff --git a/src/variables.less b/src/variables.less index 95d0279..666e674 100644 --- a/src/variables.less +++ b/src/variables.less @@ -25,4 +25,4 @@ @handleSize: 32px; @handlePointerSize: 8px; @bubblePadding: 1px 3px; -@barHeight: 4px; \ No newline at end of file +@barDimension: 4px; From b98b120d3433665857af1deea5440c631af489c9 Mon Sep 17 00:00:00 2001 From: Valentin Hervieu Date: Wed, 25 Nov 2015 10:05:56 +0100 Subject: [PATCH 2/5] Update ReadMe for vertical sliders --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f84de9d..3445e3a 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ The default options are: interval: 350, showTicks: false, showTicksValues: false, + vertical: false, scale: 1, onStart: null, onChange: null, @@ -199,6 +200,9 @@ $scope.slider = { **onEnd** - _Function(sliderId)_: Function to be called when a slider update is ended. If an id was set in the options, then it's passed to this callback. +**vertical** - _Boolean (defaults to false)_: Set to true to display the slider vertically. The slider will take the full height of its parent. +_Changing this value at runtime is not currently supported._ + ## Change default options If you want the change the default options for all the sliders displayed in your application, you can set them using the `RzSliderOptions.options()` method: ```js From 89e03c15c58ad02ed89ada4fdbaa9dc292aab911 Mon Sep 17 00:00:00 2001 From: Valentin Hervieu Date: Thu, 26 Nov 2015 10:11:03 +0100 Subject: [PATCH 3/5] Add image previews of different sliders --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 3445e3a..8da90e0 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,11 @@ Slider directive implementation for AngularJS, without any dependencies. - Simple to use - Compatibility with jQuery Lite, ie. with full jQuery ( Thanks Jusas! https://github.com/Jusas) +**Horizontal** +![image](https://cloud.githubusercontent.com/assets/2678610/11419158/d51cee88-9425-11e5-9d3f-3f7d97a31c6f.png) +**Vertical** +![image](https://cloud.githubusercontent.com/assets/2678610/11419099/7f4c0e76-9425-11e5-98c6-615412291df1.png) + ## Examples - **Various examples:** [http://rzajac.github.io/angularjs-slider/](http://rzajac.github.io/angularjs-slider/index.html) From b84a3ef596195994f11656e4a0076cb57ab5521e Mon Sep 17 00:00:00 2001 From: Valentin Hervieu Date: Thu, 26 Nov 2015 10:11:57 +0100 Subject: [PATCH 4/5] Fix images position on readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8da90e0..65720f5 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,11 @@ Slider directive implementation for AngularJS, without any dependencies. - Compatibility with jQuery Lite, ie. with full jQuery ( Thanks Jusas! https://github.com/Jusas) **Horizontal** + ![image](https://cloud.githubusercontent.com/assets/2678610/11419158/d51cee88-9425-11e5-9d3f-3f7d97a31c6f.png) + **Vertical** + ![image](https://cloud.githubusercontent.com/assets/2678610/11419099/7f4c0e76-9425-11e5-98c6-615412291df1.png) ## Examples From 9bb67f3533b541219ecc654fdb3c6e1e1fce1575 Mon Sep 17 00:00:00 2001 From: Valentin Hervieu Date: Thu, 26 Nov 2015 10:27:57 +0100 Subject: [PATCH 5/5] Fix vertical sliders positioning on IE10. --- dist/rzslider.css | 2 +- dist/rzslider.min.css | 4 ++-- dist/rzslider.min.js | 2 +- src/rzslider.less | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dist/rzslider.css b/dist/rzslider.css index 7a1cba0..c1f9c90 100644 --- a/dist/rzslider.css +++ b/dist/rzslider.css @@ -189,7 +189,7 @@ rzslider.vertical .rz-bar-wrapper { rzslider.vertical .rz-bar { bottom: 0; - left: initial; + left: auto; width: 4px; height: 100%; } diff --git a/dist/rzslider.min.css b/dist/rzslider.min.css index ffd3c62..8b46b86 100644 --- a/dist/rzslider.min.css +++ b/dist/rzslider.min.css @@ -1,2 +1,2 @@ -/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-24 */ -rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:35px 0 15px 0;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}rzslider[disabled]{cursor:not-allowed}rzslider[disabled] .rz-pointer{cursor:not-allowed;background-color:#d8e0f3}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider .rz-base{width:100%;height:100%;padding:0}rzslider .rz-bar-wrapper{left:0;z-index:1;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider .rz-bar-wrapper.rz-draggable{cursor:move}rzslider .rz-bar{left:0;z-index:1;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-bar.rz-selection{z-index:2;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-pointer{top:-14px;z-index:3;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider .rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider .rz-pointer:hover:after{background-color:#fff}rzslider .rz-pointer.rz-active:after{background-color:#451aff}rzslider .rz-bubble{bottom:16px;padding:1px 3px;color:#55637d;cursor:default}rzslider .rz-bubble.rz-selection{top:16px}rzslider .rz-bubble.rz-limit{color:#55637d}rzslider .rz-ticks{position:absolute;top:-3px;left:0;z-index:1;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;padding:0 11px;margin:0;list-style:none;box-sizing:border-box;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}rzslider .rz-ticks .tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .tick.selected{background:#0db9f0}rzslider .rz-ticks .tick .tick-value{position:absolute;top:-30px;transform:translate(-50%,0)}rzslider.vertical{position:relative;width:4px;height:100%;padding:0;margin:0 20px;vertical-align:baseline}rzslider.vertical .rz-base{width:100%;height:100%;padding:0}rzslider.vertical .rz-bar-wrapper{top:auto;left:0;width:32px;height:100%;padding:0 0 0 16px;margin:0 0 0 -16px}rzslider.vertical .rz-bar{bottom:0;left:initial;width:4px;height:100%}rzslider.vertical .rz-pointer{top:auto;bottom:0;left:-14px!important}rzslider.vertical .rz-bubble{bottom:0;left:16px!important;margin-left:3px}rzslider.vertical .rz-bubble.rz-selection{top:auto;left:16px!important}rzslider.vertical .rz-ticks{top:0;left:-3px;z-index:1;width:auto;height:100%;padding:11px 0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}rzslider.vertical .rz-ticks .tick{vertical-align:middle}rzslider.vertical .rz-ticks .tick .tick-value{top:auto;right:-30px;transform:translate(0,-28%)} \ No newline at end of file +/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-26 */ +rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:35px 0 15px 0;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}rzslider[disabled]{cursor:not-allowed}rzslider[disabled] .rz-pointer{cursor:not-allowed;background-color:#d8e0f3}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider .rz-base{width:100%;height:100%;padding:0}rzslider .rz-bar-wrapper{left:0;z-index:1;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider .rz-bar-wrapper.rz-draggable{cursor:move}rzslider .rz-bar{left:0;z-index:1;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-bar.rz-selection{z-index:2;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-pointer{top:-14px;z-index:3;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider .rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider .rz-pointer:hover:after{background-color:#fff}rzslider .rz-pointer.rz-active:after{background-color:#451aff}rzslider .rz-bubble{bottom:16px;padding:1px 3px;color:#55637d;cursor:default}rzslider .rz-bubble.rz-selection{top:16px}rzslider .rz-bubble.rz-limit{color:#55637d}rzslider .rz-ticks{position:absolute;top:-3px;left:0;z-index:1;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;padding:0 11px;margin:0;list-style:none;box-sizing:border-box;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}rzslider .rz-ticks .tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .tick.selected{background:#0db9f0}rzslider .rz-ticks .tick .tick-value{position:absolute;top:-30px;transform:translate(-50%,0)}rzslider.vertical{position:relative;width:4px;height:100%;padding:0;margin:0 20px;vertical-align:baseline}rzslider.vertical .rz-base{width:100%;height:100%;padding:0}rzslider.vertical .rz-bar-wrapper{top:auto;left:0;width:32px;height:100%;padding:0 0 0 16px;margin:0 0 0 -16px}rzslider.vertical .rz-bar{bottom:0;left:auto;width:4px;height:100%}rzslider.vertical .rz-pointer{top:auto;bottom:0;left:-14px!important}rzslider.vertical .rz-bubble{bottom:0;left:16px!important;margin-left:3px}rzslider.vertical .rz-bubble.rz-selection{top:auto;left:16px!important}rzslider.vertical .rz-ticks{top:0;left:-3px;z-index:1;width:auto;height:100%;padding:11px 0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}rzslider.vertical .rz-ticks .tick{vertical-align:middle}rzslider.vertical .rz-ticks .tick .tick-value{top:auto;right:-30px;transform:translate(0,-28%)} \ No newline at end of file diff --git a/dist/rzslider.min.js b/dist/rzslider.min.js index f2c185a..31d46a8 100644 --- a/dist/rzslider.min.js +++ b/dist/rzslider.min.js @@ -1,2 +1,2 @@ -/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-24 */ +/*! angularjs-slider - v2.0.0 - (c) Rafal Zajac , Valentin Hervieu , Jussi Saarivirta , Angelin Sirbu , https://github.com/rzajac/angularjs-slider.git - 2015-11-26 */ !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):"object"==typeof module&&module.exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){"use strict";var b=a.module("rzModule",[]).factory("RzSliderOptions",function(){var b={floor:0,ceil:null,step:1,precision:0,id:null,translate:null,stepsArray:null,draggableRange:!1,showSelectionBar:!1,hideLimitLabels:!1,readOnly:!1,disabled:!1,interval:350,showTicks:!1,showTicksValues:!1,ticksValuesTooltip:null,vertical:!1,scale:1,onStart:null,onChange:null,onEnd:null},c={},d={};return d.options=function(b){a.extend(c,b)},d.getOptions=function(d){return a.extend({},b,c,d)},d}).value("rzThrottle",function(a,b,c){var d,e,f,g=Date.now||function(){return(new Date).getTime()},h=null,i=0;c=c||{};var j=function(){i=c.leading===!1?0:g(),h=null,f=a.apply(d,e),d=e=null};return function(){var k=g();i||c.leading!==!1||(i=k);var l=b-(k-i);return d=this,e=arguments,0>=l?(clearTimeout(h),h=null,i=k,f=a.apply(d,e),d=e=null):h||c.trailing===!1||(h=setTimeout(j,l)),f}}).factory("RzSlider",["$timeout","$document","$window","$compile","RzSliderOptions","rzThrottle",function(b,c,d,e,f,g){var h=function(a,b){this.scope=a,this.sliderElem=b,this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.dragging={active:!1,value:0,difference:0,offset:0,lowDist:0,highDist:0},this.positionProperty="left",this.dimensionProperty="width",this.handleHalfDim=0,this.maxPos=0,this.precision=0,this.step=0,this.tracking="",this.minValue=0,this.maxValue=0,this.valueRange=0,this.initHasRun=!1,this.fullBar=null,this.selBar=null,this.minH=null,this.maxH=null,this.flrLab=null,this.ceilLab=null,this.minLab=null,this.maxLab=null,this.cmbLab=null,this.ticks=null,this.init()};return h.prototype={init:function(){var c,e,f=a.bind(this,this.calcViewDimensions),h=this;this.applyOptions(),this.initElemHandles(),this.manageElementsStyle(),this.addAccessibility(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions(),this.setMinAndMax(),b(function(){h.updateCeilLab(),h.updateFloorLab(),h.initHandles(),h.bindEvents()}),this.scope.$on("reCalcViewDimensions",f),a.element(d).on("resize",f),this.options.vertical&&this.sliderElem.addClass("vertical"),this.initHasRun=!0,c=g(function(){h.setMinAndMax(),h.updateLowHandle(h.valueToOffset(h.scope.rzSliderModel)),h.updateSelectionBar(),h.updateTicksScale(),h.range&&h.updateCmbLabel()},h.options.interval),e=g(function(){h.setMinAndMax(),h.updateHighHandle(h.valueToOffset(h.scope.rzSliderHigh)),h.updateSelectionBar(),h.updateTicksScale(),h.updateCmbLabel()},h.options.interval),this.scope.$on("rzSliderForceRender",function(){h.resetLabelsValue(),c(),h.range&&e(),h.resetSlider()}),this.scope.$watch("rzSliderModel",function(a,b){a!==b&&c()}),this.scope.$watch("rzSliderHigh",function(a,b){a!==b&&(null!=a&&e(),(h.range&&null==a||!h.range&&null!=a)&&(h.applyOptions(),h.resetSlider()))}),this.scope.$watch("rzSliderOptions",function(a,b){a!==b&&(h.applyOptions(),h.resetSlider())},!0),this.scope.$on("$destroy",function(){h.unbindEvents(),a.element(d).off("resize",f)})},applyOptions:function(){this.options=f.getOptions(this.scope.rzSliderOptions),this.options.step<=0&&(this.options.step=1),this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.options.draggableRange=this.range&&this.options.draggableRange,this.options.showTicks=this.options.showTicks||this.options.showTicksValues,this.options.stepsArray?(this.options.floor=0,this.options.ceil=this.options.stepsArray.length-1,this.options.step=1,this.customTrFn=function(a){return this.options.stepsArray[a]}):this.options.translate?this.customTrFn=this.options.translate:this.customTrFn=function(a){return String(a)},this.options.vertical&&(this.positionProperty="bottom",this.dimensionProperty="height")},resetSlider:function(){this.manageElementsStyle(),this.setMinAndMax(),this.updateCeilLab(),this.updateFloorLab(),this.unbindEvents(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions()},initElemHandles:function(){a.forEach(this.sliderElem.children(),function(b,c){var d=a.element(b);switch(c){case 0:this.fullBar=d;break;case 1:this.selBar=d;break;case 2:this.minH=d;break;case 3:this.maxH=d;break;case 4:this.flrLab=d;break;case 5:this.ceilLab=d;break;case 6:this.minLab=d;break;case 7:this.maxLab=d;break;case 8:this.cmbLab=d;break;case 9:this.ticks=d}},this),this.selBar.rzsp=0,this.minH.rzsp=0,this.maxH.rzsp=0,this.flrLab.rzsp=0,this.ceilLab.rzsp=0,this.minLab.rzsp=0,this.maxLab.rzsp=0,this.cmbLab.rzsp=0},manageElementsStyle:function(){this.range?this.maxH.css("display",null):this.maxH.css("display","none"),this.alwaysHide(this.flrLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.ceilLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.minLab,this.options.showTicksValues),this.alwaysHide(this.maxLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.cmbLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.selBar,!this.range&&!this.options.showSelectionBar),this.options.showTicks||this.ticks.html(""),this.options.draggableRange?this.selBar.addClass("rz-draggable"):this.selBar.removeClass("rz-draggable")},alwaysHide:function(a,b){a.rzAlwaysHide=b,b?this.hideEl(a):this.showEl(a)},manageEventsBindings:function(){this.options.disabled||this.options.readOnly?this.unbindEvents():this.options.disabled&&this.options.readOnly||this.bindEvents()},setDisabledState:function(){this.options.disabled?this.sliderElem.attr("disabled","disabled"):this.sliderElem.attr("disabled",null)},resetLabelsValue:function(){this.minLab.rzsv=void 0,this.maxLab.rzsv=void 0},initHandles:function(){this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.range&&this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateSelectionBar(),this.range&&this.updateCmbLabel(),this.updateTicksScale()},translateFn:function(a,b,c){c=void 0===c?!0:c;var d=String(c?this.customTrFn(a,this.options.id):a),e=!1;(void 0===b.rzsv||b.rzsv.length!==d.length||b.rzsv.length>0&&0===b.rzsd)&&(e=!0,b.rzsv=d),b.text(d),e&&this.getDimension(b)},setMinAndMax:function(){this.step=+this.options.step,this.precision=+this.options.precision,this.scope.rzSliderModel=this.roundStep(this.scope.rzSliderModel),this.range&&(this.scope.rzSliderHigh=this.roundStep(this.scope.rzSliderHigh)),this.minValue=this.roundStep(+this.options.floor),null!=this.options.ceil?this.maxValue=this.roundStep(+this.options.ceil):this.maxValue=this.options.ceil=this.range?this.scope.rzSliderHigh:this.scope.rzSliderModel,this.valueRange=this.maxValue-this.minValue},addAccessibility:function(){this.sliderElem.attr("role","slider")},calcViewDimensions:function(){var a=this.getDimension(this.minH);this.handleHalfDim=a/2,this.barDimension=this.getDimension(this.fullBar),this.maxPos=this.barDimension-a,this.getDimension(this.sliderElem),this.sliderElem.rzsp=this.sliderElem[0].getBoundingClientRect()[this.positionProperty],this.initHasRun&&(this.updateFloorLab(),this.updateCeilLab(),this.initHandles())},updateTicksScale:function(){if(this.options.showTicks&&this.step){for(var a="",b=Math.round((this.maxValue-this.minValue)/this.step)+1,c=0;b>c;c++){var d=this.roundStep(this.minValue+c*this.step),f=this.isTickSelected(d)?"selected":"";if(a+='
      • ',this.options.showTicksValues){var g="";this.options.ticksValuesTooltip&&(g='uib-tooltip="'+this.options.ticksValuesTooltip(d)+'"',this.options.vertical&&(g+=' tooltip-placement="right"')),a+="'+this.getDisplayValue(d)+""}a+="
      • "}this.ticks.html(a),this.options.ticksValuesTooltip&&e(this.ticks.contents())(this.scope)}},isTickSelected:function(a){return!this.range&&this.options.showSelectionBar&&a<=this.scope.rzSliderModel?!0:this.range&&a>=this.scope.rzSliderModel&&a<=this.scope.rzSliderHigh?!0:!1},updateCeilLab:function(){this.translateFn(this.maxValue,this.ceilLab),this.setPosition(this.ceilLab,this.barDimension-this.ceilLab.rzsd),this.getDimension(this.ceilLab)},updateFloorLab:function(){this.translateFn(this.minValue,this.flrLab),this.getDimension(this.flrLab)},callOnStart:function(){if(this.options.onStart){var a=this;b(function(){a.options.onStart(a.options.id)})}},callOnChange:function(){if(this.options.onChange){var a=this;b(function(){a.options.onChange(a.options.id)})}},callOnEnd:function(){if(this.options.onEnd){var a=this;b(function(){a.options.onEnd(a.options.id)})}},updateHandles:function(a,b){return"rzSliderModel"===a?(this.updateLowHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void(this.range&&this.updateCmbLabel())):"rzSliderHigh"===a?(this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void(this.range&&this.updateCmbLabel())):(this.updateLowHandle(b),this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),void this.updateCmbLabel())},updateLowHandle:function(a){this.setPosition(this.minH,a),this.translateFn(this.scope.rzSliderModel,this.minLab);var b=Math.min(Math.max(a-this.minLab.rzsd/2+this.handleHalfDim,0),this.barDimension-this.ceilLab.rzsd);this.setPosition(this.minLab,b),this.shFloorCeil()},updateHighHandle:function(a){this.setPosition(this.maxH,a),this.translateFn(this.scope.rzSliderHigh,this.maxLab);var b=Math.min(a-this.maxLab.rzsd/2+this.handleHalfDim,this.barDimension-this.ceilLab.rzsd);this.setPosition(this.maxLab,b),this.shFloorCeil()},shFloorCeil:function(){var a=!1,b=!1;this.minLab.rzsp<=this.flrLab.rzsp+this.flrLab.rzsd+5?(a=!0,this.hideEl(this.flrLab)):(a=!1,this.showEl(this.flrLab)),this.minLab.rzsp+this.minLab.rzsd>=this.ceilLab.rzsp-this.handleHalfDim-10?(b=!0,this.hideEl(this.ceilLab)):(b=!1,this.showEl(this.ceilLab)),this.range&&(this.maxLab.rzsp+this.maxLab.rzsd>=this.ceilLab.rzsp-10?this.hideEl(this.ceilLab):b||this.showEl(this.ceilLab),this.maxLab.rzsp<=this.flrLab.rzsp+this.flrLab.rzsd+this.handleHalfDim?this.hideEl(this.flrLab):a||this.showEl(this.flrLab))},updateSelectionBar:function(){this.setDimension(this.selBar,Math.abs(this.maxH.rzsp-this.minH.rzsp)+this.handleHalfDim),this.setPosition(this.selBar,this.range?this.minH.rzsp+this.handleHalfDim:0)},updateCmbLabel:function(){var a,b;if(this.minLab.rzsp+this.minLab.rzsd+10>=this.maxLab.rzsp){a=this.getDisplayValue(this.scope.rzSliderModel),b=this.getDisplayValue(this.scope.rzSliderHigh),this.translateFn(a+" - "+b,this.cmbLab,!1);var c=Math.min(Math.max(this.selBar.rzsp+this.selBar.rzsd/2-this.cmbLab.rzsd/2,0),this.barDimension-this.cmbLab.rzsd);this.setPosition(this.cmbLab,c),this.hideEl(this.minLab),this.hideEl(this.maxLab),this.showEl(this.cmbLab)}else this.showEl(this.maxLab),this.showEl(this.minLab),this.hideEl(this.cmbLab)},getDisplayValue:function(a){return this.customTrFn(a,this.options.id)},roundStep:function(a){var b=this.step,c=+((a-this.minValue)%b).toFixed(3),d=c>b/2?a+b-c:a-c;return d=d.toFixed(this.precision),+d},hideEl:function(a){return a.css({opacity:0})},showEl:function(a){return a.rzAlwaysHide?a:a.css({opacity:1})},setPosition:function(a,b){a.rzsp=b;var c={};return c[this.positionProperty]=b+"px",a.css(c),b},getDimension:function(a){var b=a[0].getBoundingClientRect();return this.options.vertical?a.rzsd=(b.bottom-b.top)*this.options.scale:a.rzsd=(b.right-b.left)*this.options.scale,a.rzsd},setDimension:function(a,b){a.rzsd=b;var c={};return c[this.dimensionProperty]=b+"px",a.css(c),b},valueToOffset:function(a){return(this.sanitizeOffsetValue(a)-this.minValue)*this.maxPos/this.valueRange||0},sanitizeOffsetValue:function(a){return Math.min(Math.max(a,this.minValue),this.maxValue)},offsetToValue:function(a){return a/this.maxPos*this.valueRange+this.minValue},getEventXY:function(a){var b=this.options.vertical?"clientY":"clientX";return b in a?a[b]:void 0===a.originalEvent?a.touches[0][b]:a.originalEvent.touches[0][b]},getEventPosition:function(a){var b=this.sliderElem.rzsp,c=0;return c=this.options.vertical?-this.getEventXY(a)+b:this.getEventXY(a)-b,(c-this.handleHalfDim)*this.options.scale},getNearestHandle:function(a){if(!this.range)return this.minH;var b=this.getEventPosition(a);return Math.abs(b-this.minH.rzsp)=d){if(0===a.rzsp)return;c=this.minValue,d=0}else if(d>=this.maxPos){if(a.rzsp===this.maxPos)return;c=this.maxValue,d=this.maxPos}else c=this.offsetToValue(d),c=this.roundStep(c),d=this.valueToOffset(c);this.positionTrackingHandle(c,d)},onDragStart:function(a,b,c){var d=this.getEventPosition(c);this.dragging={active:!0,value:this.offsetToValue(d),difference:this.scope.rzSliderHigh-this.scope.rzSliderModel,offset:d,lowDist:d-this.minH.rzsp,highDist:this.maxH.rzsp-d},this.minH.addClass("rz-active"),this.maxH.addClass("rz-active"),this.onStart(a,b,c)},onDragMove:function(a,b){var c,d,e,f,g=this.getEventPosition(b);if(g<=this.dragging.lowDist){if(a.rzsp===this.dragging.lowDist)return;e=this.minValue,c=0,f=this.minValue+this.dragging.difference,d=this.valueToOffset(f)}else if(g>=this.maxPos-this.dragging.highDist){if(a.rzsp===this.dragging.highDist)return;f=this.maxValue,d=this.maxPos,e=this.maxValue-this.dragging.difference,c=this.valueToOffset(e)}else e=this.offsetToValue(g-this.dragging.lowDist),e=this.roundStep(e),c=this.valueToOffset(e),f=e+this.dragging.difference,d=this.valueToOffset(f);this.positionTrackingBar(e,f,c,d)},positionTrackingBar:function(a,b,c,d){this.scope.rzSliderModel=a,this.scope.rzSliderHigh=b,this.updateHandles("rzSliderModel",c),this.updateHandles("rzSliderHigh",d),this.scope.$apply(),this.callOnChange()},positionTrackingHandle:function(a,b){this.range&&("rzSliderModel"===this.tracking&&a>=this.scope.rzSliderHigh?(this.scope[this.tracking]=this.scope.rzSliderHigh,this.updateHandles(this.tracking,this.maxH.rzsp),this.tracking="rzSliderHigh",this.minH.removeClass("rz-active"),this.maxH.addClass("rz-active"),this.scope.$apply(),this.callOnChange()):"rzSliderHigh"===this.tracking&&a<=this.scope.rzSliderModel&&(this.scope[this.tracking]=this.scope.rzSliderModel,this.updateHandles(this.tracking,this.minH.rzsp),this.tracking="rzSliderModel",this.maxH.removeClass("rz-active"),this.minH.addClass("rz-active"),this.scope.$apply(),this.callOnChange())),this.scope[this.tracking]!==a&&(this.scope[this.tracking]=a,this.updateHandles(this.tracking,b),this.scope.$apply(),this.callOnChange())},onEnd:function(a,b){var d=this.getEventNames(b).moveEvent;this.minH.removeClass("rz-active"),this.maxH.removeClass("rz-active"),c.off(d,a),this.scope.$emit("slideEnded"),this.tracking="",this.dragging.active=!1,this.callOnEnd()},getEventNames:function(a){var b={moveEvent:"",endEvent:""};return a.touches||void 0!==a.originalEvent&&a.originalEvent.touches?(b.moveEvent="touchmove",b.endEvent="touchend"):(b.moveEvent="mousemove",b.endEvent="mouseup"),b}},h}]).directive("rzslider",["RzSlider",function(a){return{restrict:"E",scope:{rzSliderModel:"=?",rzSliderHigh:"=?",rzSliderOptions:"=?",rzSliderTplUrl:"@"},templateUrl:function(a,b){return b.rzSliderTplUrl||"rzSliderTpl.html"},link:function(b,c){return new a(b,c)}}}]);return b.run(["$templateCache",function(a){a.put("rzSliderTpl.html",'
          ')}]),b}); \ No newline at end of file diff --git a/src/rzslider.less b/src/rzslider.less index 9d06575..5213edc 100644 --- a/src/rzslider.less +++ b/src/rzslider.less @@ -172,7 +172,7 @@ rzslider { .rz-bar { bottom: 0; - left: initial; + left: auto; width: @barDimension; height: 100%; }