Skip to content

Commit 21f599b

Browse files
committed
add ability to disable slider with "disabled" property
related to #20
1 parent 62194cc commit 21f599b

File tree

3 files changed

+113
-81
lines changed

3 files changed

+113
-81
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ prop | type | default | description
103103
**rest** | `Boolean`/`String` | `false` | Whether to show a pip or label for the all other values. Use `rest='label'` to show a label value
104104
**prefix** | `String` | `""` | A string to prefix to all displayed values
105105
**suffix** | `String` | `""` | A string to suffix to all displayed values
106+
**disabled** | `Boolean` | `false` | Determine if the slider is disabled, or enabled _(only disables interactions, and events)_
106107
**formatter** | `Function` | `(v) => v` | A function to re-format values before they are displayed
107108
**handleFormatter** | `Function` | `formatter` | A function to re-format values on the handle/float before they are displayed. Defaults to the same function given to the `formatter` property
108109
**springValues** | `Object` | `{ stiffness: 0.15, damping: 0.4 }` | Svelte spring physics object to change the behaviour of the handle when moving

src/RangeSlider.svelte

Lines changed: 96 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
export let vertical = false;
1414
export let float = false;
1515
export let hover = true;
16+
export let disabled = false;
1617
1718
// range pips / values props
1819
export let pips = false;
@@ -359,8 +360,10 @@
359360
* @param {event} e the event from browser
360361
**/
361362
function sliderFocusHandle(e) {
362-
activeHandle = index(e.target);
363-
focus = true;
363+
if ( !disabled ) {
364+
activeHandle = index(e.target);
365+
focus = true;
366+
}
364367
}
365368
366369
/**
@@ -369,37 +372,39 @@
369372
* @param {event} e the event from browser
370373
**/
371374
function sliderKeydown(e) {
372-
const handle = index(e.target);
373-
let jump = e.ctrlKey || e.metaKey || e.shiftKey ? step * 10 : step;
374-
let prevent = false;
375-
376-
switch (e.key) {
377-
case "PageDown":
378-
jump *= 10;
379-
case "ArrowRight":
380-
case "ArrowUp":
381-
moveHandle(handle, values[handle] + jump);
382-
prevent = true;
383-
break;
384-
case "PageUp":
385-
jump *= 10;
386-
case "ArrowLeft":
387-
case "ArrowDown":
388-
moveHandle(handle, values[handle] - jump);
389-
prevent = true;
390-
break;
391-
case "Home":
392-
moveHandle(handle, min);
393-
prevent = true;
394-
break;
395-
case "End":
396-
moveHandle(handle, max);
397-
prevent = true;
398-
break;
399-
}
400-
if (prevent) {
401-
e.preventDefault();
402-
e.stopPropagation();
375+
if ( !disabled ) {
376+
const handle = index(e.target);
377+
let jump = e.ctrlKey || e.metaKey || e.shiftKey ? step * 10 : step;
378+
let prevent = false;
379+
380+
switch (e.key) {
381+
case "PageDown":
382+
jump *= 10;
383+
case "ArrowRight":
384+
case "ArrowUp":
385+
moveHandle(handle, values[handle] + jump);
386+
prevent = true;
387+
break;
388+
case "PageUp":
389+
jump *= 10;
390+
case "ArrowLeft":
391+
case "ArrowDown":
392+
moveHandle(handle, values[handle] - jump);
393+
prevent = true;
394+
break;
395+
case "Home":
396+
moveHandle(handle, min);
397+
prevent = true;
398+
break;
399+
case "End":
400+
moveHandle(handle, max);
401+
prevent = true;
402+
break;
403+
}
404+
if (prevent) {
405+
e.preventDefault();
406+
e.stopPropagation();
407+
}
403408
}
404409
}
405410
@@ -409,21 +414,23 @@
409414
* @param {event} e the event from browser
410415
**/
411416
function sliderInteractStart(e) {
412-
const clientPos = normalisedClient(e);
413-
// set the closest handle as active
414-
focus = true;
415-
handleActivated = true;
416-
handlePressed = true;
417-
activeHandle = getClosestHandle(clientPos);
418-
419-
// fire the start event
420-
startValue = previousValue = alignValueToStep(values[activeHandle]);
421-
eStart();
422-
423-
// for touch devices we want the handle to instantly
424-
// move to the position touched for more responsive feeling
425-
if (e.type === "touchstart") {
426-
handleInteract(clientPos);
417+
if ( !disabled ) {
418+
const clientPos = normalisedClient(e);
419+
// set the closest handle as active
420+
focus = true;
421+
handleActivated = true;
422+
handlePressed = true;
423+
activeHandle = getClosestHandle(clientPos);
424+
425+
// fire the start event
426+
startValue = previousValue = alignValueToStep(values[activeHandle]);
427+
eStart();
428+
429+
// for touch devices we want the handle to instantly
430+
// move to the position touched for more responsive feeling
431+
if (e.type === "touchstart") {
432+
handleInteract(clientPos);
433+
}
427434
}
428435
}
429436
@@ -458,8 +465,10 @@
458465
* @param {event} e the event from browser
459466
**/
460467
function bodyInteract(e) {
461-
if (handleActivated) {
462-
handleInteract(normalisedClient(e));
468+
if ( !disabled ) {
469+
if (handleActivated) {
470+
handleInteract(normalisedClient(e));
471+
}
463472
}
464473
}
465474
@@ -470,20 +479,22 @@
470479
* @param {event} e the event from browser
471480
**/
472481
function bodyMouseUp(e) {
473-
const el = e.target;
474-
// this only works if a handle is active, which can
475-
// only happen if there was sliderInteractStart triggered
476-
// on the slider, already
477-
if (handleActivated) {
478-
if (el === slider || slider.contains(el)) {
479-
focus = true;
480-
if (!targetIsHandle(el)) {
481-
handleInteract(normalisedClient(e));
482+
if ( !disabled ) {
483+
const el = e.target;
484+
// this only works if a handle is active, which can
485+
// only happen if there was sliderInteractStart triggered
486+
// on the slider, already
487+
if (handleActivated) {
488+
if (el === slider || slider.contains(el)) {
489+
focus = true;
490+
if (!targetIsHandle(el)) {
491+
handleInteract(normalisedClient(e));
492+
}
482493
}
494+
// fire the stop event for mouse device
495+
// when the body is triggered with an active handle
496+
eStop();
483497
}
484-
// fire the stop event for mouse device
485-
// when the body is triggered with an active handle
486-
eStop();
487498
}
488499
handleActivated = false;
489500
handlePressed = false;
@@ -500,21 +511,23 @@
500511
}
501512
502513
function bodyKeyDown(e) {
503-
if (e.target === slider || slider.contains(e.target)) {
504-
keyboardActive = true;
514+
if ( !disabled ) {
515+
if (e.target === slider || slider.contains(e.target)) {
516+
keyboardActive = true;
517+
}
505518
}
506519
}
507520
508521
function eStart() {
509-
dispatch("start", {
522+
!disabled && dispatch("start", {
510523
activeHandle,
511524
value: startValue,
512525
values: values.map((v) => alignValueToStep(v)),
513526
});
514527
}
515528
516529
function eStop() {
517-
dispatch("stop", {
530+
!disabled && dispatch("stop", {
518531
activeHandle,
519532
startValue: startValue,
520533
value: values[activeHandle],
@@ -523,7 +536,7 @@
523536
}
524537
525538
function eChange() {
526-
dispatch("change", {
539+
!disabled && dispatch("change", {
527540
activeHandle,
528541
startValue: startValue,
529542
previousValue:
@@ -552,6 +565,7 @@
552565
border-radius: 100px;
553566
height: 0.5em;
554567
margin: 1em;
568+
transition: opacity 0.2s ease;
555569
}
556570
:global(.rangeSlider, .rangeSlider *) {
557571
user-select: none;
@@ -702,13 +716,21 @@
702716
background-color: #4a40d4;
703717
background-color: var(--float);
704718
}
719+
:global(.rangeSlider.disabled ) {
720+
opacity: 0.5;
721+
}
722+
:global(.rangeSlider.disabled .rangeNub) {
723+
background-color: #d7dada;
724+
background-color: var(--slider);
725+
}
705726
</style>
706727

707728
<div
708729
{id}
709730
bind:this={slider}
710731
class="rangeSlider"
711732
class:range
733+
class:disabled
712734
class:vertical
713735
class:focus
714736
class:min={range === 'min'}
@@ -723,9 +745,8 @@
723745
{#each values as value, index}
724746
<span
725747
role="slider"
726-
tabindex="0"
727748
class="rangeHandle"
728-
class:hoverable={hover}
749+
class:hoverable={hover && !disabled}
729750
class:active={focus && activeHandle === index}
730751
class:press={handlePressed && activeHandle === index}
731752
on:blur={sliderBlurHandle}
@@ -736,7 +757,11 @@
736757
aria-valuemax={range === true && index === 0 ? values[1] : max}
737758
aria-valuenow={value}
738759
aria-valuetext="{prefix}{handleFormatter(value)}{suffix}"
739-
aria-orientation={vertical ? 'vertical' : 'horizontal'}>
760+
aria-orientation={vertical ? 'vertical' : 'horizontal'}
761+
aria-disabled={disabled}
762+
{disabled}
763+
tabindex="{ disabled ? -1 : 0 }"
764+
>
740765
<span class="rangeNub" />
741766
{#if float}
742767
<span class="rangeFloat">{prefix}{handleFormatter(value)}{suffix}</span>
@@ -766,6 +791,7 @@
766791
{suffix}
767792
{formatter}
768793
{focus}
794+
{disabled}
769795
{percentOf} />
770796
{/if}
771797
</div>

test/src/App.svelte

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
let zero = [2,10];
2727
let zeromin = 0;
2828
let zeromax = 0;
29+
30+
let disabled = false;
2931
3032
</script>
3133

@@ -55,29 +57,30 @@
5557

5658
<div class="content" style="--range-handle-focus: {color}; --range-handle: {lightColor}">
5759

58-
<RangeSlider vertical range values={[10,30]} pips all="label" />
60+
<RangeSlider vertical range values={[10,30]} pips all="label" {disabled} />
5961
<RangeSlider vertical range="min" values={[10]} pips all />
6062
<RangeSlider vertical range="max" values={[30]} pips />
6163

6264
<br>
6365
<RangeSlider id="test-id" springValues={{ stiffness: 0.03, damping: 0.08 }} />
6466
<br>
65-
66-
<RangeSlider bind:values
67+
68+
<RangeSlider bind:values {disabled}
6769
on:start={(e) => { console.log("start",e.detail)}}
6870
on:stop={(e) => { console.log("end",e.detail)}}
6971
on:change={(e) => { console.log("change",e.detail)}}
7072
/>
7173
<hr>
72-
{values}<br>
73-
<input type="number" bind:value={values[0]} />
74-
<input type="number" bind:value={values[1]} />
75-
<input type="number" bind:value={values[2]} />
76-
<input type="number" bind:value={values[3]} />
74+
{values}
75+
<br>
76+
<input type="number" bind:value={values[0]} />
77+
<input type="number" bind:value={values[1]} />
78+
<input type="number" bind:value={values[2]} />
79+
<input type="number" bind:value={values[3]} />
7780
<hr>
7881
<RangeSlider float />
7982
<RangeSlider float pips all="label" />
80-
<RangeSlider float pips first="label" last="label" />
83+
<RangeSlider float pips first="label" last="label" {disabled} />
8184
<RangeSlider float pips first="label" last="label" rest="label"
8285
on:start={(e) => { console.log("start",e.detail)}}
8386
on:stop={(e) => { console.log("stop",e.detail)}}
@@ -117,9 +120,11 @@
117120

118121
<br><br>
119122

120-
<RangeSlider bind:values={zero} bind:min={zeromin} bind:max={zeromax} range float pips all="label" step={1} pipstep={5} />
121-
<br><button on:click={()=>{ zeromin = 1; zeromax = 30; zero = 10; }}>increase min/max</button> - {zero}
123+
<RangeSlider bind:values={zero} min={zeromin} max={zeromax} range float pips all="label" step={1} pipstep={5} />
124+
<br><button on:click={()=>{ zeromin = 1; zeromax = 30; zero = 10; }}>increase min/max</button> - {zero}
122125

126+
<RangeSlider bind:values float pips all="label" {disabled} />
127+
<button on:click={()=>{disabled=!disabled}}>toggle disabled</button>
123128

124129
</div>
125130

0 commit comments

Comments
 (0)