From bccf966c9eaa9e14577d1f8f3aed3e1c13ee8a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9on=20Gersen?= Date: Mon, 6 Feb 2023 21:43:00 +0100 Subject: [PATCH] Add disable/enable methods to disable slider or handles --- CHANGELOG.MD | 3 +++ dist/nouislider.d.ts | 2 ++ dist/nouislider.js | 28 +++++++++++++++++++++ dist/nouislider.min.js | 2 +- dist/nouislider.min.mjs | 2 +- dist/nouislider.mjs | 28 +++++++++++++++++++++ documentation/more.php | 6 +++-- documentation/more/disable-all.js | 7 +++--- documentation/more/disable.js | 17 ++++++------- documentation/reference.php | 10 ++++++++ package-lock.json | 2 +- package.json | 2 +- src/nouislider.ts | 42 ++++++++++++++++++++++++++++--- 13 files changed, 129 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 886f4348..4857938e 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,8 @@ # Changelog +### 15.7.0 (*2023-02-06*) +- Added: `disable` and `enable` methods to disable slider or handles (#1158, #1227); + ### 15.6.1 (*2022-08-12*) - Fixed: (Typescript) type for keys in `range` (#1218); diff --git a/dist/nouislider.d.ts b/dist/nouislider.d.ts index 5a2832cf..118ad813 100644 --- a/dist/nouislider.d.ts +++ b/dist/nouislider.d.ts @@ -134,6 +134,8 @@ export interface API { set: (input: number | string | (number | string)[], fireSetEvent?: boolean, exactInput?: boolean) => void; setHandle: (handleNumber: number, value: number | string, fireSetEvent?: boolean, exactInput?: boolean) => void; reset: (fireSetEvent?: boolean) => void; + disable: (handleNumber?: number) => void; + enable: (handleNumber?: number) => void; options: Options; updateOptions: (optionsToUpdate: UpdatableOptions, fireSetEvent: boolean) => void; target: HTMLElement; diff --git a/dist/nouislider.js b/dist/nouislider.js index 01fc0bc1..1dff19bf 100644 --- a/dist/nouislider.js +++ b/dist/nouislider.js @@ -959,6 +959,7 @@ else if (handleNumber === options.handles - 1) { addClass(handle, options.cssClasses.handleUpper); } + origin.handle = handle; return origin; } // Insert nodes for connect elements @@ -1022,6 +1023,31 @@ var handleOrigin = scope_Handles[handleNumber]; return handleOrigin.hasAttribute("disabled"); } + function disable(handleNumber) { + if (handleNumber !== null && handleNumber !== undefined) { + scope_Handles[handleNumber].setAttribute("disabled", ""); + scope_Handles[handleNumber].handle.removeAttribute("tabindex"); + } + else { + scope_Target.setAttribute("disabled", ""); + scope_Handles.forEach(function (handle) { + handle.handle.removeAttribute("tabindex"); + }); + } + } + function enable(handleNumber) { + if (handleNumber !== null && handleNumber !== undefined) { + scope_Handles[handleNumber].removeAttribute("disabled"); + scope_Handles[handleNumber].handle.setAttribute("tabindex", "0"); + } + else { + scope_Target.removeAttribute("disabled"); + scope_Handles.forEach(function (handle) { + handle.removeAttribute("disabled"); + handle.handle.setAttribute("tabindex", "0"); + }); + } + } function removeTooltips() { if (scope_Tooltips) { removeEvent("update" + INTERNAL_EVENT_NS.tooltips); @@ -2199,6 +2225,8 @@ set: valueSet, setHandle: valueSetHandle, reset: valueReset, + disable: disable, + enable: enable, // Exposed for unit testing, don't use this in your application. __moveHandles: function (upward, proposal, handleNumbers) { moveHandles(upward, proposal, scope_Locations, handleNumbers); diff --git a/dist/nouislider.min.js b/dist/nouislider.min.js index ca2b37b7..d52d86a3 100644 --- a/dist/nouislider.min.js +++ b/dist/nouislider.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).noUiSlider={})}(this,function(ot){"use strict";function n(t){return"object"==typeof t&&"function"==typeof t.to}function st(t){t.parentElement.removeChild(t)}function at(t){return null!=t}function lt(t){t.preventDefault()}function i(t){return"number"==typeof t&&!isNaN(t)&&isFinite(t)}function ut(t,e,r){0=e[r];)r+=1;return r}function r(t,e,r){if(r>=t.slice(-1)[0])return 100;var n=l(r,t),i=t[n-1],o=t[n],t=e[n-1],n=e[n];return t+(r=r,a(o=[i,o],o[0]<0?r+Math.abs(o[0]):r-o[0],0)/s(t,n))}function o(t,e,r,n){if(100===n)return n;var i=l(n,t),o=t[i-1],s=t[i];return r?(s-o)/2this.xPct[n+1];)n++;else t===this.xPct[this.xPct.length-1]&&(n=this.xPct.length-2);r||t!==this.xPct[n+1]||n++;for(var i,o=1,s=(e=null===e?[]:e)[n],a=0,l=0,u=0,c=r?(t-this.xPct[n])/(this.xPct[n+1]-this.xPct[n]):(this.xPct[n+1]-t)/(this.xPct[n+1]-this.xPct[n]);0= 2) required for mode 'count'.");for(var e=t.values-1,r=100/e,n=[];e--;)n[e]=e*r;return n.push(100),U(n,t.stepped)}(d),m={},t=S.xVal[0],e=S.xVal[S.xVal.length-1],g=!1,v=!1,b=0;return(h=h.slice().sort(function(t,e){return t-e}).filter(function(t){return!this[t]&&(this[t]=!0)},{}))[0]!==t&&(h.unshift(t),g=!0),h[h.length-1]!==e&&(h.push(e),v=!0),h.forEach(function(t,e){var r,n,i,o,s,a,l,u,t=t,c=h[e+1],p=d.mode===ot.PipsMode.Steps,f=(f=p?S.xNumSteps[e]:f)||c-t;for(void 0===c&&(c=t),f=Math.max(f,1e-7),r=t;r<=c;r=Number((r+f).toFixed(7))){for(a=(o=(i=S.toStepping(r))-b)/(d.density||1),u=o/(l=Math.round(a)),n=1;n<=l;n+=1)m[(s=b+n*u).toFixed(5)]=[S.fromStepping(s),0];a=-1ot.PipsType.NoValue&&((t=P(a,!1)).className=p(n,f.cssClasses.value),t.setAttribute("data-value",String(r)),t.style[f.style]=e+"%",t.innerHTML=String(s.to(r))))}),a}function L(){n&&(st(n),n=null)}function T(t){L();var e=D(t),r=t.filter,t=t.format||{to:function(t){return String(Math.round(t))}};return n=d.appendChild(O(e,r,t))}function j(){var t=i.getBoundingClientRect(),e="offset"+["Width","Height"][f.ort];return 0===f.ort?t.width||i[e]:t.height||i[e]}function z(n,i,o,s){function e(t){var e,r=function(e,t,r){var n=0===e.type.indexOf("touch"),i=0===e.type.indexOf("mouse"),o=0===e.type.indexOf("pointer"),s=0,a=0;0===e.type.indexOf("MSPointer")&&(o=!0);if("mousedown"===e.type&&!e.buttons&&!e.touches)return!1;if(n){var l=function(t){t=t.target;return t===r||r.contains(t)||e.composed&&e.composedPath().shift()===r};if("touchstart"===e.type){n=Array.prototype.filter.call(e.touches,l);if(1r.stepAfter.startValue&&(i=r.stepAfter.startValue-n),t=n>r.thisStep.startValue?r.thisStep.step:!1!==r.stepBefore.step&&n-r.stepBefore.highestStep,100===e?i=null:0===e&&(t=null);e=S.countStepDecimals();return null!==i&&!1!==i&&(i=Number(i.toFixed(e))),[t=null!==t&&!1!==t?Number(t.toFixed(e)):t,i]}ft(t=d,f.cssClasses.target),0===f.dir?ft(t,f.cssClasses.ltr):ft(t,f.cssClasses.rtl),0===f.ort?ft(t,f.cssClasses.horizontal):ft(t,f.cssClasses.vertical),ft(t,"rtl"===getComputedStyle(t).direction?f.cssClasses.textDirectionRtl:f.cssClasses.textDirectionLtr),i=P(t,f.cssClasses.base),function(t,e){var r=P(e,f.cssClasses.connects);l=[],(a=[]).push(N(r,t[0]));for(var n=0;n=e[r];)r+=1;return r}function r(t,e,r){if(r>=t.slice(-1)[0])return 100;var n=l(r,t),i=t[n-1],o=t[n],t=e[n-1],n=e[n];return t+(r=r,a(o=[i,o],o[0]<0?r+Math.abs(o[0]):r-o[0],0)/s(t,n))}function o(t,e,r,n){if(100===n)return n;var i=l(n,t),o=t[i-1],s=t[i];return r?(s-o)/2this.xPct[n+1];)n++;else t===this.xPct[this.xPct.length-1]&&(n=this.xPct.length-2);r||t!==this.xPct[n+1]||n++;for(var i,o=1,s=(e=null===e?[]:e)[n],a=0,l=0,u=0,c=r?(t-this.xPct[n])/(this.xPct[n+1]-this.xPct[n]):(this.xPct[n+1]-t)/(this.xPct[n+1]-this.xPct[n]);0= 2) required for mode 'count'.");for(var e=t.values-1,r=100/e,n=[];e--;)n[e]=e*r;return n.push(100),U(n,t.stepped)}(d),m={},t=S.xVal[0],e=S.xVal[S.xVal.length-1],g=!1,v=!1,b=0;return(h=h.slice().sort(function(t,e){return t-e}).filter(function(t){return!this[t]&&(this[t]=!0)},{}))[0]!==t&&(h.unshift(t),g=!0),h[h.length-1]!==e&&(h.push(e),v=!0),h.forEach(function(t,e){var r,n,i,o,s,a,l,u,t=t,c=h[e+1],p=d.mode===ot.PipsMode.Steps,f=(f=p?S.xNumSteps[e]:f)||c-t;for(void 0===c&&(c=t),f=Math.max(f,1e-7),r=t;r<=c;r=Number((r+f).toFixed(7))){for(a=(o=(i=S.toStepping(r))-b)/(d.density||1),u=o/(l=Math.round(a)),n=1;n<=l;n+=1)m[(s=b+n*u).toFixed(5)]=[S.fromStepping(s),0];a=-1ot.PipsType.NoValue&&((t=P(a,!1)).className=p(n,f.cssClasses.value),t.setAttribute("data-value",String(r)),t.style[f.style]=e+"%",t.innerHTML=String(s.to(r))))}),a}function L(){n&&(st(n),n=null)}function T(t){L();var e=D(t),r=t.filter,t=t.format||{to:function(t){return String(Math.round(t))}};return n=d.appendChild(O(e,r,t))}function j(){var t=i.getBoundingClientRect(),e="offset"+["Width","Height"][f.ort];return 0===f.ort?t.width||i[e]:t.height||i[e]}function z(n,i,o,s){function e(t){var e,r=function(e,t,r){var n=0===e.type.indexOf("touch"),i=0===e.type.indexOf("mouse"),o=0===e.type.indexOf("pointer"),s=0,a=0;0===e.type.indexOf("MSPointer")&&(o=!0);if("mousedown"===e.type&&!e.buttons&&!e.touches)return!1;if(n){var l=function(t){t=t.target;return t===r||r.contains(t)||e.composed&&e.composedPath().shift()===r};if("touchstart"===e.type){n=Array.prototype.filter.call(e.touches,l);if(1r.stepAfter.startValue&&(i=r.stepAfter.startValue-n),t=n>r.thisStep.startValue?r.thisStep.step:!1!==r.stepBefore.step&&n-r.stepBefore.highestStep,100===e?i=null:0===e&&(t=null);e=S.countStepDecimals();return null!==i&&!1!==i&&(i=Number(i.toFixed(e))),[t=null!==t&&!1!==t?Number(t.toFixed(e)):t,i]}ft(t=d,f.cssClasses.target),0===f.dir?ft(t,f.cssClasses.ltr):ft(t,f.cssClasses.rtl),0===f.ort?ft(t,f.cssClasses.horizontal):ft(t,f.cssClasses.vertical),ft(t,"rtl"===getComputedStyle(t).direction?f.cssClasses.textDirectionRtl:f.cssClasses.textDirectionLtr),i=P(t,f.cssClasses.base),function(t,e){var r=P(e,f.cssClasses.connects);l=[],(a=[]).push(N(r,t[0]));for(var n=0;n=e[r];)r+=1;return r}function toStepping(t,e,r){if(r>=t.slice(-1)[0])return 100;var n=getJ(r,t),i=t[n-1],s=t[n],t=e[n-1],n=e[n];return t+toPercentage([i,s],r)/subRangeRatio(t,n)}function fromStepping(t,e,r){if(100<=r)return t.slice(-1)[0];var n=getJ(r,e),i=t[n-1],s=t[n],t=e[n-1];return isPercentage([i,s],(r-t)*subRangeRatio(t,e[n]))}function getStep(t,e,r,n){if(100===n)return n;var i=getJ(n,t),s=t[i-1],o=t[i];return r?(o-s)/2this.xPct[n+1];)n++;else t===this.xPct[this.xPct.length-1]&&(n=this.xPct.length-2);r||t!==this.xPct[n+1]||n++;for(var i,s=1,o=(e=null===e?[]:e)[n],a=0,l=0,u=0,c=r?(t-this.xPct[n])/(this.xPct[n+1]-this.xPct[n]):(this.xPct[n+1]-t)/(this.xPct[n+1]-this.xPct[n]);0= 2) required for mode 'count'.");for(var e=t.values-1,r=100/e,n=[];e--;)n[e]=e*r;return n.push(100),M(n,t.stepped)}(f),m={},t=b.xVal[0],e=b.xVal[b.xVal.length-1],g=!1,v=!1,S=0;return(h=unique(h.slice().sort(function(t,e){return t-e})))[0]!==t&&(h.unshift(t),g=!0),h[h.length-1]!==e&&(h.push(e),v=!0),h.forEach(function(t,e){var r,n,i,s,o,a,l,u,t=t,c=h[e+1],p=f.mode===PipsMode.Steps,d=(d=p?b.xNumSteps[e]:d)||c-t;for(void 0===c&&(c=t),d=Math.max(d,1e-7),r=t;r<=c;r=Number((r+d).toFixed(7))){for(a=(s=(i=b.toStepping(r))-S)/(f.density||1),u=s/(l=Math.round(a)),n=1;n<=l;n+=1)m[(o=S+n*u).toFixed(5)]=[b.fromStepping(o),0];a=-1PipsType.NoValue&&((t=N(a,!1)).className=p(n,d.cssClasses.value),t.setAttribute("data-value",String(r)),t.style[d.style]=e+"%",t.innerHTML=String(o.to(r))))}),a}function U(){n&&(removeElement(n),n=null)}function L(t){U();var e=D(t),r=t.filter,t=t.format||{to:function(t){return String(Math.round(t))}};return n=f.appendChild(T(e,r,t))}function O(){var t=r.getBoundingClientRect(),e="offset"+["Width","Height"][d.ort];return 0===d.ort?t.width||r[e]:t.height||r[e]}function F(e,r,n,i){function s(t){return!!(t=function(e,t,r){var n=0===e.type.indexOf("touch"),i=0===e.type.indexOf("mouse"),s=0===e.type.indexOf("pointer"),o=0,a=0;0===e.type.indexOf("MSPointer")&&(s=!0);if("mousedown"===e.type&&!e.buttons&&!e.touches)return!1;if(n){var l=function(t){t=t.target;return t===r||r.contains(t)||e.composed&&e.composedPath().shift()===r};if("touchstart"===e.type){n=Array.prototype.filter.call(e.touches,l);if(1r.stepAfter.startValue&&(i=r.stepAfter.startValue-n),t=n>r.thisStep.startValue?r.thisStep.step:!1!==r.stepBefore.step&&n-r.stepBefore.highestStep,100===e?i=null:0===e&&(t=null);e=b.countStepDecimals();return null!==i&&!1!==i&&(i=Number(i.toFixed(e))),[t=null!==t&&!1!==t?Number(t.toFixed(e)):t,i]}addClass(t=f,d.cssClasses.target),0===d.dir?addClass(t,d.cssClasses.ltr):addClass(t,d.cssClasses.rtl),0===d.ort?addClass(t,d.cssClasses.horizontal):addClass(t,d.cssClasses.vertical),addClass(t,"rtl"===getComputedStyle(t).direction?d.cssClasses.textDirectionRtl:d.cssClasses.textDirectionLtr),r=N(t,d.cssClasses.base),function(t,e){var r=N(e,d.cssClasses.connects);l=[],(a=[]).push(w(r,t[0]));for(var n=0;n=e[r];)r+=1;return r}function toStepping(t,e,r){if(r>=t.slice(-1)[0])return 100;var n=getJ(r,t),i=t[n-1],s=t[n],t=e[n-1],n=e[n];return t+toPercentage([i,s],r)/subRangeRatio(t,n)}function fromStepping(t,e,r){if(100<=r)return t.slice(-1)[0];var n=getJ(r,e),i=t[n-1],s=t[n],t=e[n-1];return isPercentage([i,s],(r-t)*subRangeRatio(t,e[n]))}function getStep(t,e,r,n){if(100===n)return n;var i=getJ(n,t),s=t[i-1],o=t[i];return r?(o-s)/2this.xPct[n+1];)n++;else t===this.xPct[this.xPct.length-1]&&(n=this.xPct.length-2);r||t!==this.xPct[n+1]||n++;for(var i,s=1,o=(e=null===e?[]:e)[n],a=0,l=0,u=0,c=r?(t-this.xPct[n])/(this.xPct[n+1]-this.xPct[n]):(this.xPct[n+1]-t)/(this.xPct[n+1]-this.xPct[n]);0= 2) required for mode 'count'.");for(var e=t.values-1,r=100/e,n=[];e--;)n[e]=e*r;return n.push(100),M(n,t.stepped)}(f),m={},t=S.xVal[0],e=S.xVal[S.xVal.length-1],g=!1,v=!1,b=0;return(h=unique(h.slice().sort(function(t,e){return t-e})))[0]!==t&&(h.unshift(t),g=!0),h[h.length-1]!==e&&(h.push(e),v=!0),h.forEach(function(t,e){var r,n,i,s,o,a,l,u,t=t,c=h[e+1],p=f.mode===PipsMode.Steps,d=(d=p?S.xNumSteps[e]:d)||c-t;for(void 0===c&&(c=t),d=Math.max(d,1e-7),r=t;r<=c;r=Number((r+d).toFixed(7))){for(a=(s=(i=S.toStepping(r))-b)/(f.density||1),u=s/(l=Math.round(a)),n=1;n<=l;n+=1)m[(o=b+n*u).toFixed(5)]=[S.fromStepping(o),0];a=-1PipsType.NoValue&&((t=N(a,!1)).className=p(n,d.cssClasses.value),t.setAttribute("data-value",String(r)),t.style[d.style]=e+"%",t.innerHTML=String(o.to(r))))}),a}function U(){n&&(removeElement(n),n=null)}function L(t){U();var e=D(t),r=t.filter,t=t.format||{to:function(t){return String(Math.round(t))}};return n=f.appendChild(T(e,r,t))}function O(){var t=r.getBoundingClientRect(),e="offset"+["Width","Height"][d.ort];return 0===d.ort?t.width||r[e]:t.height||r[e]}function F(e,r,n,i){function s(t){return!!(t=function(e,t,r){var n=0===e.type.indexOf("touch"),i=0===e.type.indexOf("mouse"),s=0===e.type.indexOf("pointer"),o=0,a=0;0===e.type.indexOf("MSPointer")&&(s=!0);if("mousedown"===e.type&&!e.buttons&&!e.touches)return!1;if(n){var l=function(t){t=t.target;return t===r||r.contains(t)||e.composed&&e.composedPath().shift()===r};if("touchstart"===e.type){n=Array.prototype.filter.call(e.touches,l);if(1r.stepAfter.startValue&&(i=r.stepAfter.startValue-n),t=n>r.thisStep.startValue?r.thisStep.step:!1!==r.stepBefore.step&&n-r.stepBefore.highestStep,100===e?i=null:0===e&&(t=null);e=S.countStepDecimals();return null!==i&&!1!==i&&(i=Number(i.toFixed(e))),[t=null!==t&&!1!==t?Number(t.toFixed(e)):t,i]}addClass(t=f,d.cssClasses.target),0===d.dir?addClass(t,d.cssClasses.ltr):addClass(t,d.cssClasses.rtl),0===d.ort?addClass(t,d.cssClasses.horizontal):addClass(t,d.cssClasses.vertical),addClass(t,"rtl"===getComputedStyle(t).direction?d.cssClasses.textDirectionRtl:d.cssClasses.textDirectionLtr),r=N(t,d.cssClasses.base),function(t,e){var r=N(e,d.cssClasses.connects);l=[],(a=[]).push(w(r,t[0]));for(var n=0;n -

Disabling a slider is identical to disabling a checkbox or textarea; add the disabled attribute.

+

A slider can be disabled by calling the disable method in the API.

A disabled slider can't be changed by user interaction (sliding, clicking or touching), but its value can still be changed using the .set() method.

@@ -28,7 +28,9 @@

The slider below is disabled when the checkbox is checked, and re-enabled when it is unchecked.

-

Individual handles can be disabled by adding a disabled attribute to a .noUi-origin element.

+

Individual handles can be disabled by calling the disable with a zero-index handle number. Disabling an individual handle will also prevent it from having focus.

+ +

The slider or handles can re re-enabled using the enable method.

diff --git a/documentation/more/disable-all.js b/documentation/more/disable-all.js index 0281e0f4..6d72b70a 100644 --- a/documentation/more/disable-all.js +++ b/documentation/more/disable-all.js @@ -1,9 +1,8 @@ // To disable -slider.setAttribute('disabled', true); +slider.noUiSlider.disable(); // To re-enable -slider.removeAttribute('disabled'); +slider.noUiSlider.enable(); // To disable one handle -var origins = slider.querySelectorAll('.noUi-origin'); -origins[0].setAttribute('disabled', true); +slider.noUiSlider.disable(1); diff --git a/documentation/more/disable.js b/documentation/more/disable.js index 2d28f352..33a280ce 100644 --- a/documentation/more/disable.js +++ b/documentation/more/disable.js @@ -2,17 +2,16 @@ var slider1 = document.getElementById('disable1'), slider2 = document.getElementById('disable2'), checkbox1 = document.getElementById('checkbox1'), checkbox2 = document.getElementById('checkbox2'), - checkbox3 = document.getElementById('checkbox3'), - origins = slider2.querySelectorAll('.noUi-origin'); + checkbox3 = document.getElementById('checkbox3'); -function toggle(element) { +function toggle(checkbox, slider, handleNumber) { // If the checkbox is checked, disabled the slider. // Otherwise, re-enable it. - if (this.checked) { - element.setAttribute('disabled', true); + if (checkbox.checked) { + slider.noUiSlider.disable(handleNumber); } else { - element.removeAttribute('disabled'); + slider.noUiSlider.enable(handleNumber); } } @@ -34,13 +33,13 @@ noUiSlider.create(slider2, { }); checkbox1.addEventListener('click', function () { - toggle.call(this, slider1); + toggle(this, slider1); }); checkbox2.addEventListener('click', function () { - toggle.call(this, origins[0]); + toggle(this, slider2, 0); }); checkbox3.addEventListener('click', function () { - toggle.call(this, origins[1]); + toggle(this, slider2, 1); }); diff --git a/documentation/reference.php b/documentation/reference.php index 39c1424b..da8faa69 100644 --- a/documentation/reference.php +++ b/documentation/reference.php @@ -231,6 +231,16 @@ slider.noUiSlider.reset() [none] + + disable + slider.noUiSlider.disable() + [none], "number" + + + enable + slider.noUiSlider.enable() + [none], "number" + updateOptions slider.noUiSlider.updateOptions(...) diff --git a/package-lock.json b/package-lock.json index 23098007..d074ad36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "nouislider", - "version": "15.6.1", + "version": "15.7.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 4cddf453..0c97edfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nouislider", - "version": "15.6.1", + "version": "15.7.0", "main": "dist/nouislider.js", "style": "dist/nouislider.min.css", "types": "dist/nouislider.d.ts", diff --git a/src/nouislider.ts b/src/nouislider.ts index 620a5fe2..3df8bccc 100644 --- a/src/nouislider.ts +++ b/src/nouislider.ts @@ -70,6 +70,7 @@ type SubRange = number | WrappedSubRange; interface Range { min: SubRange; max: SubRange; + [key: `${number}%`]: SubRange; } @@ -204,6 +205,8 @@ export interface API { set: (input: number | string | (number | string)[], fireSetEvent?: boolean, exactInput?: boolean) => void; setHandle: (handleNumber: number, value: number | string, fireSetEvent?: boolean, exactInput?: boolean) => void; reset: (fireSetEvent?: boolean) => void; + disable: (handleNumber?: number) => void; + enable: (handleNumber?: number) => void; options: Options; updateOptions: (optionsToUpdate: UpdatableOptions, fireSetEvent: boolean) => void; target: HTMLElement; @@ -218,6 +221,10 @@ interface TargetElement extends HTMLElement { noUiSlider?: API; } +interface Origin extends HTMLElement { + handle: HTMLElement; +} + interface CSSStyleDeclarationIE10 extends CSSStyleDeclaration { msTransform?: string; } @@ -1357,7 +1364,7 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O // Slider DOM Nodes const scope_Target = target; let scope_Base: HTMLElement; - let scope_Handles: HTMLElement[]; + let scope_Handles: Origin[]; let scope_Connects: (HTMLElement | false)[]; let scope_Pips: HTMLElement | null; let scope_Tooltips: (HTMLElement | false)[] | null; @@ -1393,7 +1400,7 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O } // Append a origin to the base - function addOrigin(base: HTMLElement, handleNumber: number): HTMLElement { + function addOrigin(base: HTMLElement, handleNumber: number): Origin { const origin = addNodeTo(base, options.cssClasses.origin); const handle = addNodeTo(origin, options.cssClasses.handle); @@ -1426,7 +1433,9 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O addClass(handle, options.cssClasses.handleUpper); } - return origin; + (origin as Origin).handle = handle; + + return origin as Origin; } // Insert nodes for connect elements @@ -1504,6 +1513,31 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O return handleOrigin.hasAttribute("disabled"); } + function disable(handleNumber?: number): void { + if (handleNumber !== null && handleNumber !== undefined) { + scope_Handles[handleNumber].setAttribute("disabled", ""); + scope_Handles[handleNumber].handle.removeAttribute("tabindex"); + } else { + scope_Target.setAttribute("disabled", ""); + scope_Handles.forEach(function (handle) { + handle.handle.removeAttribute("tabindex"); + }); + } + } + + function enable(handleNumber?: number): void { + if (handleNumber !== null && handleNumber !== undefined) { + scope_Handles[handleNumber].removeAttribute("disabled"); + scope_Handles[handleNumber].handle.setAttribute("tabindex", "0"); + } else { + scope_Target.removeAttribute("disabled"); + scope_Handles.forEach(function (handle) { + handle.removeAttribute("disabled"); + handle.handle.setAttribute("tabindex", "0"); + }); + } + } + function removeTooltips(): void { if (scope_Tooltips) { removeEvent("update" + INTERNAL_EVENT_NS.tooltips); @@ -3013,6 +3047,8 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O set: valueSet, setHandle: valueSetHandle, reset: valueReset, + disable: disable, + enable: enable, // Exposed for unit testing, don't use this in your application. __moveHandles: function (upward: boolean, proposal: number, handleNumbers: number[]) { moveHandles(upward, proposal, scope_Locations, handleNumbers);