src/module-elasticsuite-catalog/view/frontend/web/js/slider.js
/*!
* jQuery UI Slider - v1.10.4
* http://jqueryui.com
*
* Copyright 2014 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/slider/
*/
define([
'jquery',
'jquery-ui-modules/core',
'jquery-ui-modules/mouse'
], function ($, undefined) {
// number of pages in a slider
// (how many times can you page up/down to go through the whole range)
var numPages = 5;
$.widget("ui.slider", $.ui.mouse, {
version: "1.10.4",
widgetEventPrefix: "slide",
options: {
animate: false,
distance: 0,
max: 100,
min: 0,
orientation: "horizontal",
range: false,
step: 1,
value: 0,
values: null,
// callbacks
change: null,
slide: null,
start: null,
stop: null
},
_create: function () {
this._keySliding = false;
this._mouseSliding = false;
this._animateOff = true;
this._handleIndex = null;
this._detectOrientation();
this._mouseInit();
this.element
.addClass("ui-slider" +
" ui-slider-" + this.orientation +
" ui-widget" +
" ui-widget-content" +
" ui-corner-all");
this._refresh();
this._setOption("disabled", this.options.disabled);
this._animateOff = false;
},
_refresh: function () {
this._createRange();
this._createHandles();
this._setupEvents();
this._refreshValue();
},
_createHandles: function () {
var i, handleCount,
options = this.options,
existingHandles = this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),
handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
handles = [];
handleCount = (options.values && options.values.length) || 1;
if (existingHandles.length > handleCount) {
existingHandles.slice(handleCount).remove();
existingHandles = existingHandles.slice(0, handleCount);
}
for (i = existingHandles.length; i < handleCount; i++) {
handles.push(handle);
}
this.handles = existingHandles.add($(handles.join("")).appendTo(this.element));
this.handle = this.handles.eq(0);
this.handles.each(function (i) {
$(this).data("ui-slider-handle-index", i);
});
},
_createRange: function () {
var options = this.options,
classes = "";
if (options.range) {
if (options.range === true) {
if (!options.values) {
options.values = [this._valueMin(), this._valueMin()];
} else if (options.values.length && options.values.length !== 2) {
options.values = [options.values[0], options.values[0]];
} else if (Array.isArray(options.values)) {
options.values = options.values.slice(0);
}
}
if (!this.range || !this.range.length) {
this.range = $("<div></div>")
.appendTo(this.element);
classes = "ui-slider-range" +
// note: this isn't the most fittingly semantic framework class for this element,
// but worked best visually with a variety of themes
" ui-widget-header ui-corner-all";
} else {
this.range.removeClass("ui-slider-range-min ui-slider-range-max")
// Handle range switching from true to min/max
.css({
"left": "",
"bottom": ""
});
}
this.range.addClass(classes +
((options.range === "min" || options.range === "max") ? " ui-slider-range-" + options.range : ""));
} else {
if (this.range) {
this.range.remove();
}
this.range = null;
}
},
_setupEvents: function () {
var elements = this.handles.add(this.range).filter("a");
this._off(elements);
this._on(elements, this._handleEvents);
this._hoverable(elements);
this._focusable(elements);
},
_destroy: function () {
this.handles.remove();
if (this.range) {
this.range.remove();
}
this.element
.removeClass("ui-slider" +
" ui-slider-horizontal" +
" ui-slider-vertical" +
" ui-widget" +
" ui-widget-content" +
" ui-corner-all");
this._mouseDestroy();
},
_mouseCapture: function (event) {
var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
that = this,
o = this.options;
if (o.disabled) {
return false;
}
this.elementSize = {
width: this.element.outerWidth(),
height: this.element.outerHeight()
};
this.elementOffset = this.element.offset();
position = {x: event.pageX, y: event.pageY};
normValue = this._normValueFromMouse(position);
distance = this._valueMax() - this._valueMin() + 1;
this.handles.each(function (i) {
var thisDistance = Math.abs(normValue - that.values(i));
if ((distance > thisDistance) ||
(distance === thisDistance &&
(i === that._lastChangedValue || that.values(i) === o.min))) {
distance = thisDistance;
closestHandle = $(this);
index = i;
}
});
allowed = this._start(event, index);
if (allowed === false) {
return false;
}
this._mouseSliding = true;
this._handleIndex = index;
closestHandle
.addClass("ui-state-active")
.trigger("focus");
offset = closestHandle.offset();
mouseOverHandle = !$(event.target).parents().addBack().is(".ui-slider-handle");
this._clickOffset = mouseOverHandle ? {left: 0, top: 0} : {
left: event.pageX - offset.left - (closestHandle.width() / 2),
top: event.pageY - offset.top -
(closestHandle.height() / 2) -
(parseInt(closestHandle.css("borderTopWidth"), 10) || 0) -
(parseInt(closestHandle.css("borderBottomWidth"), 10) || 0) +
(parseInt(closestHandle.css("marginTop"), 10) || 0)
};
if (!this.handles.hasClass("ui-state-hover")) {
this._slide(event, index, normValue);
}
this._animateOff = true;
return true;
},
_mouseStart: function () {
return true;
},
_mouseDrag: function (event) {
var position = {x: event.pageX, y: event.pageY},
normValue = this._normValueFromMouse(position);
this._slide(event, this._handleIndex, normValue);
return false;
},
_mouseStop: function (event) {
this.handles.removeClass("ui-state-active");
this._mouseSliding = false;
this._stop(event, this._handleIndex);
this._change(event, this._handleIndex);
this._handleIndex = null;
this._clickOffset = null;
this._animateOff = false;
return false;
},
_detectOrientation: function () {
this.orientation = (this.options.orientation === "vertical") ? "vertical" : "horizontal";
},
_normValueFromMouse: function (position) {
var pixelTotal,
pixelMouse,
percentMouse,
valueTotal,
valueMouse;
if (this.orientation === "horizontal") {
pixelTotal = this.elementSize.width;
pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
} else {
pixelTotal = this.elementSize.height;
pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
}
percentMouse = (pixelMouse / pixelTotal);
if (percentMouse > 1) {
percentMouse = 1;
}
if (percentMouse < 0) {
percentMouse = 0;
}
if (this.orientation === "vertical") {
percentMouse = 1 - percentMouse;
}
valueTotal = this._valueMax() - this._valueMin();
valueMouse = this._valueMin() + percentMouse * valueTotal;
return this._trimAlignValue(valueMouse);
},
_start: function (event, index) {
var uiHash = {
handle: this.handles[index],
value: this.value()
};
if (this.options.values && this.options.values.length) {
uiHash.value = this.values(index);
uiHash.values = this.values();
}
return this._trigger("start", event, uiHash);
},
_slide: function (event, index, newVal) {
var otherVal,
newValues,
allowed;
if (this.options.values && this.options.values.length) {
otherVal = this.values(index ? 0 : 1);
if ((this.options.values.length === 2 && this.options.range === true) &&
((index === 0 && newVal > otherVal) || (index === 1 && newVal < otherVal))
) {
newVal = otherVal;
}
if (newVal !== this.values(index)) {
newValues = this.values();
newValues[index] = newVal;
// A slide can be canceled by returning false from the slide callback
allowed = this._trigger("slide", event, {
handle: this.handles[index],
value: newVal,
values: newValues
});
otherVal = this.values(index ? 0 : 1);
if (allowed !== false) {
this.values(index, newVal);
}
}
} else {
if (newVal !== this.value()) {
// A slide can be canceled by returning false from the slide callback
allowed = this._trigger("slide", event, {
handle: this.handles[index],
value: newVal
});
if (allowed !== false) {
this.value(newVal);
}
}
}
},
_stop: function (event, index) {
var uiHash = {
handle: this.handles[index],
value: this.value()
};
if (this.options.values && this.options.values.length) {
uiHash.value = this.values(index);
uiHash.values = this.values();
}
this._trigger("stop", event, uiHash);
},
_change: function (event, index) {
if (!this._keySliding && !this._mouseSliding) {
var uiHash = {
handle: this.handles[index],
value: this.value()
};
if (this.options.values && this.options.values.length) {
uiHash.value = this.values(index);
uiHash.values = this.values();
}
//store the last changed value index for reference when handles overlap
this._lastChangedValue = index;
this._trigger("change", event, uiHash);
}
},
value: function (newValue) {
if (arguments.length) {
this.options.value = this._trimAlignValue(newValue);
this._refreshValue();
this._change(null, 0);
return;
}
return this._value();
},
values: function (index, newValue) {
var vals,
newValues,
i;
if (arguments.length > 1) {
this.options.values[index] = this._trimAlignValue(newValue);
this._refreshValue();
this._change(null, index);
return;
}
if (arguments.length) {
if (Array.isArray(arguments[0])) {
vals = this.options.values;
newValues = arguments[0];
for (i = 0; i < vals.length; i += 1) {
vals[i] = this._trimAlignValue(newValues[i]);
this._change(null, i);
}
this._refreshValue();
} else {
if (this.options.values && this.options.values.length) {
return this._values(index);
} else {
return this.value();
}
}
} else {
return this._values();
}
},
_setOption: function (key, value) {
var i,
valsLength = 0;
if (key === "range" && this.options.range === true) {
if (value === "min") {
this.options.value = this._values(0);
this.options.values = null;
} else if (value === "max") {
this.options.value = this._values(this.options.values.length - 1);
this.options.values = null;
}
}
if (Array.isArray(this.options.values)) {
valsLength = this.options.values.length;
}
$.Widget.prototype._setOption.apply(this, arguments);
switch (key) {
case "orientation":
this._detectOrientation();
this.element
.removeClass("ui-slider-horizontal ui-slider-vertical")
.addClass("ui-slider-" + this.orientation);
this._refreshValue();
break;
case "value":
this._animateOff = true;
this._refreshValue();
this._change(null, 0);
this._animateOff = false;
break;
case "values":
this._animateOff = true;
this._refreshValue();
for (i = 0; i < valsLength; i += 1) {
this._change(null, i);
}
this._animateOff = false;
break;
case "min":
case "max":
this._animateOff = true;
this._refreshValue();
this._animateOff = false;
break;
case "range":
this._animateOff = true;
this._refresh();
this._animateOff = false;
break;
}
},
//internal value getter
// _value() returns value trimmed by min and max, aligned by step
_value: function () {
var val = this.options.value;
val = this._trimAlignValue(val);
return val;
},
//internal values getter
// _values() returns array of values trimmed by min and max, aligned by step
// _values( index ) returns single value trimmed by min and max, aligned by step
_values: function (index) {
var val,
vals,
i;
if (arguments.length) {
val = this.options.values[index];
val = this._trimAlignValue(val);
return val;
} else if (this.options.values && this.options.values.length) {
// .slice() creates a copy of the array
// this copy gets trimmed by min and max and then returned
vals = this.options.values.slice();
for (i = 0; i < vals.length; i += 1) {
vals[i] = this._trimAlignValue(vals[i]);
}
return vals;
} else {
return [];
}
},
// returns the step-aligned value that val is closest to, between (inclusive) min and max
_trimAlignValue: function (val) {
if (val <= this._valueMin()) {
return this._valueMin();
}
if (val >= this._valueMax()) {
return this._valueMax();
}
var step = (this.options.step > 0) ? this.options.step : 1,
valModStep = (val - this._valueMin()) % step,
alignValue = val - valModStep;
if (Math.abs(valModStep) * 2 >= step) {
alignValue += (valModStep > 0) ? step : (-step);
}
// Since JavaScript has problems with large floats, round
// the final value to 5 digits after the decimal point (see #4124)
return parseFloat(alignValue.toFixed(5));
},
_valueMin: function () {
return this.options.min;
},
_valueMax: function () {
return this.options.max;
},
_refreshValue: function () {
var lastValPercent, valPercent, value, valueMin, valueMax,
oRange = this.options.range,
o = this.options,
that = this,
animate = (!this._animateOff) ? o.animate : false,
_set = {};
if (this.options.values && this.options.values.length) {
this.handles.each(function (i) {
valPercent = (that.values(i) - that._valueMin()) / (that._valueMax() - that._valueMin()) * 100;
_set[that.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
$(this).stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);
if (that.options.range === true) {
if (that.orientation === "horizontal") {
if (i === 0) {
that.range.stop(1, 1)[animate ? "animate" : "css"]({left: valPercent + "%"}, o.animate);
}
if (i === 1) {
that.range[animate ? "animate" : "css"]({width: (valPercent - lastValPercent) + "%"}, {
queue: false,
duration: o.animate
});
}
} else {
if (i === 0) {
that.range.stop(1, 1)[animate ? "animate" : "css"]({bottom: (valPercent) + "%"}, o.animate);
}
if (i === 1) {
that.range[animate ? "animate" : "css"]({height: (valPercent - lastValPercent) + "%"}, {
queue: false,
duration: o.animate
});
}
}
}
lastValPercent = valPercent;
});
} else {
value = this.value();
valueMin = this._valueMin();
valueMax = this._valueMax();
valPercent = (valueMax !== valueMin) ?
(value - valueMin) / (valueMax - valueMin) * 100 :
0;
_set[this.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
this.handle.stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);
if (oRange === "min" && this.orientation === "horizontal") {
this.range.stop(1, 1)[animate ? "animate" : "css"]({width: valPercent + "%"}, o.animate);
}
if (oRange === "max" && this.orientation === "horizontal") {
this.range[animate ? "animate" : "css"]({width: (100 - valPercent) + "%"}, {
queue: false,
duration: o.animate
});
}
if (oRange === "min" && this.orientation === "vertical") {
this.range.stop(1, 1)[animate ? "animate" : "css"]({height: valPercent + "%"}, o.animate);
}
if (oRange === "max" && this.orientation === "vertical") {
this.range[animate ? "animate" : "css"]({height: (100 - valPercent) + "%"}, {
queue: false,
duration: o.animate
});
}
}
},
_handleEvents: {
keydown: function (event) {
var allowed, curVal, newVal, step,
index = $(event.target).data("ui-slider-handle-index");
switch (event.keyCode) {
case $.ui.keyCode.HOME:
case $.ui.keyCode.END:
case $.ui.keyCode.PAGE_UP:
case $.ui.keyCode.PAGE_DOWN:
case $.ui.keyCode.UP:
case $.ui.keyCode.RIGHT:
case $.ui.keyCode.DOWN:
case $.ui.keyCode.LEFT:
event.preventDefault();
if (!this._keySliding) {
this._keySliding = true;
$(event.target).addClass("ui-state-active");
allowed = this._start(event, index);
if (allowed === false) {
return;
}
}
break;
}
step = this.options.step;
if (this.options.values && this.options.values.length) {
curVal = newVal = this.values(index);
} else {
curVal = newVal = this.value();
}
switch (event.keyCode) {
case $.ui.keyCode.HOME:
newVal = this._valueMin();
break;
case $.ui.keyCode.END:
newVal = this._valueMax();
break;
case $.ui.keyCode.PAGE_UP:
newVal = this._trimAlignValue(curVal + ((this._valueMax() - this._valueMin()) / numPages));
break;
case $.ui.keyCode.PAGE_DOWN:
newVal = this._trimAlignValue(curVal - ((this._valueMax() - this._valueMin()) / numPages));
break;
case $.ui.keyCode.UP:
case $.ui.keyCode.RIGHT:
if (curVal === this._valueMax()) {
return;
}
newVal = this._trimAlignValue(curVal + step);
break;
case $.ui.keyCode.DOWN:
case $.ui.keyCode.LEFT:
if (curVal === this._valueMin()) {
return;
}
newVal = this._trimAlignValue(curVal - step);
break;
}
this._slide(event, index, newVal);
},
click: function (event) {
event.preventDefault();
},
keyup: function (event) {
var index = $(event.target).data("ui-slider-handle-index");
if (this._keySliding) {
this._keySliding = false;
this._stop(event, index);
this._change(event, index);
$(event.target).removeClass("ui-state-active");
}
}
}
});
});