Skip to content

Commit

Permalink
noUiSlider 14.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
leongersen committed May 11, 2020
1 parent ad6ccad commit a5bb92a
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 36 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

### 14.5.0 (*2020-05-20*)
- Added: Support for `margin`, `padding` and `limit` on non-linear sliders (#911, #1030, #1031, #1071);

### 14.4.0 (*2020-05-06*)
- Added: `getOrigins` and `getTooltips` methods;
- Added: Default styling to support merging overlapping tooltips (#1032);
Expand Down
2 changes: 1 addition & 1 deletion distribute/nouislider.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! nouislider - 14.4.0 - 5/6/2020 */
/*! nouislider - 14.5.0 - 5/11/2020 */
/* Functional styling;
* These styles are required for noUiSlider to function.
* You don't need to change these rules to apply your design.
Expand Down
164 changes: 133 additions & 31 deletions distribute/nouislider.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! nouislider - 14.4.0 - 5/6/2020 */
/*! nouislider - 14.5.0 - 5/11/2020 */
(function(factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
Expand All @@ -13,7 +13,7 @@
})(function() {
"use strict";

var VERSION = "14.4.0";
var VERSION = "14.5.0";

//region Helper Methods

Expand Down Expand Up @@ -206,13 +206,13 @@
}

// (percentage) How many percent is this value of this range?
function fromPercentage(range, value) {
return (value * 100) / (range[1] - range[0]);
function fromPercentage(range, value, startRange) {
return (value * 100) / (range[startRange + 1] - range[startRange]);
}

// (percentage) Where is this value on this range?
function toPercentage(range, value) {
return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0]);
return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0], 0);
}

// (value) How much is this percentage on this range?
Expand Down Expand Up @@ -348,7 +348,7 @@

// Factor to range ratio
that.xSteps[i] =
fromPercentage([that.xVal[i], that.xVal[i + 1]], n) / subRangeRatio(that.xPct[i], that.xPct[i + 1]);
fromPercentage([that.xVal[i], that.xVal[i + 1]], n, 0) / subRangeRatio(that.xPct[i], that.xPct[i + 1]);

var totalSteps = (that.xVal[i + 1] - that.xVal[i]) / that.xNumSteps[i];
var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
Expand Down Expand Up @@ -406,14 +406,107 @@
}
}

Spectrum.prototype.getMargin = function(value) {
var step = this.xNumSteps[0];
Spectrum.prototype.getDistance = function(value) {
var index;
var distances = [];

for (index = 0; index < this.xNumSteps.length - 1; index++) {
// last "range" can't contain step size as it is purely an endpoint.
var step = this.xNumSteps[index];

if (step && (value / step) % 1 !== 0) {
throw new Error(
"noUiSlider (" +
VERSION +
"): 'limit', 'margin' and 'padding' of " +
this.xPct[index] +
"% range must be divisible by step."
);
}

// Calculate percentual distance in current range of limit, margin or padding
distances[index] = fromPercentage(this.xVal, value, index);
}

return distances;
};

// Calculate the percentual distance over the whole scale of ranges.
// direction: 0 = backwards / 1 = forwards
Spectrum.prototype.getAbsoluteDistance = function(value, distances, direction) {
var xPct_index = 0;

// Calculate range where to start calculation
if (value < this.xPct[this.xPct.length - 1]) {
while (value > this.xPct[xPct_index + 1]) {
xPct_index++;
}
} else if (value === this.xPct[this.xPct.length - 1]) {
xPct_index = this.xPct.length - 2;
}

// If looking backwards and the value is exactly at a range separator then look one range further
if (!direction && value === this.xPct[xPct_index + 1]) {
xPct_index++;
}

var start_factor;
var rest_factor = 1;

var rest_rel_distance = distances[xPct_index];

var range_pct = 0;

if (step && (value / step) % 1 !== 0) {
throw new Error("noUiSlider (" + VERSION + "): 'limit', 'margin' and 'padding' must be divisible by step.");
var rel_range_distance = 0;
var abs_distance_counter = 0;
var range_counter = 0;

// Calculate what part of the start range the value is
if (direction) {
start_factor = (value - this.xPct[xPct_index]) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
} else {
start_factor = (this.xPct[xPct_index + 1] - value) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
}

// Do until the complete distance across ranges is calculated
while (rest_rel_distance > 0) {
// Calculate the percentage of total range
range_pct = this.xPct[xPct_index + 1 + range_counter] - this.xPct[xPct_index + range_counter];

// Detect if the margin, padding or limit is larger then the current range and calculate
if (distances[xPct_index + range_counter] * rest_factor + 100 - start_factor * 100 > 100) {
// If larger then take the percentual distance of the whole range
rel_range_distance = range_pct * start_factor;
// Rest factor of relative percentual distance still to be calculated
rest_factor = (rest_rel_distance - 100 * start_factor) / distances[xPct_index + range_counter];
// Set start factor to 1 as for next range it does not apply.
start_factor = 1;
} else {
// If smaller or equal then take the percentual distance of the calculate percentual part of that range
rel_range_distance = ((distances[xPct_index + range_counter] * range_pct) / 100) * rest_factor;
// No rest left as the rest fits in current range
rest_factor = 0;
}

if (direction) {
abs_distance_counter = abs_distance_counter - rel_range_distance;
// Limit range to first range when distance becomes outside of minimum range
if (this.xPct.length + range_counter >= 1) {
range_counter--;
}
} else {
abs_distance_counter = abs_distance_counter + rel_range_distance;
// Limit range to last range when distance becomes outside of maximum range
if (this.xPct.length - range_counter >= 1) {
range_counter++;
}
}

// Rest of relative percentual distance still to be calculated
rest_rel_distance = distances[xPct_index + range_counter] * rest_factor;
}

return this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false;
return value + abs_distance_counter;
};

Spectrum.prototype.toStepping = function(value) {
Expand Down Expand Up @@ -678,19 +771,15 @@
return;
}

parsed.margin = parsed.spectrum.getMargin(entry);

if (!parsed.margin) {
throw new Error("noUiSlider (" + VERSION + "): 'margin' option is only supported on linear sliders.");
}
parsed.margin = parsed.spectrum.getDistance(entry);
}

function testLimit(parsed, entry) {
if (!isNumeric(entry)) {
throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric.");
}

parsed.limit = parsed.spectrum.getMargin(entry);
parsed.limit = parsed.spectrum.getDistance(entry);

if (!parsed.limit || parsed.handles < 2) {
throw new Error(
Expand All @@ -702,6 +791,8 @@
}

function testPadding(parsed, entry) {
var index;

if (!isNumeric(entry) && !Array.isArray(entry)) {
throw new Error(
"noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
Expand All @@ -722,18 +813,21 @@
entry = [entry, entry];
}

// 'getMargin' returns false for invalid values.
parsed.padding = [parsed.spectrum.getMargin(entry[0]), parsed.spectrum.getMargin(entry[1])];
// 'getDistance' returns false for invalid values.
parsed.padding = [parsed.spectrum.getDistance(entry[0]), parsed.spectrum.getDistance(entry[1])];

if (parsed.padding[0] === false || parsed.padding[1] === false) {
throw new Error("noUiSlider (" + VERSION + "): 'padding' option is only supported on linear sliders.");
for (index = 0; index < parsed.spectrum.xNumSteps.length - 1; index++) {
// last "range" can't contain step size as it is purely an endpoint.
if (parsed.padding[0][index] < 0 || parsed.padding[1][index] < 0) {
throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number(s).");
}
}

if (parsed.padding[0] < 0 || parsed.padding[1] < 0) {
throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number(s).");
}
var totalPadding = entry[0] + entry[1];
var firstValue = parsed.spectrum.xVal[0];
var lastValue = parsed.spectrum.xVal[parsed.spectrum.xVal.length - 1];

if (parsed.padding[0] + parsed.padding[1] > 100) {
if (totalPadding / (lastValue - firstValue) > 1) {
throw new Error("noUiSlider (" + VERSION + "): 'padding' option must not exceed 100% of the range.");
}
}
Expand Down Expand Up @@ -2008,15 +2102,19 @@

// Split out the handle positioning logic so the Move event can use it, too
function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue) {
var distance;

// For sliders with multiple handles, limit movement to the other handle.
// Apply the margin option by adding it to the handle positions.
if (scope_Handles.length > 1 && !options.events.unconstrained) {
if (lookBackward && handleNumber > 0) {
to = Math.max(to, reference[handleNumber - 1] + options.margin);
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.margin, 0);
to = Math.max(to, distance);
}

if (lookForward && handleNumber < scope_Handles.length - 1) {
to = Math.min(to, reference[handleNumber + 1] - options.margin);
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.margin, 1);
to = Math.min(to, distance);
}
}

Expand All @@ -2025,23 +2123,27 @@
// handles would be unmovable.
if (scope_Handles.length > 1 && options.limit) {
if (lookBackward && handleNumber > 0) {
to = Math.min(to, reference[handleNumber - 1] + options.limit);
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.limit, 0);
to = Math.min(to, distance);
}

if (lookForward && handleNumber < scope_Handles.length - 1) {
to = Math.max(to, reference[handleNumber + 1] - options.limit);
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.limit, 1);
to = Math.max(to, distance);
}
}

// The padding option keeps the handles a certain distance from the
// edges of the slider. Padding must be > 0.
if (options.padding) {
if (handleNumber === 0) {
to = Math.max(to, options.padding[0]);
distance = scope_Spectrum.getAbsoluteDistance(0, options.padding[0], 0);
to = Math.max(to, distance);
}

if (handleNumber === scope_Handles.length - 1) {
to = Math.min(to, 100 - options.padding[1]);
distance = scope_Spectrum.getAbsoluteDistance(100, options.padding[1], 1);
to = Math.min(to, distance);
}
}

Expand Down
2 changes: 1 addition & 1 deletion distribute/nouislider.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions distribute/nouislider.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nouislider",
"version": "14.4.0",
"version": "14.5.0",
"main": "distribute/nouislider.js",
"style": "distribute/nouislider.min.css",
"license": "MIT",
Expand Down

0 comments on commit a5bb92a

Please sign in to comment.