LogSlider is a simple widget that extends the original jQuery UI's slider in order to facilitate mapping the handle's position to a specific value based on any mathematical model function. Using logSlider, the implementor can very easily set up an exponential scale without having to worry about the underlying mathematics. It is also very easy to create custom model functions using logSlider's convenient API.
It is strongly recommended to familiarize oneself with the original slider before reading further or using logSlider.
$('#slider').logSlider();Alternatively, it is possible to initialize the widget using options. All methods, options and events are identical to those of the original slider widget; there are a few exceptions and additions unique to logSlider, though.
$('#slider').logSlider({ // See
slide: function (event, ui) {
var value = ui.value;
// OR
value = $(this).logSlider('newValue'); // It's 'newValue', not 'value'
console.log(value);
}
});WARNING: The UI's original slider uses the value method to calibrate its own position and therefore $('#slider').logSlider('value') is not to be used.
To really make the slider non-linear, we need a mathematical function to turn the handle's position into useful numbers. Expressing it numerically, the number extracted from the handle's position is and the number we actually want is
. We modulate
to obtain
. Theoretically, the UI's original slider also has such function:
. But note that this particular function's domain is identical to its range, which renders both domain and range irrelevant. However, in case of other functions this does not apply and therefore with logSlider it is necessary to take these into account.
To amend the domain'n'range, the original slider uses two options: min and max. However, now that domain and range actually matter, these are ambiguous. Does min mean minimum or minimum
? To settle this, logSlider uses these two options:
$('#slider').logSlider({ // The values set in this example are also the default values.
range: [0, 1], // The minimum and maximum y value. Use this instead of min: 0, max: 1
domain: [0, 1] // Absolutely irrelevant in most cases. See the "Custom model functions" section below for further information
});In most cases, the values of are decimals, that sometimes have rather large decimal expansion, something that javascript tends to struggle with. And since such precision is often unnecessary in the context of web, logSlider automatically rounds the output values. This can be also influenced by configuration:
$('#slider').logSlider({ // The value set in this example is also the default value.
maximumDecimals: 5 // Between 0 and 5 decimal points
});By default, logSlider supports two basic model functions. exponential because it is likely to be used the most, and linear in order to ensure some compatibility with the original slider.
$('#slider').logSlider({ // The value set in this example is also the default value.
modelFunction: 'exponential' // See the "Underlying mathematics" section below for further information.
});Quite obviously, in most cases the implementor will not have to worry about this particular setting. However, should he/she decide to create their own model function, it can be done rather easily.
$('#slider').logSlider({
modelFunction: function (options, x) {
// The options object contains all the options the implementor set and the default values.
// The x variable is any value within the domain, a multiple of value of the `step` option.
var d1 = options.domain[0], // First, we need to obtain information about the domain
d2 = options.domain[1],
r1 = options.range[0], // and range.
r2 = options.range[1];
// We can then use some mathematical function and translate it using these variables.
// Simply using something like return Math.asin(x) would not work.
// This approach is better because it works for all domains and ranges.
return ((r2 - r1) * Math.asin((2*x - d2 - d1) / (d2 - d1))) / Math.PI + (r1 + r2) / 2;
// However, if you are unable to do all the math, you can always amend the domain, for instance.
// Sometimes you may also consider the `passThrough` option.
// See the "Changing the curvature" for further information.
}
});Alternatively, it is possible to call the global method registerModelFunction. Model functions registered this way are then available for use by all logSliders on the page.
$.ui.logSlider.registerModelFunction('arcsin', function (options, x) {
// The same magic as shown above.
});
$('#slider1').logSlider({
modelFunction: 'arcsin'
});
$('#slider2').logSlider({
modelFunction: 'arcsin'
});It is highly recommended to read the underlying mathematics section before this one.
Some model functions, such as the default, exponential, can take various forms within one setting of domain and range. In contrast, some other functions, such as linear or the arcsin example above, are entirely defined by domain and range. But for those model functions where it does make sense, logSlider supports the passThrough option.
$('#slider').logSlider({
modelFunction: 'exponential',
range: [0, 1],
domain: [0, 1], // Domain is now important.
passThrough: [0.5, 0.25] // The coordinates must lie within the domain and the range.
});In the example above we want the value to be 0.25 when the handle is in the middle of the slider – the value 0.5 is the average of the domain's two bounds.
This option is to be used wisely as some funny values might result in unexpected behavior. For instance, if we used passThrough: [0, 1] in the previous example, the model function could not possibly exist.
The default model function exponential implements a mathematical function of this form:
. But why?
First, we start with the basic exponential function: . To facilitate the translations, we would like it to pass through the points
(0, 0) and (1, 1). To achieve this, we change the function to . The numerator is
because
, which ensures that the function passes through the origin. And the denominator is
because
, which causes the function to pass through
(1, 1).
Now we need to take care of the translation so that the function satisfies the domain and the range. Let us start with range as the vertical translations are simpler. We simply introduce and
so that the function is now in this form:
.
stretches the function vertically and
shifts it in the same direction.
Now, to translate the function horizontally, we need to replace by a function of
,
. This simple polynomial allows us to perform the same translations but this time horizontally –
stretches and
shifts.
So now we have . If we set the parameters right according to the domain and the range, we obtain a fairly usable exponential function. However, not only that it does not differ too much from
(only within the domain and the range, of course), but it also does not allow us to change the curvature. To solve this problem, we change the function
so that
. By introducing the variable
we can change the curvature and support the
passThrough feature.
The implementor does not get to directly set the value of by design. He/she can only use the
passThrough option to affect it. However, if the value of the passThrough option is too odd, shall remain at the default setting – 1.5.