From 3406bc1075f969626ce6e99d6ad381054b999a52 Mon Sep 17 00:00:00 2001 From: lgersen Date: Mon, 10 Jun 2024 20:55:12 +0200 Subject: [PATCH] Bypass full updateOptions, fix eslint, check for two handles --- documentation/behaviour-option.php | 6 +- .../behaviour-option/invert-connects-link.js | 2 +- .../behaviour-option/invert-connects.js | 2 +- documentation/more.php | 2 +- src/nouislider.ts | 71 +++++++++++-------- 5 files changed, 49 insertions(+), 34 deletions(-) diff --git a/documentation/behaviour-option.php b/documentation/behaviour-option.php index c9df959..e242046 100644 --- a/documentation/behaviour-option.php +++ b/documentation/behaviour-option.php @@ -10,9 +10,9 @@
-

noUiSlider offers several ways to handle user interaction. The range can be made draggable, or handles can move to tapped positions. All these effects are optional, and can be enable by adding their keyword to the behaviour option.

+

noUiSlider offers several ways to handle user interaction. The range can be made draggable, or handles can move to tapped positions. All these effects are optional, and can be enabled by adding their keyword to the behaviour option.

-

This option accepts a "-" separated list of "drag", "drag-all", "tap", "fixed", "snap", "unconstrained" or "none".

+

This option accepts a "-" separated list of "drag", "drag-all", "tap", "fixed", "snap", "unconstrained", "invert-connects" or "none".

@@ -273,7 +273,7 @@

With this option set, connects invert when handles pass each other.

-

Requires the unconstrained behaviour and the connect option.

+

Requires the unconstrained behaviour and the connect option. This option is only applicable for sliders with two handles.

diff --git a/documentation/behaviour-option/invert-connects-link.js b/documentation/behaviour-option/invert-connects-link.js index 26cd2dd..f9453f7 100644 --- a/documentation/behaviour-option/invert-connects-link.js +++ b/documentation/behaviour-option/invert-connects-link.js @@ -6,4 +6,4 @@ invertConnectsSlider.noUiSlider.on('update', function (values) { return [mins / 60 ^ 0, mins % 60].map(pad).join(':'); }; invertConnectsValues.innerHTML = values.map(minToHHMM).join(' - '); -}); \ No newline at end of file +}); diff --git a/documentation/behaviour-option/invert-connects.js b/documentation/behaviour-option/invert-connects.js index 236687b..52d2a2a 100644 --- a/documentation/behaviour-option/invert-connects.js +++ b/documentation/behaviour-option/invert-connects.js @@ -9,4 +9,4 @@ noUiSlider.create(invertConnectsSlider, { 'min': 0, 'max': 24*60 } -}); \ No newline at end of file +}); diff --git a/documentation/more.php b/documentation/more.php index 1cea5eb..b15d106 100644 --- a/documentation/more.php +++ b/documentation/more.php @@ -75,7 +75,7 @@
-

noUiSlider has an update method that can change the 'margin', 'padding', 'limit', 'step', 'range', 'pips', 'tooltips', 'animate' and 'snap' options.

+

noUiSlider has an update method that can change the 'margin', 'padding', 'limit', 'step', 'range', 'pips', 'tooltips', 'connect', 'animate' and 'snap' options.

All other options require changes to the slider's HTML or event bindings.

diff --git a/src/nouislider.ts b/src/nouislider.ts index 5978522..e7ee831 100644 --- a/src/nouislider.ts +++ b/src/nouislider.ts @@ -1150,6 +1150,10 @@ function testBehaviour(parsed: ParsedOptions, entry: unknown): void { testMargin(parsed, parsed.start[1] - parsed.start[0]); } + if (invertConnects && parsed.handles !== 2) { + throw new Error("noUiSlider: 'invert-connects' behaviour must be used with 2 handles"); + } + if (unconstrained && (parsed.margin || parsed.limit)) { throw new Error("noUiSlider: 'unconstrained' behaviour cannot be used with margin or limit"); } @@ -1383,7 +1387,7 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O const scope_HandleNumbers: number[] = []; let scope_ActiveHandlesCount = 0; const scope_Events: { [key: string]: EventCallback[] } = {}; - let scope_ConnectsInverted: boolean = false; + let scope_ConnectsInverted = false; // Document Nodes const scope_Document = target.ownerDocument; @@ -2671,23 +2675,27 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O (scope_Handles[handleNumber].style as CSSStyleDeclarationIE10)[options.transformRule] = translateRule; - if( - options.events.invertConnects && - // sanity check for at least 2 handles - scope_Locations.length > 1 && + // sanity check for at least 2 handles (e.g. during setup) + if (options.events.invertConnects && scope_Locations.length > 1) { // check if handles passed each other, but don't match the ConnectsInverted state - scope_ConnectsInverted !== !scope_Locations.every( - (position: number, index: number, locations: number[]): boolean => + const handlesAreInOrder = scope_Locations.every( + (position: number, index: number, locations: number[]): boolean => index === 0 || position >= locations[index - 1] - )) { - // when invertConnects is set, automatically invert connects when handles pass each other + ); + + if (scope_ConnectsInverted !== !handlesAreInOrder) { + // invert connects when handles pass each other invertConnects(); + + // invertConnects already updates all connect elements + return; } + } updateConnect(handleNumber); updateConnect(handleNumber + 1); - - if(scope_ConnectsInverted) { + + if (scope_ConnectsInverted) { // When connects are inverted, we also have to update adjacent connects updateConnect(handleNumber - 1); updateConnect(handleNumber + 2); @@ -2744,9 +2752,10 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O } // Create a copy of locations, so we can sort them for the local scope logic - let locations = scope_Locations.slice(); + const locations = scope_Locations.slice(); + if (scope_ConnectsInverted) { - locations.sort(function(a, b) { + locations.sort(function (a, b) { return a - b; }); } @@ -3048,30 +3057,36 @@ function scope(target: TargetElement, options: ParsedOptions, originalOptions: O // Update connects only if it was set if (optionsToUpdate.connect) { - // IE supported way of removing children including event handlers - while (scope_ConnectBase.firstChild) { - scope_ConnectBase.removeChild(scope_ConnectBase.firstChild); - } + updateConnectOption(); + } + } - // Adding new connects according to the new connect options - for (let i = 0; i <= options.handles; i++) { - scope_Connects[i] = addConnect(scope_ConnectBase, options.connect[i]); - updateConnect(i); - } + function updateConnectOption() { + // IE supported way of removing children including event handlers + while (scope_ConnectBase.firstChild) { + scope_ConnectBase.removeChild(scope_ConnectBase.firstChild); + } - // readding drag events for the new connect elements - // to ignore the other events we have to negate the 'if (!behaviour.fixed)' check - bindSliderEvents({ drag: options.events.drag, fixed: true } as Behaviour); + // Adding new connects according to the new connect options + for (let i = 0; i <= options.handles; i++) { + scope_Connects[i] = addConnect(scope_ConnectBase, options.connect[i]); + updateConnect(i); } + + // re-adding drag events for the new connect elements + // to ignore the other events we have to negate the 'if (!behaviour.fixed)' check + bindSliderEvents({ drag: options.events.drag, fixed: true } as Behaviour); } // Invert options for connect handles function invertConnects() { scope_ConnectsInverted = !scope_ConnectsInverted; - updateOptions({ + testConnect( + options, // inverse the connect boolean array - connect: options.connect.map((b: boolean) => !b) - }, false); // don't fire the set event + options.connect.map((b: boolean) => !b) + ); + updateConnectOption(); } // Initialization steps