Commit 22a4ca54 authored by Valentin Hervieu's avatar Valentin Hervieu

feat(ticks): Add legend support.

This feature enables to display legend under each slider tick.
parent 2ffe193d
...@@ -187,6 +187,7 @@ The default options are: ...@@ -187,6 +187,7 @@ The default options are:
minRange: 0, minRange: 0,
id: null, id: null,
translate: null, translate: null,
getLegend: null,
stepsArray: null, stepsArray: null,
draggableRange: false, draggableRange: false,
draggableRangeOnly: false, draggableRangeOnly: false,
...@@ -257,9 +258,22 @@ $scope.slider = { ...@@ -257,9 +258,22 @@ $scope.slider = {
}; };
``` ```
**getLegend** - _Function(value, sliderId)_: Use to display legend under ticks. The function will be called with each tick value and returned content will be displayed under the tick as a legend. If the returned value is null, then no legend is displayed under the corresponding tick.
> In order to get enough space to display legends under the slider, you need to add the `with-legend` class to the slider component. The default margin-bottom is then 40px which is enough for legends that are displayed on 2 lines. If you need more, simply override the style for the class.
**id** - _Any (defaults to null)_: If you want to use the same `translate` function for several sliders, just set the `id` to anything you want, and it will be passed to the `translate(value, sliderId)` function as a second argument. **id** - _Any (defaults to null)_: If you want to use the same `translate` function for several sliders, just set the `id` to anything you want, and it will be passed to the `translate(value, sliderId)` function as a second argument.
**stepsArray** - _Array_: If you want to display a slider with non linear/number steps. Just pass an array with each slider value and that's it; the floor, ceil and step settings of the slider will be computed automatically. The `rz-slider-model` value will be the index of the selected item in the stepsArray. **stepsArray** - _Array_: If you want to display a slider with non linear/number steps.
Just pass an array with each slider value and that's it; the floor, ceil and step settings of the slider will be computed automatically. The `rz-slider-model` value will be the index of the selected item in the stepsArray.
`stepsArray` can also be an array of objects like:
```js
[
{value: 'A'}, // the display value will be *A*
{value: 10, legend: 'Legend for 10'} // the display value will be 10 and a legend will be displayed under the corresponding tick.
]
```
**draggableRange** - _Boolean (defaults to false)_: When set to true and using a range slider, the range can be dragged by the selection bar. *Applies to range slider only.* **draggableRange** - _Boolean (defaults to false)_: When set to true and using a range slider, the range can be dragged by the selection bar. *Applies to range slider only.*
......
...@@ -116,10 +116,10 @@ app.controller('MainCtrl', function($scope, $rootScope, $timeout, $modal) { ...@@ -116,10 +116,10 @@ app.controller('MainCtrl', function($scope, $rootScope, $timeout, $modal) {
$scope.slider_floor_ceil_rtl = { $scope.slider_floor_ceil_rtl = {
value: 12, value: 12,
options: { options: {
floor: 10, floor: 10,
ceil: 100, ceil: 100,
step: 5, step: 5,
rightToLeft: true rightToLeft: true
} }
} }
...@@ -257,6 +257,27 @@ app.controller('MainCtrl', function($scope, $rootScope, $timeout, $modal) { ...@@ -257,6 +257,27 @@ app.controller('MainCtrl', function($scope, $rootScope, $timeout, $modal) {
} }
}; };
//Slider with ticks values and legend
$scope.slider_ticks_legend = {
value: 5,
options: {
ceil: 10,
floor: 0,
showTicksValues: true,
stepsArray: [
{value: 1, legend: 'Very poor'},
{value: 2},
{value: 3, legend: 'Fair'},
{value: 4},
{value: 5, legend: 'Average'},
{value: 6},
{value: 7, legend: 'Good'},
{value: 8},
{value: 9, legend: 'Excellent'}
]
}
};
//Slider with draggable range //Slider with draggable range
$scope.slider_draggable_range = { $scope.slider_draggable_range = {
minValue: 1, minValue: 1,
......
...@@ -195,6 +195,15 @@ ...@@ -195,6 +195,15 @@
rz-slider-model="slider_ticks_values_at.value" rz-slider-model="slider_ticks_values_at.value"
rz-slider-options="slider_ticks_values_at.options" rz-slider-options="slider_ticks_values_at.options"
></rzslider> ></rzslider>
<br><br>
</article>
<article>
<h2>Slider with ticks values and legend</h2>
<rzslider class="with-legend"
rz-slider-model="slider_ticks_legend.value"
rz-slider-options="slider_ticks_legend.options"
></rzslider>
</article> </article>
<article> <article>
......
/*! angularjs-slider - v2.12.0 - /*! angularjs-slider - v2.12.0 -
(c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> -
https://github.com/angular-slider/angularjs-slider - https://github.com/angular-slider/angularjs-slider -
2016-04-22 */ 2016-04-24 */
rzslider { rzslider {
position: relative; position: relative;
display: inline-block; display: inline-block;
...@@ -15,6 +15,10 @@ rzslider { ...@@ -15,6 +15,10 @@ rzslider {
user-select: none; user-select: none;
} }
rzslider.with-legend {
margin-bottom: 40px;
}
rzslider[disabled] { rzslider[disabled] {
cursor: not-allowed; cursor: not-allowed;
} }
...@@ -159,6 +163,14 @@ rzslider .rz-ticks .rz-tick .rz-tick-value { ...@@ -159,6 +163,14 @@ rzslider .rz-ticks .rz-tick .rz-tick-value {
transform: translate(-50%, 0); transform: translate(-50%, 0);
} }
rzslider .rz-ticks .rz-tick .rz-tick-legend {
position: absolute;
top: 24px;
max-width: 50px;
white-space: normal;
transform: translate(-50%, 0);
}
rzslider .rz-ticks.rz-ticks-values-under .rz-tick-value { rzslider .rz-ticks.rz-ticks-values-under .rz-tick-value {
top: initial; top: initial;
bottom: -40px; bottom: -40px;
...@@ -234,6 +246,14 @@ rzslider.rz-vertical .rz-ticks .rz-tick .rz-tick-value { ...@@ -234,6 +246,14 @@ rzslider.rz-vertical .rz-ticks .rz-tick .rz-tick-value {
transform: translate(0, -28%); transform: translate(0, -28%);
} }
rzslider.rz-vertical .rz-ticks .rz-tick .rz-tick-legend {
top: initial;
right: 24px;
max-width: none;
white-space: nowrap;
transform: translate(0, -28%);
}
rzslider.rz-vertical .rz-ticks.rz-ticks-values-under .rz-tick-value { rzslider.rz-vertical .rz-ticks.rz-ticks-values-under .rz-tick-value {
right: 12px; right: 12px;
bottom: initial; bottom: initial;
......
/*! angularjs-slider - v2.12.0 - /*! angularjs-slider - v2.12.0 -
(c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> -
https://github.com/angular-slider/angularjs-slider - https://github.com/angular-slider/angularjs-slider -
2016-04-22 */ 2016-04-24 */
/*jslint unparam: true */ /*jslint unparam: true */
/*global angular: false, console: false, define, module */ /*global angular: false, console: false, define, module */
(function(root, factory) { (function(root, factory) {
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
minRange: 0, minRange: 0,
id: null, id: null,
translate: null, translate: null,
getLegend: null,
stepsArray: null, stepsArray: null,
draggableRange: false, draggableRange: false,
draggableRangeOnly: false, draggableRangeOnly: false,
...@@ -424,30 +425,26 @@ ...@@ -424,30 +425,26 @@
this.options.showTicks = this.options.showTicks || this.options.showTicksValues; this.options.showTicks = this.options.showTicks || this.options.showTicksValues;
this.scope.showTicks = this.options.showTicks; //scope is used in the template this.scope.showTicks = this.options.showTicks; //scope is used in the template
if(angular.isNumber(this.options.showTicks)) if (angular.isNumber(this.options.showTicks))
this.intermediateTicks = true; this.intermediateTicks = true;
this.options.showSelectionBar = this.options.showSelectionBar || this.options.showSelectionBarEnd this.options.showSelectionBar = this.options.showSelectionBar || this.options.showSelectionBarEnd
|| this.options.showSelectionBarFromValue !== null; || this.options.showSelectionBarFromValue !== null;
if (this.options.stepsArray) { if (this.options.stepsArray) {
this.options.floor = 0; this.parseStepsArray();
this.options.ceil = this.options.stepsArray.length - 1; } else {
this.options.step = 1; if (this.options.translate)
if (this.options.translate) {
this.customTrFn = this.options.translate; this.customTrFn = this.options.translate;
} else
else {
this.customTrFn = function(value) { this.customTrFn = function(value) {
return this.options.stepsArray[value]; return String(value);
}; };
if (this.options.getLegend) {
this.getLegend = this.options.getLegend;
} }
} else if (this.options.translate) }
this.customTrFn = this.options.translate;
else
this.customTrFn = function(value) {
return String(value);
};
if (this.options.vertical) { if (this.options.vertical) {
this.positionProperty = 'bottom'; this.positionProperty = 'bottom';
...@@ -455,6 +452,31 @@ ...@@ -455,6 +452,31 @@
} }
}, },
parseStepsArray: function() {
this.options.floor = 0;
this.options.ceil = this.options.stepsArray.length - 1;
this.options.step = 1;
if (this.options.translate) {
this.customTrFn = this.options.translate;
}
else {
this.customTrFn = function(index) {
var step = this.options.stepsArray[index];
if (angular.isObject(step))
return step.value;
return step;
};
}
this.getLegend = function(index) {
var step = this.options.stepsArray[index];
if (angular.isObject(step))
return step.legend;
return null;
};
},
/** /**
* Resets slider * Resets slider
* *
...@@ -558,7 +580,7 @@ ...@@ -558,7 +580,7 @@
else else
this.selBar.removeClass('rz-draggable'); this.selBar.removeClass('rz-draggable');
if(this.intermediateTicks && this.options.showTicksValues) if (this.intermediateTicks && this.options.showTicksValues)
this.ticks.addClass('rz-ticks-values-under'); this.ticks.addClass('rz-ticks-values-under');
}, },
...@@ -768,7 +790,7 @@ ...@@ -768,7 +790,7 @@
updateTicksScale: function() { updateTicksScale: function() {
if (!this.options.showTicks) return; if (!this.options.showTicks) return;
var step = this.step; var step = this.step;
if(this.intermediateTicks) if (this.intermediateTicks)
step = this.options.showTicks; step = this.options.showTicks;
var ticksCount = Math.round((this.maxValue - this.minValue) / step) + 1; var ticksCount = Math.round((this.maxValue - this.minValue) / step) + 1;
this.scope.ticks = []; this.scope.ticks = [];
...@@ -793,6 +815,11 @@ ...@@ -793,6 +815,11 @@
tick.valueTooltipPlacement = this.options.vertical ? 'right' : 'top'; tick.valueTooltipPlacement = this.options.vertical ? 'right' : 'top';
} }
} }
if (this.getLegend) {
var legend = this.getLegend(value, this.options.id);
if (legend)
tick.legend = legend;
}
if (!this.options.rightToLeft) { if (!this.options.rightToLeft) {
this.scope.ticks.push(tick); this.scope.ticks.push(tick);
} else { } else {
...@@ -1458,7 +1485,7 @@ ...@@ -1458,7 +1485,7 @@
newValue = ceilValue; newValue = ceilValue;
} else { } else {
newValue = this.offsetToValue(newOffset); newValue = this.offsetToValue(newOffset);
if(fromTick && angular.isNumber(this.options.showTicks)) if (fromTick && angular.isNumber(this.options.showTicks))
newValue = this.roundStep(newValue, this.options.showTicks); newValue = this.roundStep(newValue, this.options.showTicks);
else else
newValue = this.roundStep(newValue); newValue = this.roundStep(newValue);
...@@ -1911,7 +1938,7 @@ ...@@ -1911,7 +1938,7 @@
'use strict'; 'use strict';
$templateCache.put('rzSliderTpl.html', $templateCache.put('rzSliderTpl.html',
"<span class=rz-bar-wrapper><span class=rz-bar></span></span> <span class=rz-bar-wrapper><span class=\"rz-bar rz-selection\" ng-style=barStyle></span></span> <span class=\"rz-pointer rz-pointer-min\" ng-style=minPointerStyle></span> <span class=\"rz-pointer rz-pointer-max\" ng-style=maxPointerStyle></span> <span class=\"rz-bubble rz-limit\"></span> <span class=\"rz-bubble rz-limit\"></span> <span class=rz-bubble></span> <span class=rz-bubble></span> <span class=rz-bubble></span><ul ng-show=showTicks class=rz-ticks><li ng-repeat=\"t in ticks track by $index\" class=rz-tick ng-class=\"{'rz-selected': t.selected}\" ng-style=t.style ng-attr-uib-tooltip=\"{{ t.tooltip }}\" ng-attr-tooltip-placement={{t.tooltipPlacement}} ng-attr-tooltip-append-to-body=\"{{ t.tooltip ? true : undefined}}\"><span ng-if=\"t.value != null\" class=rz-tick-value ng-attr-uib-tooltip=\"{{ t.valueTooltip }}\" ng-attr-tooltip-placement={{t.valueTooltipPlacement}}>{{ t.value }}</span></li></ul>" "<span class=rz-bar-wrapper><span class=rz-bar></span></span> <span class=rz-bar-wrapper><span class=\"rz-bar rz-selection\" ng-style=barStyle></span></span> <span class=\"rz-pointer rz-pointer-min\" ng-style=minPointerStyle></span> <span class=\"rz-pointer rz-pointer-max\" ng-style=maxPointerStyle></span> <span class=\"rz-bubble rz-limit\"></span> <span class=\"rz-bubble rz-limit\"></span> <span class=rz-bubble></span> <span class=rz-bubble></span> <span class=rz-bubble></span><ul ng-show=showTicks class=rz-ticks><li ng-repeat=\"t in ticks track by $index\" class=rz-tick ng-class=\"{'rz-selected': t.selected}\" ng-style=t.style ng-attr-uib-tooltip=\"{{ t.tooltip }}\" ng-attr-tooltip-placement={{t.tooltipPlacement}} ng-attr-tooltip-append-to-body=\"{{ t.tooltip ? true : undefined}}\"><span ng-if=\"t.value != null\" class=rz-tick-value ng-attr-uib-tooltip=\"{{ t.valueTooltip }}\" ng-attr-tooltip-placement={{t.valueTooltipPlacement}}>{{ t.value }}</span> <span ng-if=\"t.legend != null\" class=rz-tick-legend>{{ t.legend }}</span></li></ul>"
); );
}]); }]);
......
/*! angularjs-slider - v2.12.0 - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - https://github.com/angular-slider/angularjs-slider - 2016-04-22 */ /*! angularjs-slider - v2.12.0 - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - https://github.com/angular-slider/angularjs-slider - 2016-04-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{z-index:4}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%;height:0;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 .rz-tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .rz-tick.rz-selected{background:#0db9f0}rzslider .rz-ticks .rz-tick .rz-tick-value{position:absolute;top:-30px;transform:translate(-50%,0)}rzslider .rz-ticks.rz-ticks-values-under .rz-tick-value{top:initial;bottom:-40px}rzslider.rz-vertical{position:relative;width:4px;height:100%;padding:0;margin:0 20px;vertical-align:baseline}rzslider.rz-vertical .rz-base{width:100%;height:100%;padding:0}rzslider.rz-vertical .rz-bar-wrapper{top:auto;left:0;width:32px;height:100%;padding:0 0 0 16px;margin:0 0 0 -16px}rzslider.rz-vertical .rz-bar{bottom:0;left:auto;width:4px;height:100%}rzslider.rz-vertical .rz-pointer{top:auto;bottom:0;left:-14px!important}rzslider.rz-vertical .rz-bubble{bottom:0;left:16px!important;margin-left:3px}rzslider.rz-vertical .rz-bubble.rz-selection{top:auto;left:16px!important}rzslider.rz-vertical .rz-ticks{top:0;left:-3px;z-index:1;width:0;height:100%;padding:11px 0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}rzslider.rz-vertical .rz-ticks .rz-tick{vertical-align:middle}rzslider.rz-vertical .rz-ticks .rz-tick .rz-tick-value{top:initial;left:22px;transform:translate(0,-28%)}rzslider.rz-vertical .rz-ticks.rz-ticks-values-under .rz-tick-value{right:12px;bottom:initial;left:initial} 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.with-legend{margin-bottom:40px}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{z-index:4}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%;height:0;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 .rz-tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .rz-tick.rz-selected{background:#0db9f0}rzslider .rz-ticks .rz-tick .rz-tick-value{position:absolute;top:-30px;transform:translate(-50%,0)}rzslider .rz-ticks .rz-tick .rz-tick-legend{position:absolute;top:24px;max-width:50px;white-space:normal;transform:translate(-50%,0)}rzslider .rz-ticks.rz-ticks-values-under .rz-tick-value{top:initial;bottom:-40px}rzslider.rz-vertical{position:relative;width:4px;height:100%;padding:0;margin:0 20px;vertical-align:baseline}rzslider.rz-vertical .rz-base{width:100%;height:100%;padding:0}rzslider.rz-vertical .rz-bar-wrapper{top:auto;left:0;width:32px;height:100%;padding:0 0 0 16px;margin:0 0 0 -16px}rzslider.rz-vertical .rz-bar{bottom:0;left:auto;width:4px;height:100%}rzslider.rz-vertical .rz-pointer{top:auto;bottom:0;left:-14px!important}rzslider.rz-vertical .rz-bubble{bottom:0;left:16px!important;margin-left:3px}rzslider.rz-vertical .rz-bubble.rz-selection{top:auto;left:16px!important}rzslider.rz-vertical .rz-ticks{top:0;left:-3px;z-index:1;width:0;height:100%;padding:11px 0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}rzslider.rz-vertical .rz-ticks .rz-tick{vertical-align:middle}rzslider.rz-vertical .rz-ticks .rz-tick .rz-tick-value{top:initial;left:22px;transform:translate(0,-28%)}rzslider.rz-vertical .rz-ticks .rz-tick .rz-tick-legend{top:initial;right:24px;max-width:none;white-space:nowrap;transform:translate(0,-28%)}rzslider.rz-vertical .rz-ticks.rz-ticks-values-under .rz-tick-value{right:12px;bottom:initial;left:initial}
\ No newline at end of file \ No newline at end of file
This diff is collapsed.
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
ng-attr-uib-tooltip="{{ t.tooltip }}" ng-attr-tooltip-placement="{{t.tooltipPlacement}}" ng-attr-uib-tooltip="{{ t.tooltip }}" ng-attr-tooltip-placement="{{t.tooltipPlacement}}"
ng-attr-tooltip-append-to-body="{{ t.tooltip ? true : undefined}}"> ng-attr-tooltip-append-to-body="{{ t.tooltip ? true : undefined}}">
<span ng-if="t.value != null" class="rz-tick-value" <span ng-if="t.value != null" class="rz-tick-value"
ng-attr-uib-tooltip="{{ t.valueTooltip }}" ng-attr-uib-tooltip="{{ t.valueTooltip }}"
ng-attr-tooltip-placement="{{t.valueTooltipPlacement}}">{{ t.value }}</span> ng-attr-tooltip-placement="{{t.valueTooltipPlacement}}">{{ t.value }}</span>
<span ng-if="t.legend != null" class="rz-tick-legend">{{ t.legend }}</span>
</li> </li>
</ul> </ul>
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
minRange: 0, minRange: 0,
id: null, id: null,
translate: null, translate: null,
getLegend: null,
stepsArray: null, stepsArray: null,
draggableRange: false, draggableRange: false,
draggableRangeOnly: false, draggableRangeOnly: false,
...@@ -428,30 +429,26 @@ ...@@ -428,30 +429,26 @@
this.options.showTicks = this.options.showTicks || this.options.showTicksValues; this.options.showTicks = this.options.showTicks || this.options.showTicksValues;
this.scope.showTicks = this.options.showTicks; //scope is used in the template this.scope.showTicks = this.options.showTicks; //scope is used in the template
if(angular.isNumber(this.options.showTicks)) if (angular.isNumber(this.options.showTicks))
this.intermediateTicks = true; this.intermediateTicks = true;
this.options.showSelectionBar = this.options.showSelectionBar || this.options.showSelectionBarEnd this.options.showSelectionBar = this.options.showSelectionBar || this.options.showSelectionBarEnd
|| this.options.showSelectionBarFromValue !== null; || this.options.showSelectionBarFromValue !== null;
if (this.options.stepsArray) { if (this.options.stepsArray) {
this.options.floor = 0; this.parseStepsArray();
this.options.ceil = this.options.stepsArray.length - 1; } else {
this.options.step = 1; if (this.options.translate)
if (this.options.translate) {
this.customTrFn = this.options.translate; this.customTrFn = this.options.translate;
} else
else {
this.customTrFn = function(value) { this.customTrFn = function(value) {
return this.options.stepsArray[value]; return String(value);
}; };
if (this.options.getLegend) {
this.getLegend = this.options.getLegend;
} }
} else if (this.options.translate) }
this.customTrFn = this.options.translate;
else
this.customTrFn = function(value) {
return String(value);
};
if (this.options.vertical) { if (this.options.vertical) {
this.positionProperty = 'bottom'; this.positionProperty = 'bottom';
...@@ -459,6 +456,31 @@ ...@@ -459,6 +456,31 @@
} }
}, },
parseStepsArray: function() {
this.options.floor = 0;
this.options.ceil = this.options.stepsArray.length - 1;
this.options.step = 1;
if (this.options.translate) {
this.customTrFn = this.options.translate;
}
else {
this.customTrFn = function(index) {
var step = this.options.stepsArray[index];
if (angular.isObject(step))
return step.value;
return step;
};
}
this.getLegend = function(index) {
var step = this.options.stepsArray[index];
if (angular.isObject(step))
return step.legend;
return null;
};
},
/** /**
* Resets slider * Resets slider
* *
...@@ -562,7 +584,7 @@ ...@@ -562,7 +584,7 @@
else else
this.selBar.removeClass('rz-draggable'); this.selBar.removeClass('rz-draggable');
if(this.intermediateTicks && this.options.showTicksValues) if (this.intermediateTicks && this.options.showTicksValues)
this.ticks.addClass('rz-ticks-values-under'); this.ticks.addClass('rz-ticks-values-under');
}, },
...@@ -772,7 +794,7 @@ ...@@ -772,7 +794,7 @@
updateTicksScale: function() { updateTicksScale: function() {
if (!this.options.showTicks) return; if (!this.options.showTicks) return;
var step = this.step; var step = this.step;
if(this.intermediateTicks) if (this.intermediateTicks)
step = this.options.showTicks; step = this.options.showTicks;
var ticksCount = Math.round((this.maxValue - this.minValue) / step) + 1; var ticksCount = Math.round((this.maxValue - this.minValue) / step) + 1;
this.scope.ticks = []; this.scope.ticks = [];
...@@ -797,6 +819,11 @@ ...@@ -797,6 +819,11 @@
tick.valueTooltipPlacement = this.options.vertical ? 'right' : 'top'; tick.valueTooltipPlacement = this.options.vertical ? 'right' : 'top';
} }
} }
if (this.getLegend) {
var legend = this.getLegend(value, this.options.id);
if (legend)
tick.legend = legend;
}
if (!this.options.rightToLeft) { if (!this.options.rightToLeft) {
this.scope.ticks.push(tick); this.scope.ticks.push(tick);
} else { } else {
...@@ -1462,7 +1489,7 @@ ...@@ -1462,7 +1489,7 @@
newValue = ceilValue; newValue = ceilValue;
} else { } else {
newValue = this.offsetToValue(newOffset); newValue = this.offsetToValue(newOffset);
if(fromTick && angular.isNumber(this.options.showTicks)) if (fromTick && angular.isNumber(this.options.showTicks))
newValue = this.roundStep(newValue, this.options.showTicks); newValue = this.roundStep(newValue, this.options.showTicks);
else else
newValue = this.roundStep(newValue); newValue = this.roundStep(newValue);
......
...@@ -20,6 +20,10 @@ rzslider { ...@@ -20,6 +20,10 @@ rzslider {
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
&.with-legend {
margin-bottom: @withLegendMargin;
}
&[disabled] { &[disabled] {
cursor: not-allowed; cursor: not-allowed;
.rz-pointer { .rz-pointer {
...@@ -148,6 +152,13 @@ rzslider { ...@@ -148,6 +152,13 @@ rzslider {
top: @ticksValuePosition; top: @ticksValuePosition;
transform: translate(-50%, 0); transform: translate(-50%, 0);
} }
.rz-tick-legend {
position: absolute;
top: @ticksLegendPosition;
transform: translate(-50%, 0);
max-width: 50px;
white-space: normal;
}
} }
&.rz-ticks-values-under { &.rz-ticks-values-under {
...@@ -222,6 +233,13 @@ rzslider { ...@@ -222,6 +233,13 @@ rzslider {
top: initial; top: initial;
transform: translate(0, -28%); transform: translate(0, -28%);
} }
.rz-tick-legend {
top: initial;
right: @ticksLegendPosition;
transform: translate(0, -28%);
max-width: none;
white-space: nowrap;
}
} }
&.rz-ticks-values-under { &.rz-ticks-values-under {
......
...@@ -19,9 +19,12 @@ ...@@ -19,9 +19,12 @@
@ticksWidth: 10px; @ticksWidth: 10px;
@ticksHeight: 10px; @ticksHeight: 10px;
@ticksValuePosition: -30px; @ticksValuePosition: -30px;
@ticksLegendPosition: 24px;
@ticksValuePositionOnVertical: 22px; @ticksValuePositionOnVertical: 22px;
@handleSize: 32px; @handleSize: 32px;
@handlePointerSize: 8px; @handlePointerSize: 8px;
@bubblePadding: 1px 3px; @bubblePadding: 1px 3px;
@barDimension: 4px; @barDimension: 4px;
@withLegendMargin: 40px;
...@@ -104,8 +104,20 @@ ...@@ -104,8 +104,20 @@
expect(helper.slider.options.draggableRangeOnly).to.be.false; expect(helper.slider.options.draggableRangeOnly).to.be.false;
}); });
it('should set correct step/floor/ceil and translate function when stepsArray is used', function() { it('should set correct step/floor/ceil and translate function when stepsArray is used with values', function() {
helper.scope.slider.options.stepsArray = ['A', 'B', 'C', 'D', 'E'];
helper.scope.$digest();
expect(helper.slider.options.step).to.equal(1);
expect(helper.slider.options.floor).to.equal(0);
expect(helper.slider.options.ceil).to.equal(4);
expect(helper.slider.customTrFn(0)).to.equal('A');
expect(helper.slider.customTrFn(2)).to.equal('C');
});
it('should set correct step/floor/ceil and translate function when stepsArray is used with values and ticks', function() {
helper.scope.slider.options.stepsArray = ['A', 'B', 'C', 'D', 'E']; helper.scope.slider.options.stepsArray = ['A', 'B', 'C', 'D', 'E'];
helper.scope.slider.options.showTicks = true;
helper.scope.$digest(); helper.scope.$digest();
expect(helper.slider.options.step).to.equal(1); expect(helper.slider.options.step).to.equal(1);
expect(helper.slider.options.floor).to.equal(0); expect(helper.slider.options.floor).to.equal(0);
...@@ -115,6 +127,48 @@ ...@@ -115,6 +127,48 @@
expect(helper.slider.customTrFn(2)).to.equal('C'); expect(helper.slider.customTrFn(2)).to.equal('C');
}); });
it('should set correct step/floor/ceil and translate function when stepsArray is used with objects', function() {
helper.scope.slider.options.stepsArray = [
{value: 'A'},
{value: 'B'},
{value: 'C'},
{value: 'D'},
{value: 'E'}
];
helper.scope.$digest();
expect(helper.slider.options.step).to.equal(1);
expect(helper.slider.options.floor).to.equal(0);
expect(helper.slider.options.ceil).to.equal(4);
expect(helper.slider.customTrFn(0)).to.equal('A');
expect(helper.slider.customTrFn(2)).to.equal('C');
});
it('should set correct step/floor/ceil and translate function when stepsArray is used with objects containing legends', function() {
helper.scope.slider.options.stepsArray = [
{value: 'A'},
{value: 'B', legend: 'Legend B'},
{value: 'C'},
{value: 'D', legend: 'Legend D'},
{value: 'E'}
];
helper.scope.slider.options.showTicks = true;
helper.scope.$digest();
expect(helper.slider.options.step).to.equal(1);
expect(helper.slider.options.floor).to.equal(0);
expect(helper.slider.options.ceil).to.equal(4);
expect(helper.slider.customTrFn(0)).to.equal('A');
expect(helper.slider.customTrFn(2)).to.equal('C');
expect(helper.slider.getLegend(1)).to.equal('Legend B');
expect(helper.slider.getLegend(3)).to.equal('Legend D');
expect(helper.element[0].querySelectorAll('.rz-tick-legend')).to.have.length(2);
});
it('should allow a custom translate function when stepsArray is used', function() { it('should allow a custom translate function when stepsArray is used', function() {
helper.scope.slider.options.stepsArray = [{'foo': 'barA'}, {'foo': 'barB'}, {'foo': 'barC'}]; helper.scope.slider.options.stepsArray = [{'foo': 'barA'}, {'foo': 'barB'}, {'foo': 'barC'}];
helper.scope.slider.options.translate = function(value, sliderId, label) { helper.scope.slider.options.translate = function(value, sliderId, label) {
......
...@@ -102,6 +102,50 @@ ...@@ -102,6 +102,50 @@
expect(lastTick.text()).to.equal('100'); expect(lastTick.text()).to.equal('100');
}); });
it('should create the correct number of legend items when getLegend is defined', function() {
var sliderConf = {
value: 50,
options: {
floor: 0,
ceil: 100,
step: 10,
showTicks: true,
getLegend: function(value) {
return 'Legend for ' + value;
}
}
};
helper.createSlider(sliderConf);
expect(helper.element[0].querySelectorAll('.rz-tick-legend')).to.have.length(11);
var firstLegend = angular.element(helper.element[0].querySelectorAll('.rz-tick-legend')[0]);
expect(firstLegend.text()).to.equal('Legend for 0');
var lastLegend = angular.element(helper.element[0].querySelectorAll('.rz-tick-legend')[10]);
expect(lastLegend.text()).to.equal('Legend for 100');
});
it('should create the correct number of legend items when getLegend is defined and only some legend are displayed', function() {
var sliderConf = {
value: 50,
options: {
floor: 0,
ceil: 100,
step: 10,
showTicks: true,
getLegend: function(value) {
if(value % 20 === 0)
return 'Legend for ' + value;
return null;
}
}
};
helper.createSlider(sliderConf);
expect(helper.element[0].querySelectorAll('.rz-tick-legend')).to.have.length(6);
var firstLegend = angular.element(helper.element[0].querySelectorAll('.rz-tick-legend')[0]);
expect(firstLegend.text()).to.equal('Legend for 0');
var lastLegend = angular.element(helper.element[0].querySelectorAll('.rz-tick-legend')[5]);
expect(lastLegend.text()).to.equal('Legend for 100');
});
it('should set rz-selected class to ticks below the model value if showSelectionBar is true', function() { it('should set rz-selected class to ticks below the model value if showSelectionBar is true', function() {
var sliderConf = { var sliderConf = {
value: 50, value: 50,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment