Skip to content

Commit 28fb68c

Browse files
authored
feat(slider): restrictedLabels, min/maxRange, always ticks, tooltip
This PR adds new features to the slider module: minRange and maxRange settings to be able to restrict a range slider to a specific range by giving edge values minRange: 5 makes sure that the two thumbs always need to have a difference of 5 maxRange: 10 makes sure that the two thumbs dont exceed a difference of 10 restrictedLabels: an array of label values which restrict the displayed labels to only those which are defined showLabelTicks "always". This differs from "true" and comes in handy when used together with "restrictedLabels" 'always' will always show the ticks for all labels (even if not shown) true will display the ticks only if the related label is also shown showThumbTooltip option will display a tooltip containing the current value to the thumb(s)
1 parent e2d4cc1 commit 28fb68c

File tree

2 files changed

+118
-23
lines changed

2 files changed

+118
-23
lines changed

src/definitions/modules/popup.less

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@
117117
[data-tooltip]::before,
118118
[data-tooltip]::after {
119119
pointer-events: none;
120-
visibility: hidden;
121120
opacity: 0;
122121
transition:
123122
transform @tooltipDuration @tooltipEasing,
@@ -138,9 +137,10 @@
138137
[data-tooltip]::after {
139138
transform-origin: center bottom;
140139
}
140+
[data-tooltip][data-variation~="visible"]::before,
141+
[data-tooltip][data-variation~="visible"]::after,
141142
[data-tooltip]:hover::before,
142143
[data-tooltip]:hover::after {
143-
visibility: visible;
144144
pointer-events: auto;
145145
opacity: 1;
146146
}

src/definitions/modules/slider.js

Lines changed: 116 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -135,20 +135,32 @@
135135
$module.attr('tabindex', 0);
136136
}
137137
if ($module.find('.inner').length === 0) {
138-
$module.append("<div class='inner'>"
139-
+ "<div class='track'></div>"
140-
+ "<div class='track-fill'></div>"
141-
+ "<div class='thumb'></div>"
138+
$module.append('<div class="inner">'
139+
+ '<div class="track"></div>'
140+
+ '<div class="track-fill"></div>'
141+
+ '<div class="thumb"></div>'
142142
+ '</div>');
143143
}
144144
precision = module.get.precision();
145145
$thumb = $module.find('.thumb:not(.second)');
146+
if (settings.showThumbTooltip) {
147+
$thumb
148+
.attr('data-position', settings.tooltipConfig.position)
149+
.attr('data-variation', settings.tooltipConfig.variation)
150+
;
151+
}
146152
$currThumb = $thumb;
147153
if (module.is.range()) {
148154
if ($module.find('.thumb.second').length === 0) {
149-
$module.find('.inner').append("<div class='thumb second'></div>");
155+
$module.find('.inner').append('<div class="thumb second"></div>');
150156
}
151157
$secondThumb = $module.find('.thumb.second');
158+
if (settings.showThumbTooltip) {
159+
$secondThumb
160+
.attr('data-position', settings.tooltipConfig.position)
161+
.attr('data-variation', settings.tooltipConfig.variation)
162+
;
163+
}
152164
}
153165
$track = $module.find('.track');
154166
$trackFill = $module.find('.track-fill');
@@ -202,9 +214,10 @@
202214
for (var i = 0, len = module.get.numLabels(); i <= len; i++) {
203215
var
204216
labelText = module.get.label(i),
205-
$label = labelText !== ''
217+
showLabel = settings.restrictedLabels.length === 0 || settings.restrictedLabels.indexOf(labelText) >= 0,
218+
$label = labelText !== '' && (showLabel || settings.showLabelTicks === 'always')
206219
? (!(i % module.get.gapRatio())
207-
? $('<li class="label">' + labelText + '</li>')
220+
? $('<li class="label">' + (showLabel ? labelText : '') + '</li>')
208221
: $('<li class="halftick label"></li>'))
209222
: null,
210223
ratio = i / len
@@ -348,6 +361,18 @@
348361
;
349362
$currThumb = initialPosition > newPos ? $thumb : $secondThumb;
350363
}
364+
if (module.is.range() && (settings.minRange || settings.maxRange)) {
365+
var currentRangeDiff = module.get.currentRangeDiff(value),
366+
isSecondThumb = $currThumb.hasClass('second')
367+
;
368+
if ((settings.minRange && currentRangeDiff < settings.minRange)
369+
|| (settings.maxRange && currentRangeDiff > settings.maxRange)
370+
|| (settings.preventCrossover && !isSecondThumb && value > module.secondThumbVal)
371+
|| (settings.preventCrossover && isSecondThumb && value < module.thumbVal)
372+
) {
373+
return;
374+
}
375+
}
351376
if (module.get.step() === 0 || module.is.smooth()) {
352377
var
353378
thumbVal = module.thumbVal,
@@ -383,6 +408,17 @@
383408
return;
384409
}
385410
var value = module.determine.valueFromEvent(event);
411+
if (module.is.range() && (settings.minRange || settings.maxRange)) {
412+
if ($currThumb === undefined) {
413+
$currThumb = value <= module.get.currentThumbValue() ? $thumb : $secondThumb;
414+
}
415+
var currentRangeDiff = module.get.currentRangeDiff(value);
416+
if (settings.minRange && currentRangeDiff < settings.minRange) {
417+
value = module.get.edgeValue(value, settings.minRange);
418+
} else if (settings.maxRange && currentRangeDiff > settings.maxRange) {
419+
value = module.get.edgeValue(value, settings.maxRange);
420+
}
421+
}
386422
module.set.value(value);
387423
module.unbind.slidingEvents();
388424
touchIdentifier = undefined;
@@ -503,7 +539,13 @@
503539

504540
is: {
505541
range: function () {
506-
return $module.hasClass(settings.className.range);
542+
var isRange = $module.hasClass(className.range);
543+
if (!isRange && (settings.minRange || settings.maxRange)) {
544+
$module.addClass(className.range);
545+
isRange = true;
546+
}
547+
548+
return isRange;
507549
},
508550
hover: function () {
509551
return isHover;
@@ -512,23 +554,56 @@
512554
return $module.is(':focus');
513555
},
514556
disabled: function () {
515-
return $module.hasClass(settings.className.disabled);
557+
return $module.hasClass(className.disabled);
516558
},
517559
labeled: function () {
518-
return $module.hasClass(settings.className.labeled);
560+
var isLabeled = $module.hasClass(className.labeled);
561+
if (!isLabeled && (settings.restrictedLabels.length > 0 || settings.showLabelTicks !== false)) {
562+
$module.addClass(className.labeled);
563+
isLabeled = true;
564+
}
565+
566+
return isLabeled;
519567
},
520568
reversed: function () {
521-
return $module.hasClass(settings.className.reversed);
569+
return $module.hasClass(className.reversed);
522570
},
523571
vertical: function () {
524-
return $module.hasClass(settings.className.vertical);
572+
return $module.hasClass(className.vertical);
525573
},
526574
smooth: function () {
527-
return settings.smooth || $module.hasClass(settings.className.smooth);
575+
return settings.smooth || $module.hasClass(className.smooth);
528576
},
529577
},
530578

531579
get: {
580+
currentRangeDiff: function (value) {
581+
var currentRangeDiff;
582+
if ($currThumb.hasClass('second')) {
583+
currentRangeDiff = module.thumbVal < value
584+
? value - module.thumbVal
585+
: module.thumbVal - value;
586+
} else {
587+
currentRangeDiff = module.secondThumbVal > value
588+
? module.secondThumbVal - value
589+
: value - module.secondThumbVal;
590+
}
591+
592+
return currentRangeDiff;
593+
},
594+
edgeValue: function (value, edgeValue) {
595+
if ($currThumb.hasClass('second')) {
596+
value = module.thumbVal < value
597+
? module.thumbVal + edgeValue
598+
: module.thumbVal - edgeValue;
599+
} else {
600+
value = module.secondThumbVal < value
601+
? module.secondThumbVal + edgeValue
602+
: module.secondThumbVal - edgeValue;
603+
}
604+
605+
return value;
606+
},
532607
trackOffset: function () {
533608
if (module.is.vertical()) {
534609
return $track.offset().top;
@@ -732,13 +807,10 @@
732807
return thumbDelta <= secondThumbDelta ? thumbPos : secondThumbPos;
733808
},
734809
thumbPos: function ($element) {
735-
var
736-
pos = module.is.vertical()
737-
? (module.is.reversed() ? $element.css('bottom') : $element.css('top'))
738-
: (module.is.reversed() ? $element.css('right') : $element.css('left'))
810+
return module.is.vertical()
811+
? (module.is.reversed() ? $element.css('bottom') : $element.css('top'))
812+
: (module.is.reversed() ? $element.css('right') : $element.css('left'))
739813
;
740-
741-
return pos;
742814
},
743815
positionFromValue: function (val) {
744816
var
@@ -762,6 +834,7 @@
762834
position = Math.round(ratio * trackLength),
763835
adjustedPos = step === 0 ? position : Math.round(position / step) * step
764836
;
837+
module.verbose('Determined position: ' + position + ' from ratio: ' + ratio);
765838

766839
return adjustedPos;
767840
},
@@ -985,12 +1058,12 @@
9851058
}
9861059
if (!$currThumb.hasClass('second')) {
9871060
if (settings.preventCrossover && module.is.range()) {
988-
newValue = Math.min(module.secondThumbVal, newValue);
1061+
newValue = Math.min(module.secondThumbVal - (settings.minRange || 0), newValue);
9891062
}
9901063
module.thumbVal = newValue;
9911064
} else {
9921065
if (settings.preventCrossover && module.is.range()) {
993-
newValue = Math.max(module.thumbVal, newValue);
1066+
newValue = Math.max(module.thumbVal + (settings.minRange || 0), newValue);
9941067
}
9951068
module.secondThumbVal = newValue;
9961069
}
@@ -1009,6 +1082,10 @@
10091082
thumbVal = module.thumbVal || module.get.min(),
10101083
secondThumbVal = module.secondThumbVal || module.get.min()
10111084
;
1085+
if (settings.showThumbTooltip) {
1086+
var precision = module.get.precision();
1087+
$targetThumb.attr('data-tooltip', Math.round(newValue * precision) / precision);
1088+
}
10121089
if (module.is.range()) {
10131090
if (!$targetThumb.hasClass('second')) {
10141091
position = newPos;
@@ -1097,6 +1174,14 @@
10971174
settings: function () {
10981175
if (settings.start !== false) {
10991176
if (module.is.range()) {
1177+
var rangeDiff = settings.end - settings.start;
1178+
if (rangeDiff < 0
1179+
|| (settings.minRange && rangeDiff < settings.minRange)
1180+
|| (settings.maxRange && rangeDiff > settings.maxRange)
1181+
|| (settings.minRange && settings.maxRange && settings.minRange > settings.maxRange)
1182+
) {
1183+
module.error(error.invalidRanges, settings.start, settings.end, settings.minRange, settings.maxRange);
1184+
}
11001185
module.debug('Start position set from settings', settings.start, settings.end);
11011186
module.set.rangeValue(settings.start, settings.end);
11021187
} else {
@@ -1289,6 +1374,7 @@
12891374
error: {
12901375
method: 'The method you called is not defined.',
12911376
notrange: 'This slider is not a range slider',
1377+
invalidRanges: 'Invalid range settings (start/end/minRange/maxRange)',
12921378
},
12931379

12941380
metadata: {
@@ -1301,6 +1387,8 @@
13011387
step: 1,
13021388
start: 0,
13031389
end: 20,
1390+
minRange: false,
1391+
maxRange: false,
13041392
labelType: 'number',
13051393
showLabelTicks: false,
13061394
smooth: false,
@@ -1337,6 +1425,13 @@
13371425
downArrow: 40,
13381426
},
13391427

1428+
restrictedLabels: [],
1429+
showThumbTooltip: false,
1430+
tooltipConfig: {
1431+
position: 'top center',
1432+
variation: 'tiny black',
1433+
},
1434+
13401435
labelTypes: {
13411436
number: 'number',
13421437
letter: 'letter',

0 commit comments

Comments
 (0)