Commit 0181c28d authored by Valentin Hervieu's avatar Valentin Hervieu

2.10.0 release

parent a97b40af
2.10.0 (2016-02-28)
#2.10.0 (2016-02-29)
## Features
- Added rightToLeft option for RTL support (#270)
- Added `rightToLeft` option for RTL support (#270)
# 2.9.0 (2016-02-18)
## Features
......
......@@ -297,7 +297,7 @@ $scope.slider = {
**onEnd** - _Function(sliderId, modelValue, highValue)_: Function to be called when a slider update is ended. If an id was set in the options, then it's passed to this callback.
**rightToLeft** - _Boolean (defaults to false)_: Set to true to show graphs right to left. If **vertical** is true it reverses the left / right arrow functions
**rightToLeft** - _Boolean (defaults to false)_: Set to true to show graphs right to left. If **vertical** is true it will be from top to bottom and left / right arrow functions reversed.
**vertical** - _Boolean (defaults to false)_: Set to true to display the slider vertically. The slider will take the full height of its parent.
_Changing this value at runtime is not currently supported._
......
{
"name": "angularjs-slider",
"version": "2.9.0",
"version": "2.10.0",
"homepage": "https://github.com/angular-slider/angularjs-slider",
"authors": [
"Rafal Zajac <rzajac@gmail.com>",
......
/*! angularjs-slider - v2.9.0 -
/*! angularjs-slider - v2.10.0 -
(c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> -
https://github.com/angular-slider/angularjs-slider -
2016-02-29 */
......
/*! angularjs-slider - v2.10.0 -
(c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> -
https://github.com/angular-slider/angularjs-slider -
2016-02-29 */
/*jslint unparam: true */
/*global angular: false, console: false, define, module */
(function(root, factory) {
'use strict';
/* istanbul ignore next */
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['angular'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
// to support bundler like browserify
module.exports = factory(require('angular'));
} else {
// Browser globals (root is window)
factory(root.angular);
}
}(this, function(angular) {
'use strict';
var module = angular.module('rzModule', [])
.factory('RzSliderOptions', function() {
var defaultOptions = {
floor: 0,
ceil: null, //defaults to rz-slider-model
step: 1,
precision: 0,
minRange: 0,
id: null,
translate: null,
stepsArray: null,
draggableRange: false,
draggableRangeOnly: false,
showSelectionBar: false,
showSelectionBarEnd: false,
showSelectionBarFromValue: null,
hideLimitLabels: false,
readOnly: false,
disabled: false,
interval: 350,
showTicks: false,
showTicksValues: false,
ticksTooltip: null,
ticksValuesTooltip: null,
vertical: false,
getSelectionBarColor: null,
getPointerColor: null,
keyboardSupport: true,
scale: 1,
enforceStep: true,
enforceRange: false,
noSwitching: false,
onlyBindHandles: false,
onStart: null,
onChange: null,
onEnd: null,
rightToLeft: false
};
var globalOptions = {};
var factory = {};
/**
* `options({})` allows global configuration of all sliders in the
* application.
*
* var app = angular.module( 'App', ['rzModule'], function( RzSliderOptions ) {
* // show ticks for all sliders
* RzSliderOptions.options( { showTicks: true } );
* });
*/
factory.options = function(value) {
angular.extend(globalOptions, value);
};
factory.getOptions = function(options) {
return angular.extend({}, defaultOptions, globalOptions, options);
};
return factory;
})
.factory('rzThrottle', ['$timeout', function($timeout) {
/**
* rzThrottle
*
* Taken from underscore project
*
* @param {Function} func
* @param {number} wait
* @param {ThrottleOptions} options
* @returns {Function}
*/
return function(func, wait, options) {
'use strict';
/* istanbul ignore next */
var getTime = (Date.now || function() {
return new Date().getTime();
});
var context, args, result;
var timeout = null;
var previous = 0;
options = options || {};
var later = function() {
previous = getTime();
timeout = null;
result = func.apply(context, args);
context = args = null;
};
return function() {
var now = getTime();
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0) {
$timeout.cancel(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = $timeout(later, remaining);
}
return result;
};
}
}])
.factory('RzSlider', ['$timeout', '$document', '$window', '$compile', 'RzSliderOptions', 'rzThrottle', function($timeout, $document, $window, $compile, RzSliderOptions, rzThrottle) {
'use strict';
/**
* Slider
*
* @param {ngScope} scope The AngularJS scope
* @param {Element} sliderElem The slider directive element wrapped in jqLite
* @constructor
*/
var Slider = function(scope, sliderElem) {
/**
* The slider's scope
*
* @type {ngScope}
*/
this.scope = scope;
/**
* Slider element wrapped in jqLite
*
* @type {jqLite}
*/
this.sliderElem = sliderElem;
/**
* Slider type
*
* @type {boolean} Set to true for range slider
*/
this.range = this.scope.rzSliderModel !== undefined && this.scope.rzSliderHigh !== undefined;
/**
* Values recorded when first dragging the bar
*
* @type {Object}
*/
this.dragging = {
active: false,
value: 0,
difference: 0,
offset: 0,
lowLimit: 0,
highLimit: 0
};
/**
* property that handle position (defaults to left for horizontal)
* @type {string}
*/
this.positionProperty = 'left';
/**
* property that handle dimension (defaults to width for horizontal)
* @type {string}
*/
this.dimensionProperty = 'width';
/**
* Half of the width or height of the slider handles
*
* @type {number}
*/
this.handleHalfDim = 0;
/**
* Maximum position the slider handle can have
*
* @type {number}
*/
this.maxPos = 0;
/**
* Precision
*
* @type {number}
*/
this.precision = 0;
/**
* Step
*
* @type {number}
*/
this.step = 1;
/**
* The name of the handle we are currently tracking
*
* @type {string}
*/
this.tracking = '';
/**
* Minimum value (floor) of the model
*
* @type {number}
*/
this.minValue = 0;
/**
* Maximum value (ceiling) of the model
*
* @type {number}
*/
this.maxValue = 0;
/**
* The delta between min and max value
*
* @type {number}
*/
this.valueRange = 0;
/**
* Set to true if init method already executed
*
* @type {boolean}
*/
this.initHasRun = false;
/**
* Internal flag to prevent watchers to be called when the sliders value are modified internally.
* @type {boolean}
*/
this.internalChange = false;
// Slider DOM elements wrapped in jqLite
this.fullBar = null; // The whole slider bar
this.selBar = null; // Highlight between two handles
this.minH = null; // Left slider handle
this.maxH = null; // Right slider handle
this.flrLab = null; // Floor label
this.ceilLab = null; // Ceiling label
this.minLab = null; // Label above the low value
this.maxLab = null; // Label above the high value
this.cmbLab = null; // Combined label
this.ticks = null; // The ticks
// Initialize slider
this.init();
};
// Add instance methods
Slider.prototype = {
/**
* Initialize slider
*
* @returns {undefined}
*/
init: function() {
var thrLow, thrHigh,
self = this;
var calcDimFn = function() {
self.calcViewDimensions();
};
this.applyOptions();
this.initElemHandles();
this.manageElementsStyle();
this.setDisabledState();
this.calcViewDimensions();
this.setMinAndMax();
this.addAccessibility();
this.updateCeilLab();
this.updateFloorLab();
this.initHandles();
this.manageEventsBindings();
// Recalculate slider view dimensions
this.scope.$on('reCalcViewDimensions', calcDimFn);
// Recalculate stuff if view port dimensions have changed
angular.element($window).on('resize', calcDimFn);
this.initHasRun = true;
// Watch for changes to the model
thrLow = rzThrottle(function() {
self.onLowHandleChange();
}, self.options.interval);
thrHigh = rzThrottle(function() {
self.onHighHandleChange();
}, self.options.interval);
this.scope.$on('rzSliderForceRender', function() {
self.resetLabelsValue();
thrLow();
if (self.range) {
thrHigh();
}
self.resetSlider();
});
// Watchers (order is important because in case of simultaneous change,
// watchers will be called in the same order)
this.scope.$watch('rzSliderOptions()', function(newValue, oldValue) {
if (newValue === oldValue)
return;
self.applyOptions();
self.resetSlider();
}, true);
this.scope.$watch('rzSliderModel', function(newValue, oldValue) {
if (self.internalChange)
return;
if (newValue === oldValue)
return;
thrLow();
});
this.scope.$watch('rzSliderHigh', function(newValue, oldValue) {
if (self.internalChange)
return;
if (newValue === oldValue)
return;
if (newValue != null)
thrHigh();
if (self.range && newValue == null || !self.range && newValue != null) {
self.applyOptions();
self.resetSlider();
}
});
this.scope.$on('$destroy', function() {
self.unbindEvents();
angular.element($window).off('resize', calcDimFn);
});
},
/*
* Reflow the slider when the low handle changes (called with throttle)
*/
onLowHandleChange: function() {
this.setMinAndMax();
this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel));
this.updateSelectionBar();
this.updateTicksScale();
this.updateAriaAttributes();
if (this.range) {
this.updateCmbLabel();
}
},
/*
* Reflow the slider when the high handle changes (called with throttle)
*/
onHighHandleChange: function() {
this.setMinAndMax();
this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh));
this.updateSelectionBar();
this.updateTicksScale();
this.updateCmbLabel();
this.updateAriaAttributes();
},
/**
* Read the user options and apply them to the slider model
*/
applyOptions: function() {
var sliderOptions;
if (this.scope.rzSliderOptions)
sliderOptions = this.scope.rzSliderOptions();
else
sliderOptions = {};
this.options = RzSliderOptions.getOptions(sliderOptions);
if (this.options.step <= 0)
this.options.step = 1;
this.range = this.scope.rzSliderModel !== undefined && this.scope.rzSliderHigh !== undefined;
this.options.draggableRange = this.range && this.options.draggableRange;
this.options.draggableRangeOnly = this.range && this.options.draggableRangeOnly;
if (this.options.draggableRangeOnly) {
this.options.draggableRange = true;
}
this.options.showTicks = this.options.showTicks || this.options.showTicksValues;
this.scope.showTicks = this.options.showTicks; //scope is used in the template
this.options.showSelectionBar = this.options.showSelectionBar || this.options.showSelectionBarEnd
|| this.options.showSelectionBarFromValue !== null;
if (this.options.stepsArray) {
this.options.floor = 0;
this.options.ceil = this.options.stepsArray.length - 1;
this.options.step = 1;
this.customTrFn = function(value) {
return this.options.stepsArray[value];
};
} else if (this.options.translate)
this.customTrFn = this.options.translate;
else
this.customTrFn = function(value) {
return String(value);
};
if (this.options.vertical) {
this.positionProperty = 'bottom';
this.dimensionProperty = 'height';
}
},
/**
* Resets slider
*
* @returns {undefined}
*/
resetSlider: function() {
this.manageElementsStyle();
this.addAccessibility();
this.setMinAndMax();
this.updateCeilLab();
this.updateFloorLab();
this.unbindEvents();
this.manageEventsBindings();
this.setDisabledState();
this.calcViewDimensions();
},
/**
* Set the slider children to variables for easy access
*
* Run only once during initialization
*
* @returns {undefined}
*/
initElemHandles: function() {
// Assign all slider elements to object properties for easy access
angular.forEach(this.sliderElem.children(), function(elem, index) {
var jElem = angular.element(elem);
switch (index) {
case 0:
this.fullBar = jElem;
break;
case 1:
this.selBar = jElem;
break;
case 2:
this.minH = jElem;
break;
case 3:
this.maxH = jElem;
break;
case 4:
this.flrLab = jElem;
break;
case 5:
this.ceilLab = jElem;
break;
case 6:
this.minLab = jElem;
break;
case 7:
this.maxLab = jElem;
break;
case 8:
this.cmbLab = jElem;
break;
case 9:
this.ticks = jElem;
break;
}
}, this);
// Initialize offset cache properties
this.selBar.rzsp = 0;
this.minH.rzsp = 0;
this.maxH.rzsp = 0;
this.flrLab.rzsp = 0;
this.ceilLab.rzsp = 0;
this.minLab.rzsp = 0;
this.maxLab.rzsp = 0;
this.cmbLab.rzsp = 0;
},
/**
* Update each elements style based on options
*/
manageElementsStyle: function() {
if (!this.range)
this.maxH.css('display', 'none');
else
this.maxH.css('display', '');
this.alwaysHide(this.flrLab, this.options.showTicksValues || this.options.hideLimitLabels);
this.alwaysHide(this.ceilLab, this.options.showTicksValues || this.options.hideLimitLabels);
this.alwaysHide(this.minLab, this.options.showTicksValues);
this.alwaysHide(this.maxLab, this.options.showTicksValues || !this.range);
this.alwaysHide(this.cmbLab, this.options.showTicksValues || !this.range);
this.alwaysHide(this.selBar, !this.range && !this.options.showSelectionBar);
if (this.options.vertical)
this.sliderElem.addClass('vertical');
if (this.options.draggableRange)
this.selBar.addClass('rz-draggable');
else
this.selBar.removeClass('rz-draggable');
},
alwaysHide: function(el, hide) {
el.rzAlwaysHide = hide;
if (hide)
this.hideEl(el);
else
this.showEl(el)
},
/**
* Manage the events bindings based on readOnly and disabled options
*
* @returns {undefined}
*/
manageEventsBindings: function() {
if (this.options.disabled || this.options.readOnly)
this.unbindEvents();
else
this.bindEvents();
},
/**
* Set the disabled state based on rzSliderDisabled
*
* @returns {undefined}
*/
setDisabledState: function() {
if (this.options.disabled) {
this.sliderElem.attr('disabled', 'disabled');
} else {
this.sliderElem.attr('disabled', null);
}
},
/**
* Reset label values
*
* @return {undefined}
*/
resetLabelsValue: function() {
this.minLab.rzsv = undefined;
this.maxLab.rzsv = undefined;
},
/**
* Initialize slider handles positions and labels
*
* Run only once during initialization and every time view port changes size
*
* @returns {undefined}
*/
initHandles: function() {
this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel));
/*
the order here is important since the selection bar should be
updated after the high handle but before the combined label
*/
if (this.range)
this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh));
this.updateSelectionBar();
if (this.range)
this.updateCmbLabel();
this.updateTicksScale();
},
/**
* Translate value to human readable format
*
* @param {number|string} value
* @param {jqLite} label
* @param {boolean} [useCustomTr]
* @returns {undefined}
*/
translateFn: function(value, label, which, useCustomTr) {
useCustomTr = useCustomTr === undefined ? true : useCustomTr;
var valStr = String((useCustomTr ? this.customTrFn(value, this.options.id, which) : value)),
getDimension = false;
if (label.rzsv === undefined || label.rzsv.length !== valStr.length || (label.rzsv.length > 0 && label.rzsd === 0)) {
getDimension = true;
label.rzsv = valStr;
}
label.html(valStr);
// Update width only when length of the label have changed
if (getDimension) {
this.getDimension(label);
}
},
/**
* Set maximum and minimum values for the slider and ensure the model and high
* value match these limits
* @returns {undefined}
*/
setMinAndMax: function() {
this.step = +this.options.step;
this.precision = +this.options.precision;
this.minValue = this.options.floor;
if (this.options.enforceStep) {
this.scope.rzSliderModel = this.roundStep(this.scope.rzSliderModel);
if (this.range)
this.scope.rzSliderHigh = this.roundStep(this.scope.rzSliderHigh);
}
if (this.options.ceil != null)
this.maxValue = this.options.ceil;
else
this.maxValue = this.options.ceil = this.range ? this.scope.rzSliderHigh : this.scope.rzSliderModel;
if (this.options.enforceRange) {
this.scope.rzSliderModel = this.sanitizeValue(this.scope.rzSliderModel);
if (this.range)
this.scope.rzSliderHigh = this.sanitizeValue(this.scope.rzSliderHigh);
}
this.valueRange = this.maxValue - this.minValue;
},
/**
* Adds accessibility attributes
*
* Run only once during initialization
*
* @returns {undefined}
*/
addAccessibility: function() {
this.minH.attr('role', 'slider');
this.updateAriaAttributes();
if (this.options.keyboardSupport && !(this.options.readOnly || this.options.disabled))
this.minH.attr('tabindex', '0');
else
this.minH.attr('tabindex', '');
if (this.options.vertical)
this.minH.attr('aria-orientation', 'vertical');
if (this.range) {
this.maxH.attr('role', 'slider');
if (this.options.keyboardSupport && !(this.options.readOnly || this.options.disabled))
this.maxH.attr('tabindex', '0');
else
this.maxH.attr('tabindex', '');
if (this.options.vertical)
this.maxH.attr('aria-orientation', 'vertical');
}
},
/**
* Updates aria attributes according to current values
*/
updateAriaAttributes: function() {
this.minH.attr({
'aria-valuenow': this.scope.rzSliderModel,
'aria-valuetext': this.customTrFn(this.scope.rzSliderModel, this.options.id, 'model'),
'aria-valuemin': this.minValue,
'aria-valuemax': this.maxValue
});
if (this.range) {
this.maxH.attr({
'aria-valuenow': this.scope.rzSliderHigh,
'aria-valuetext': this.customTrFn(this.scope.rzSliderHigh, this.options.id, 'high'),
'aria-valuemin': this.minValue,
'aria-valuemax': this.maxValue
});
}
},
/**
* Calculate dimensions that are dependent on view port size
*
* Run once during initialization and every time view port changes size.
*
* @returns {undefined}
*/
calcViewDimensions: function() {
var handleWidth = this.getDimension(this.minH);
this.handleHalfDim = handleWidth / 2;
this.barDimension = this.getDimension(this.fullBar);
this.maxPos = this.barDimension - handleWidth;
this.getDimension(this.sliderElem);
this.sliderElem.rzsp = this.sliderElem[0].getBoundingClientRect()[this.positionProperty];
if (this.initHasRun) {
this.updateFloorLab();
this.updateCeilLab();
this.initHandles();
}
},
/**
* Update the ticks position
*
* @returns {undefined}
*/
updateTicksScale: function() {
if (!this.options.showTicks) return;
var positions = '',
ticksCount = Math.round((this.maxValue - this.minValue) / this.step) + 1;
this.scope.ticks = [];
for (var i = 0; i < ticksCount; i++) {
var value = this.roundStep(this.minValue + i * this.step);
var tick = {
selected: this.isTickSelected(value)
};
if (tick.selected && this.options.getSelectionBarColor) {
tick.style = {
'background-color': this.getSelectionBarColor()
};
}
if (this.options.ticksTooltip) {
tick.tooltip = this.options.ticksTooltip(value);
tick.tooltipPlacement = this.options.vertical ? 'right' : 'top';
}
if (this.options.showTicksValues) {
tick.value = this.getDisplayValue(value, 'tick-value');
if (this.options.ticksValuesTooltip) {
tick.valueTooltip = this.options.ticksValuesTooltip(value);
tick.valueTooltipPlacement = this.options.vertical ? 'right' : 'top';
}
}
if (!this.options.rightToLeft) {
this.scope.ticks.push(tick);
} else {
this.scope.ticks.unshift(tick);
}
}
},
isTickSelected: function(value) {
if (!this.range) {
if (this.options.showSelectionBarFromValue !== null) {
var center = this.options.showSelectionBarFromValue;
if (this.scope.rzSliderModel > center && value >= center && value <= this.scope.rzSliderModel)
return true;
else if (this.scope.rzSliderModel < center && value <= center && value >= this.scope.rzSliderModel)
return true;
}
else if (this.options.showSelectionBarEnd) {
if (value >= this.scope.rzSliderModel)
return true;
}
else if (this.options.showSelectionBar && value <= this.scope.rzSliderModel)
return true;
}
if (this.range && value >= this.scope.rzSliderModel && value <= this.scope.rzSliderHigh)
return true;
return false;
},
/**
* Update position of the floor label
*
* @returns {undefined}
*/
updateFloorLab: function() {
this.translateFn(this.minValue, this.flrLab, 'floor');
this.getDimension(this.flrLab);
var position = this.options.rightToLeft ? this.barDimension - this.flrLab.rzsd : 0;
this.setPosition(this.flrLab, position);
},
/**
* Update position of the ceiling label
*
* @returns {undefined}
*/
updateCeilLab: function() {
this.translateFn(this.maxValue, this.ceilLab, 'ceil');
this.getDimension(this.ceilLab);
var position = this.options.rightToLeft ? 0 : this.barDimension - this.ceilLab.rzsd;
this.setPosition(this.ceilLab, position);
},
/**
* Update slider handles and label positions
*
* @param {string} which
* @param {number} newOffset
*/
updateHandles: function(which, newOffset) {
if (which === 'rzSliderModel')
this.updateLowHandle(newOffset);
else
this.updateHighHandle(newOffset);
this.updateSelectionBar();
this.updateTicksScale();
if (this.range)
this.updateCmbLabel();
},
/**
* Helper function to work out the position for handle labels depending on RTL or not
*
* @param {string} labelName maxLab or minLab
* @param newOffset
*
* @returns {number}
*/
getHandleLabelPos: function(labelName, newOffset) {
var labelRzsd = this[labelName].rzsd,
nearHandlePos = newOffset - labelRzsd / 2 + this.handleHalfDim,
endOfBarPos = this.barDimension - labelRzsd;
if (this.options.rightToLeft && labelName === 'minLab' || !this.options.rightToLeft && labelName === 'maxLab') {
return Math.min(nearHandlePos, endOfBarPos);
} else {
return Math.min(Math.max(nearHandlePos, 0), endOfBarPos);
}
},
/**
* Update low slider handle position and label
*
* @param {number} newOffset
* @returns {undefined}
*/
updateLowHandle: function(newOffset) {
this.setPosition(this.minH, newOffset);
this.translateFn(this.scope.rzSliderModel, this.minLab, 'model');
this.setPosition(this.minLab, this.getHandleLabelPos('minLab', newOffset));
if (this.options.getPointerColor) {
var pointercolor = this.getPointerColor('min');
this.scope.minPointerStyle = {
backgroundColor: pointercolor
};
}
this.shFloorCeil();
},
/**
* Update high slider handle position and label
*
* @param {number} newOffset
* @returns {undefined}
*/
updateHighHandle: function(newOffset) {
this.setPosition(this.maxH, newOffset);
this.translateFn(this.scope.rzSliderHigh, this.maxLab, 'high');
this.setPosition(this.maxLab, this.getHandleLabelPos('maxLab', newOffset));
if (this.options.getPointerColor) {
var pointercolor = this.getPointerColor('max');
this.scope.maxPointerStyle = {
backgroundColor: pointercolor
};
}
this.shFloorCeil();
},
/**
* Show/hide floor/ceiling label
*
* @returns {undefined}
*/
shFloorCeil: function() {
var flHidden = false,
clHidden = false,
isRTL = this.options.rightToLeft,
flrLabPos = this.flrLab.rzsp,
flrLabDim = this.flrLab.rzsd,
minLabPos = this.minLab.rzsp,
minLabDim = this.minLab.rzsd,
maxLabPos = this.maxLab.rzsp,
maxLabDim = this.maxLab.rzsd,
ceilLabPos = this.ceilLab.rzsp,
halfHandle = this.handleHalfDim,
isMinLabAtFloor = isRTL ? minLabPos + minLabDim >= flrLabPos - flrLabDim - 5 : minLabPos <= flrLabPos + flrLabDim + 5,
isMinLabAtCeil = isRTL ? minLabPos - minLabDim <= ceilLabPos + halfHandle + 10 : minLabPos + minLabDim >= ceilLabPos - halfHandle - 10,
isMaxLabAtFloor = isRTL ? maxLabPos >= flrLabPos - flrLabDim - halfHandle : maxLabPos <= flrLabPos + flrLabDim + halfHandle,
isMaxLabAtCeil = isRTL ? maxLabPos - maxLabDim <= ceilLabPos + 10 : maxLabPos + maxLabDim >= ceilLabPos - 10;
if (isMinLabAtFloor) {
flHidden = true;
this.hideEl(this.flrLab);
} else {
flHidden = false;
this.showEl(this.flrLab);
}
if (isMinLabAtCeil) {
clHidden = true;
this.hideEl(this.ceilLab);
} else {
clHidden = false;
this.showEl(this.ceilLab);
}
if (this.range) {
if (isMaxLabAtCeil) {
this.hideEl(this.ceilLab);
} else if (!clHidden) {
this.showEl(this.ceilLab);
}
// Hide or show floor label
if (isMaxLabAtFloor) {
this.hideEl(this.flrLab);
} else if (!flHidden) {
this.showEl(this.flrLab);
}
}
},
/**
* Update slider selection bar, combined label and range label
*
* @returns {undefined}
*/
updateSelectionBar: function() {
var position = 0,
dimension = 0,
isSelectionBarFromRight = this.options.rightToLeft ? !this.options.showSelectionBarEnd : this.options.showSelectionBarEnd,
positionForRange = this.options.rightToLeft ? this.maxH.rzsp + this.handleHalfDim : this.minH.rzsp + this.handleHalfDim;
if (this.range) {
dimension = Math.abs(this.maxH.rzsp - this.minH.rzsp);
position = positionForRange;
}
else {
if (this.options.showSelectionBarFromValue !== null) {
var center = this.options.showSelectionBarFromValue,
centerPosition = this.valueToOffset(center),
isModelGreaterThanCenter = this.options.rightToLeft ? this.scope.rzSliderModel <= center : this.scope.rzSliderModel > center;
if (isModelGreaterThanCenter) {
dimension = this.minH.rzsp - centerPosition;
position = centerPosition + this.handleHalfDim;
}
else {
dimension = centerPosition - this.minH.rzsp;
position = this.minH.rzsp + this.handleHalfDim;
}
}
else if (isSelectionBarFromRight) {
dimension = Math.abs(this.maxPos - this.minH.rzsp) + this.handleHalfDim;
position = this.minH.rzsp + this.handleHalfDim;
} else {
dimension = Math.abs(this.maxH.rzsp - this.minH.rzsp) + this.handleHalfDim;
position = 0;
}
}
this.setDimension(this.selBar, dimension);
this.setPosition(this.selBar, position);
if (this.options.getSelectionBarColor) {
var color = this.getSelectionBarColor();
this.scope.barStyle = {
backgroundColor: color
};
}
},
/**
* Wrapper around the getSelectionBarColor of the user to pass to
* correct parameters
*/
getSelectionBarColor: function() {
if (this.range)
return this.options.getSelectionBarColor(this.scope.rzSliderModel, this.scope.rzSliderHigh);
return this.options.getSelectionBarColor(this.scope.rzSliderModel);
},
/**
* Wrapper around the getPointerColor of the user to pass to
* correct parameters
*/
getPointerColor: function(pointerType) {
if (pointerType === 'max') {
return this.options.getPointerColor(this.scope.rzSliderHigh, pointerType);
}
return this.options.getPointerColor(this.scope.rzSliderModel, pointerType);
},
/**
* Update combined label position and value
*
* @returns {undefined}
*/
updateCmbLabel: function() {
var isLabelOverlap = null;
if (this.options.rightToLeft) {
isLabelOverlap = this.minLab.rzsp - this.minLab.rzsd - 10 <= this.maxLab.rzsp;
} else {
isLabelOverlap = this.minLab.rzsp + this.minLab.rzsd + 10 >= this.maxLab.rzsp;
}
if (isLabelOverlap) {
var lowTr = this.getDisplayValue(this.scope.rzSliderModel, 'model'),
highTr = this.getDisplayValue(this.scope.rzSliderHigh, 'high'),
labelVal = '';
if (lowTr === highTr) {
labelVal = lowTr;
} else {
labelVal = this.options.rightToLeft ? highTr + ' - ' + lowTr : lowTr + ' - ' + highTr;
}
this.translateFn(labelVal, this.cmbLab, 'cmb', false);
var pos = Math.min(
Math.max(
this.selBar.rzsp + this.selBar.rzsd / 2 - this.cmbLab.rzsd / 2,
0
),
this.barDimension - this.cmbLab.rzsd
);
this.setPosition(this.cmbLab, pos);
this.hideEl(this.minLab);
this.hideEl(this.maxLab);
this.showEl(this.cmbLab);
} else {
this.showEl(this.maxLab);
this.showEl(this.minLab);
this.hideEl(this.cmbLab);
}
},
/**
* Return the translated value if a translate function is provided else the original value
* @param value
* @returns {*}
*/
getDisplayValue: function(value, which) {
return this.customTrFn(value, this.options.id, which);
},
/**
* Round value to step and precision based on minValue
*
* @param {number} value
* @returns {number}
*/
roundStep: function(value) {
var steppedDifference = parseFloat((value - this.minValue) / this.step).toPrecision(12);
steppedDifference = Math.round(steppedDifference) * this.step;
var newValue = (this.minValue + steppedDifference).toFixed(this.precision);
return +newValue;
},
/**
* Hide element
*
* @param element
* @returns {jqLite} The jqLite wrapped DOM element
*/
hideEl: function(element) {
return element.css({
opacity: 0
});
},
/**
* Show element
*
* @param element The jqLite wrapped DOM element
* @returns {jqLite} The jqLite
*/
showEl: function(element) {
if (!!element.rzAlwaysHide) {
return element;
}
return element.css({
opacity: 1
});
},
/**
* Set element left/top offset depending on whether slider is horizontal or vertical
*
* @param {jqLite} elem The jqLite wrapped DOM element
* @param {number} pos
* @returns {number}
*/
setPosition: function(elem, pos) {
elem.rzsp = pos;
var css = {};
css[this.positionProperty] = pos + 'px';
elem.css(css);
return pos;
},
/**
* Get element width/height depending on whether slider is horizontal or vertical
*
* @param {jqLite} elem The jqLite wrapped DOM element
* @returns {number}
*/
getDimension: function(elem) {
var val = elem[0].getBoundingClientRect();
if (this.options.vertical)
elem.rzsd = (val.bottom - val.top) * this.options.scale;
else
elem.rzsd = (val.right - val.left) * this.options.scale;
return elem.rzsd;
},
/**
* Set element width/height depending on whether slider is horizontal or vertical
*
* @param {jqLite} elem The jqLite wrapped DOM element
* @param {number} dim
* @returns {number}
*/
setDimension: function(elem, dim) {
elem.rzsd = dim;
var css = {};
css[this.dimensionProperty] = dim + 'px';
elem.css(css);
return dim;
},
/**
* Translate value to pixel offset
*
* @param {number} val
* @returns {number}
*/
valueToOffset: function(val) {
if (this.options.rightToLeft) {
return (this.maxValue - this.sanitizeValue(val)) * this.maxPos / this.valueRange || 0;
}
return (this.sanitizeValue(val) - this.minValue) * this.maxPos / this.valueRange || 0;
},
/**
* Returns a value that is within slider range
*
* @param {number} val
* @returns {number}
*/
sanitizeValue: function(val) {
return Math.min(Math.max(val, this.minValue), this.maxValue);
},
/**
* Translate offset to model value
*
* @param {number} offset
* @returns {number}
*/
offsetToValue: function(offset) {
if (this.options.rightToLeft) {
return (1 - (offset / this.maxPos)) * this.valueRange + this.minValue;
}
return (offset / this.maxPos) * this.valueRange + this.minValue;
},
// Events
/**
* Get the X-coordinate or Y-coordinate of an event
*
* @param {Object} event The event
* @returns {number}
*/
getEventXY: function(event) {
/* http://stackoverflow.com/a/12336075/282882 */
//noinspection JSLint
var clientXY = this.options.vertical ? 'clientY' : 'clientX';
if (clientXY in event) {
return event[clientXY];
}
return event.originalEvent === undefined ?
event.touches[0][clientXY] : event.originalEvent.touches[0][clientXY];
},
/**
* Compute the event position depending on whether the slider is horizontal or vertical
* @param event
* @returns {number}
*/
getEventPosition: function(event) {
var sliderPos = this.sliderElem.rzsp,
eventPos = 0;
if (this.options.vertical)
eventPos = -this.getEventXY(event) + sliderPos;
else
eventPos = this.getEventXY(event) - sliderPos;
return (eventPos - this.handleHalfDim) * this.options.scale;
},
/**
* Get event names for move and event end
*
* @param {Event} event The event
*
* @return {{moveEvent: string, endEvent: string}}
*/
getEventNames: function(event) {
var eventNames = {
moveEvent: '',
endEvent: ''
};
if (event.touches || (event.originalEvent !== undefined && event.originalEvent.touches)) {
eventNames.moveEvent = 'touchmove';
eventNames.endEvent = 'touchend';
} else {
eventNames.moveEvent = 'mousemove';
eventNames.endEvent = 'mouseup';
}
return eventNames;
},
/**
* Get the handle closest to an event.
*
* @param event {Event} The event
* @returns {jqLite} The handle closest to the event.
*/
getNearestHandle: function(event) {
if (!this.range) {
return this.minH;
}
var offset = this.getEventPosition(event),
distanceMin = Math.abs(offset - this.minH.rzsp),
distanceMax = Math.abs(offset - this.maxH.rzsp);
if (distanceMin < distanceMax)
return this.minH;
else if (distanceMin > distanceMax)
return this.maxH;
else if (!this.options.rightToLeft)
//if event is at the same distance from min/max then if it's at left of minH, we return minH else maxH
return offset < this.minH.rzsp ? this.minH : this.maxH;
else
//reverse in rtl
return offset > this.minH.rzsp ? this.minH : this.maxH;
},
/**
* Wrapper function to focus an angular element
*
* @param el {AngularElement} the element to focus
*/
focusElement: function(el) {
var DOM_ELEMENT = 0;
el[DOM_ELEMENT].focus();
},
/**
* Bind mouse and touch events to slider handles
*
* @returns {undefined}
*/
bindEvents: function() {
var barTracking, barStart, barMove;
if (this.options.draggableRange) {
barTracking = 'rzSliderDrag';
barStart = this.onDragStart;
barMove = this.onDragMove;
} else {
barTracking = 'rzSliderModel';
barStart = this.onStart;
barMove = this.onMove;
}
if (!this.options.onlyBindHandles) {
this.selBar.on('mousedown', angular.bind(this, barStart, null, barTracking));
this.selBar.on('mousedown', angular.bind(this, barMove, this.selBar));
}
if (this.options.draggableRangeOnly) {
this.minH.on('mousedown', angular.bind(this, barStart, null, barTracking));
this.maxH.on('mousedown', angular.bind(this, barStart, null, barTracking));
} else {
this.minH.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
if (this.range) {
this.maxH.on('mousedown', angular.bind(this, this.onStart, this.maxH, 'rzSliderHigh'));
}
if (!this.options.onlyBindHandles) {
this.fullBar.on('mousedown', angular.bind(this, this.onStart, null, null));
this.fullBar.on('mousedown', angular.bind(this, this.onMove, this.fullBar));
this.ticks.on('mousedown', angular.bind(this, this.onStart, null, null));
this.ticks.on('mousedown', angular.bind(this, this.onMove, this.ticks));
}
}
if (!this.options.onlyBindHandles) {
this.selBar.on('touchstart', angular.bind(this, barStart, null, barTracking));
this.selBar.on('touchstart', angular.bind(this, barMove, this.selBar));
}
if (this.options.draggableRangeOnly) {
this.minH.on('touchstart', angular.bind(this, barStart, null, barTracking));
this.maxH.on('touchstart', angular.bind(this, barStart, null, barTracking));
} else {
this.minH.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
if (this.range) {
this.maxH.on('touchstart', angular.bind(this, this.onStart, this.maxH, 'rzSliderHigh'));
}
if (!this.options.onlyBindHandles) {
this.fullBar.on('touchstart', angular.bind(this, this.onStart, null, null));
this.fullBar.on('touchstart', angular.bind(this, this.onMove, this.fullBar));
this.ticks.on('touchstart', angular.bind(this, this.onStart, null, null));
this.ticks.on('touchstart', angular.bind(this, this.onMove, this.ticks));
}
}
if (this.options.keyboardSupport) {
this.minH.on('focus', angular.bind(this, this.onPointerFocus, this.minH, 'rzSliderModel'));
if (this.range) {
this.maxH.on('focus', angular.bind(this, this.onPointerFocus, this.maxH, 'rzSliderHigh'));
}
}
},
/**
* Unbind mouse and touch events to slider handles
*
* @returns {undefined}
*/
unbindEvents: function() {
this.minH.off();
this.maxH.off();
this.fullBar.off();
this.selBar.off();
this.ticks.off();
},
/**
* onStart event handler
*
* @param {?Object} pointer The jqLite wrapped DOM element; if null, the closest handle is used
* @param {?string} ref The name of the handle being changed; if null, the closest handle's value is modified
* @param {Event} event The event
* @returns {undefined}
*/
onStart: function(pointer, ref, event) {
var ehMove, ehEnd,
eventNames = this.getEventNames(event);
event.stopPropagation();
event.preventDefault();
// We have to do this in case the HTML where the sliders are on
// have been animated into view.
this.calcViewDimensions();
if (pointer) {
this.tracking = ref;
} else {
pointer = this.getNearestHandle(event);
this.tracking = pointer === this.minH ? 'rzSliderModel' : 'rzSliderHigh';
}
pointer.addClass('rz-active');
if (this.options.keyboardSupport)
this.focusElement(pointer);
ehMove = angular.bind(this, this.dragging.active ? this.onDragMove : this.onMove, pointer);
ehEnd = angular.bind(this, this.onEnd, ehMove);
$document.on(eventNames.moveEvent, ehMove);
$document.one(eventNames.endEvent, ehEnd);
this.callOnStart();
},
/**
* onMove event handler
*
* @param {jqLite} pointer
* @param {Event} event The event
* @returns {undefined}
*/
onMove: function(pointer, event) {
var newOffset = this.getEventPosition(event),
newValue,
ceilValue = this.options.rightToLeft ? this.minValue : this.maxValue,
flrValue = this.options.rightToLeft ? this.maxValue : this.minValue;
if (newOffset <= 0) {
newValue = flrValue;
} else if (newOffset >= this.maxPos) {
newValue = ceilValue;
} else {
newValue = this.offsetToValue(newOffset);
newValue = this.roundStep(newValue);
}
this.positionTrackingHandle(newValue);
},
/**
* onEnd event handler
*
* @param {Event} event The event
* @param {Function} ehMove The the bound move event handler
* @returns {undefined}
*/
onEnd: function(ehMove, event) {
var moveEventName = this.getEventNames(event).moveEvent;
if (!this.options.keyboardSupport) {
this.minH.removeClass('rz-active');
this.maxH.removeClass('rz-active');
this.tracking = '';
}
this.dragging.active = false;
$document.off(moveEventName, ehMove);
this.scope.$emit('slideEnded');
this.callOnEnd();
},
onPointerFocus: function(pointer, ref) {
this.tracking = ref;
pointer.one('blur', angular.bind(this, this.onPointerBlur, pointer));
pointer.on('keydown', angular.bind(this, this.onKeyboardEvent));
pointer.addClass('rz-active');
},
onPointerBlur: function(pointer) {
pointer.off('keydown');
this.tracking = '';
pointer.removeClass('rz-active');
},
/**
* Key actions helper function
*
* @param {number} currentValue value of the slider
*
* @returns {?Object} action value mappings
*/
getKeyActions: function(currentValue) {
var increaseStep = currentValue + this.step,
decreaseStep = currentValue - this.step,
increasePage = currentValue + this.valueRange / 10,
decreasePage = currentValue - this.valueRange / 10;
//Left to right default actions
var actions = {
'UP': increaseStep,
'DOWN': decreaseStep,
'LEFT': decreaseStep,
'RIGHT': increaseStep,
'PAGEUP': increasePage,
'PAGEDOWN': decreasePage,
'HOME': this.minValue,
'END': this.maxValue
};
//right to left means swapping right and left arrows
if (this.options.rightToLeft) {
actions.LEFT = increaseStep;
actions.RIGHT = decreaseStep;
// right to left and vertical means we also swap up and down
if (this.options.vertical) {
actions.UP = decreaseStep;
actions.DOWN = increaseStep;
}
}
return actions;
},
onKeyboardEvent: function(event) {
var currentValue = this.scope[this.tracking],
keyCode = event.keyCode || event.which,
keys = {
38: 'UP',
40: 'DOWN',
37: 'LEFT',
39: 'RIGHT',
33: 'PAGEUP',
34: 'PAGEDOWN',
36: 'HOME',
35: 'END'
},
actions = this.getKeyActions(currentValue),
key = keys[keyCode],
action = actions[key];
if (action == null || this.tracking === '') return;
event.preventDefault();
var newValue = this.roundStep(this.sanitizeValue(action));
if (!this.options.draggableRangeOnly) {
this.positionTrackingHandle(newValue);
} else {
var difference = this.scope.rzSliderHigh - this.scope.rzSliderModel,
newMinValue, newMaxValue;
if (this.tracking === 'rzSliderModel') {
newMinValue = newValue;
newMaxValue = newValue + difference;
if (newMaxValue > this.maxValue) {
newMaxValue = this.maxValue;
newMinValue = newMaxValue - difference;
}
} else {
newMaxValue = newValue;
newMinValue = newValue - difference;
if (newMinValue < this.minValue) {
newMinValue = this.minValue;
newMaxValue = newMinValue + difference;
}
}
this.positionTrackingBar(newMinValue, newMaxValue);
}
},
/**
* onDragStart event handler
*
* Handles dragging of the middle bar.
*
* @param {Object} pointer The jqLite wrapped DOM element
* @param {string} ref One of the refLow, refHigh values
* @param {Event} event The event
* @returns {undefined}
*/
onDragStart: function(pointer, ref, event) {
var offset = this.getEventPosition(event);
this.dragging = {
active: true,
value: this.offsetToValue(offset),
difference: this.scope.rzSliderHigh - this.scope.rzSliderModel,
lowLimit: this.options.rightToLeft ? this.minH.rzsp - offset : offset - this.minH.rzsp,
highLimit: this.options.rightToLeft ? offset - this.maxH.rzsp : this.maxH.rzsp - offset
};
this.onStart(pointer, ref, event);
},
/**
* getValue helper function
*
* gets max or min value depending on whether the newOffset is outOfBounds above or below the bar and rightToLeft
*
* @param {string} type 'max' || 'min' The value we are calculating
* @param {number} newOffset The new offset
* @param {boolean} outOfBounds Is the new offset above or below the max/min?
* @param {boolean} isAbove Is the new offset above the bar if out of bounds?
*
* @returns {number}
*/
getValue: function(type, newOffset, outOfBounds, isAbove) {
var isRTL = this.options.rightToLeft,
value = null;
if (type === 'min') {
if (outOfBounds) {
if (isAbove) {
value = isRTL ? value : this.maxValue - this.dragging.difference;
} else {
value = isRTL ? this.maxValue - this.dragging.difference : value;
}
} else {
value = isRTL ? this.offsetToValue(newOffset + this.dragging.lowLimit) : this.offsetToValue(newOffset - this.dragging.lowLimit)
}
} else {
if (outOfBounds) {
if (isAbove) {
value = isRTL ? this.minValue + this.dragging.difference : this.maxValue;
} else {
value = isRTL ? this.maxValue : this.minValue + this.dragging.difference;
}
} else {
if (isRTL) {
value = this.offsetToValue(newOffset + this.dragging.lowLimit) + this.dragging.difference
} else {
value = this.offsetToValue(newOffset - this.dragging.lowLimit) + this.dragging.difference;
}
}
}
return this.roundStep(value);
},
/**
* onDragMove event handler
*
* Handles dragging of the middle bar.
*
* @param {jqLite} pointer
* @param {Event} event The event
* @returns {undefined}
*/
onDragMove: function(pointer, event) {
var newOffset = this.getEventPosition(event),
newMinValue, newMaxValue,
ceilLimit, flrLimit,
isUnderFlrLimit, isOverCeilLimit,
flrH, ceilH;
if (this.options.rightToLeft) {
ceilLimit = this.dragging.lowLimit;
flrLimit = this.dragging.highLimit;
flrH = this.maxH;
ceilH = this.minH;
} else {
ceilLimit = this.dragging.highLimit;
flrLimit = this.dragging.lowLimit;
flrH = this.minH;
ceilH = this.maxH;
}
isUnderFlrLimit = newOffset <= flrLimit;
isOverCeilLimit = newOffset >= this.maxPos - ceilLimit;
if (isUnderFlrLimit) {
if (flrH.rzsp === 0)
return;
newMinValue = this.getValue('min', newOffset, true, false);
newMaxValue = this.getValue('max', newOffset, true, false);
} else if (isOverCeilLimit) {
if (ceilH.rzsp === this.maxPos)
return;
newMaxValue = this.getValue('max', newOffset, true, true);
newMinValue = this.getValue('min', newOffset, true, true);
} else {
newMinValue = this.getValue('min', newOffset, false);
newMaxValue = this.getValue('max', newOffset, false);
}
this.positionTrackingBar(newMinValue, newMaxValue);
},
/**
* Set the new value and offset for the entire bar
*
* @param {number} newMinValue the new minimum value
* @param {number} newMaxValue the new maximum value
*/
positionTrackingBar: function(newMinValue, newMaxValue) {
this.scope.rzSliderModel = newMinValue;
this.scope.rzSliderHigh = newMaxValue;
this.updateHandles('rzSliderModel', this.valueToOffset(newMinValue));
this.updateHandles('rzSliderHigh', this.valueToOffset(newMaxValue));
this.applyModel();
},
/**
* Set the new value and offset to the current tracking handle
*
* @param {number} newValue new model value
*/
positionTrackingHandle: function(newValue) {
var valueChanged = false;
if (this.range) {
newValue = this.applyMinRange(newValue);
/* This is to check if we need to switch the min and max handles */
if (this.tracking === 'rzSliderModel' && newValue > this.scope.rzSliderHigh) {
if (this.options.noSwitching && this.scope.rzSliderHigh !== this.minValue) {
newValue = this.applyMinRange(this.scope.rzSliderHigh);
}
else {
this.scope[this.tracking] = this.scope.rzSliderHigh;
this.updateHandles(this.tracking, this.maxH.rzsp);
this.updateAriaAttributes();
this.tracking = 'rzSliderHigh';
this.minH.removeClass('rz-active');
this.maxH.addClass('rz-active');
if (this.options.keyboardSupport)
this.focusElement(this.maxH);
}
valueChanged = true;
} else if (this.tracking === 'rzSliderHigh' && newValue < this.scope.rzSliderModel) {
if (this.options.noSwitching && this.scope.rzSliderModel !== this.maxValue) {
newValue = this.applyMinRange(this.scope.rzSliderModel);
}
else {
this.scope[this.tracking] = this.scope.rzSliderModel;
this.updateHandles(this.tracking, this.minH.rzsp);
this.updateAriaAttributes();
this.tracking = 'rzSliderModel';
this.maxH.removeClass('rz-active');
this.minH.addClass('rz-active');
if (this.options.keyboardSupport)
this.focusElement(this.minH);
}
valueChanged = true;
}
}
if (this.scope[this.tracking] !== newValue) {
this.scope[this.tracking] = newValue;
this.updateHandles(this.tracking, this.valueToOffset(newValue));
this.updateAriaAttributes();
valueChanged = true;
}
if (valueChanged)
this.applyModel();
},
applyMinRange: function(newValue) {
if (this.options.minRange !== 0) {
var oppositeValue = this.tracking === 'rzSliderModel' ? this.scope.rzSliderHigh : this.scope.rzSliderModel,
difference = Math.abs(newValue - oppositeValue);
if (difference < this.options.minRange) {
if (this.tracking === 'rzSliderModel')
return this.scope.rzSliderHigh - this.options.minRange;
else
return this.scope.rzSliderModel + this.options.minRange;
}
}
return newValue;
},
/**
* Apply the model values using scope.$apply.
* We wrap it with the internalChange flag to avoid the watchers to be called
*/
applyModel: function() {
this.internalChange = true;
this.scope.$apply();
this.callOnChange();
this.internalChange = false;
},
/**
* Call the onStart callback if defined
* The callback call is wrapped in a $evalAsync to ensure that its result will be applied to the scope.
*
* @returns {undefined}
*/
callOnStart: function() {
if (this.options.onStart) {
var self = this;
this.scope.$evalAsync(function() {
self.options.onStart(self.options.id, self.scope.rzSliderModel, self.scope.rzSliderHigh);
});
}
},
/**
* Call the onChange callback if defined
* The callback call is wrapped in a $evalAsync to ensure that its result will be applied to the scope.
*
* @returns {undefined}
*/
callOnChange: function() {
if (this.options.onChange) {
var self = this;
this.scope.$evalAsync(function() {
self.options.onChange(self.options.id, self.scope.rzSliderModel, self.scope.rzSliderHigh);
});
}
},
/**
* Call the onEnd callback if defined
* The callback call is wrapped in a $evalAsync to ensure that its result will be applied to the scope.
*
* @returns {undefined}
*/
callOnEnd: function() {
if (this.options.onEnd) {
var self = this;
this.scope.$evalAsync(function() {
self.options.onEnd(self.options.id, self.scope.rzSliderModel, self.scope.rzSliderHigh);
});
}
}
};
return Slider;
}])
.directive('rzslider', ['RzSlider', function(RzSlider) {
'use strict';
return {
restrict: 'E',
scope: {
rzSliderModel: '=?',
rzSliderHigh: '=?',
rzSliderOptions: '&?',
rzSliderTplUrl: '@'
},
/**
* Return template URL
*
* @param {jqLite} elem
* @param {Object} attrs
* @return {string}
*/
templateUrl: function(elem, attrs) {
//noinspection JSUnresolvedVariable
return attrs.rzSliderTplUrl || 'rzSliderTpl.html';
},
link: function(scope, elem) {
scope.slider = new RzSlider(scope, elem); //attach on scope so we can test it
}
};
}]);
// IDE assist
/**
* @name ngScope
*
* @property {number} rzSliderModel
* @property {number} rzSliderHigh
* @property {Object} rzSliderOptions
*/
/**
* @name jqLite
*
* @property {number|undefined} rzsp rzslider label position offset
* @property {number|undefined} rzsd rzslider element dimension
* @property {string|undefined} rzsv rzslider label value/text
* @property {Function} css
* @property {Function} text
*/
/**
* @name Event
* @property {Array} touches
* @property {Event} originalEvent
*/
/**
* @name ThrottleOptions
*
* @property {boolean} leading
* @property {boolean} trailing
*/
module.run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('rzSliderTpl.html',
"<span class=rz-bar-wrapper><span class=rz-bar></span></span> <span class=rz-bar-wrapper><span class=\"rz-bar rz-selection\" ng-style=barStyle></span></span> <span class=\"rz-pointer rz-pointer-min\" ng-style=minPointerStyle></span> <span class=\"rz-pointer rz-pointer-max\" ng-style=maxPointerStyle></span> <span class=\"rz-bubble rz-limit\"></span> <span class=\"rz-bubble rz-limit\"></span> <span class=rz-bubble></span> <span class=rz-bubble></span> <span class=rz-bubble></span><ul ng-show=showTicks class=rz-ticks><li ng-repeat=\"t in ticks track by $index\" class=tick ng-class=\"{selected: t.selected}\" ng-style=t.style ng-attr-uib-tooltip=\"{{ t.tooltip }}\" ng-attr-tooltip-placement={{t.tooltipPlacement}} ng-attr-tooltip-append-to-body=\"{{ t.tooltip ? true : undefined}}\"><span ng-if=\"t.value != null\" class=tick-value ng-attr-uib-tooltip=\"{{ t.valueTooltip }}\" ng-attr-tooltip-placement={{t.valueTooltipPlacement}}>{{ t.value }}</span></li></ul>"
);
}]);
return module
}));
/*! angularjs-slider - v2.9.0 - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - https://github.com/angular-slider/angularjs-slider - 2016-02-29 */
/*! angularjs-slider - v2.10.0 - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - https://github.com/angular-slider/angularjs-slider - 2016-02-29 */
rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:35px 0 15px 0;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}rzslider[disabled]{cursor:not-allowed}rzslider[disabled] .rz-pointer{cursor:not-allowed;background-color:#d8e0f3}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider .rz-base{width:100%;height:100%;padding:0}rzslider .rz-bar-wrapper{left:0;z-index:1;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider .rz-bar-wrapper.rz-draggable{cursor:move}rzslider .rz-bar{left:0;z-index:1;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-bar.rz-selection{z-index:2;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider .rz-pointer{top:-14px;z-index:3;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider .rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider .rz-pointer:hover:after{background-color:#fff}rzslider .rz-pointer.rz-active{z-index:4}rzslider .rz-pointer.rz-active:after{background-color:#451aff}rzslider .rz-bubble{bottom:16px;padding:1px 3px;color:#55637d;cursor:default}rzslider .rz-bubble.rz-selection{top:16px}rzslider .rz-bubble.rz-limit{color:#55637d}rzslider .rz-ticks{position:absolute;top:-3px;left:0;z-index:1;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:0;padding:0 11px;margin:0;list-style:none;box-sizing:border-box;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}rzslider .rz-ticks .tick{width:10px;height:10px;text-align:center;cursor:pointer;background:#d8e0f3;border-radius:50%}rzslider .rz-ticks .tick.selected{background:#0db9f0}rzslider .rz-ticks .tick .tick-value{position:absolute;top:-30px;transform:translate(-50%,0)}rzslider.vertical{position:relative;width:4px;height:100%;padding:0;margin:0 20px;vertical-align:baseline}rzslider.vertical .rz-base{width:100%;height:100%;padding:0}rzslider.vertical .rz-bar-wrapper{top:auto;left:0;width:32px;height:100%;padding:0 0 0 16px;margin:0 0 0 -16px}rzslider.vertical .rz-bar{bottom:0;left:auto;width:4px;height:100%}rzslider.vertical .rz-pointer{top:auto;bottom:0;left:-14px!important}rzslider.vertical .rz-bubble{bottom:0;left:16px!important;margin-left:3px}rzslider.vertical .rz-bubble.rz-selection{top:auto;left:16px!important}rzslider.vertical .rz-ticks{top:0;left:-3px;z-index:1;width:0;height:100%;padding:11px 0;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}rzslider.vertical .rz-ticks .tick{vertical-align:middle}rzslider.vertical .rz-ticks .tick .tick-value{top:auto;right:-30px;transform:translate(0,-28%)}
\ No newline at end of file
/*! angularjs-slider - v2.9.0 - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - https://github.com/angular-slider/angularjs-slider - 2016-02-29 */
/*! angularjs-slider - v2.10.0 - (c) Rafal Zajac <rzajac@gmail.com>, Valentin Hervieu <valentin@hervieu.me>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com> - https://github.com/angular-slider/angularjs-slider - 2016-02-29 */
!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):"object"==typeof module&&module.exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){"use strict";var b=a.module("rzModule",[]).factory("RzSliderOptions",function(){var b={floor:0,ceil:null,step:1,precision:0,minRange:0,id:null,translate:null,stepsArray:null,draggableRange:!1,draggableRangeOnly:!1,showSelectionBar:!1,showSelectionBarEnd:!1,showSelectionBarFromValue:null,hideLimitLabels:!1,readOnly:!1,disabled:!1,interval:350,showTicks:!1,showTicksValues:!1,ticksTooltip:null,ticksValuesTooltip:null,vertical:!1,getSelectionBarColor:null,getPointerColor:null,keyboardSupport:!0,scale:1,enforceStep:!0,enforceRange:!1,noSwitching:!1,onlyBindHandles:!1,onStart:null,onChange:null,onEnd:null,rightToLeft:!1},c={},d={};return d.options=function(b){a.extend(c,b)},d.getOptions=function(d){return a.extend({},b,c,d)},d}).factory("rzThrottle",["$timeout",function(a){return function(b,c,d){var e,f,g,h=Date.now||function(){return(new Date).getTime()},i=null,j=0;d=d||{};var k=function(){j=h(),i=null,g=b.apply(e,f),e=f=null};return function(){var l=h(),m=c-(l-j);return e=this,f=arguments,0>=m?(a.cancel(i),i=null,j=l,g=b.apply(e,f),e=f=null):i||d.trailing===!1||(i=a(k,m)),g}}}]).factory("RzSlider",["$timeout","$document","$window","$compile","RzSliderOptions","rzThrottle",function(b,c,d,e,f,g){var h=function(a,b){this.scope=a,this.sliderElem=b,this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.dragging={active:!1,value:0,difference:0,offset:0,lowLimit:0,highLimit:0},this.positionProperty="left",this.dimensionProperty="width",this.handleHalfDim=0,this.maxPos=0,this.precision=0,this.step=1,this.tracking="",this.minValue=0,this.maxValue=0,this.valueRange=0,this.initHasRun=!1,this.internalChange=!1,this.fullBar=null,this.selBar=null,this.minH=null,this.maxH=null,this.flrLab=null,this.ceilLab=null,this.minLab=null,this.maxLab=null,this.cmbLab=null,this.ticks=null,this.init()};return h.prototype={init:function(){var b,c,e=this,f=function(){e.calcViewDimensions()};this.applyOptions(),this.initElemHandles(),this.manageElementsStyle(),this.setDisabledState(),this.calcViewDimensions(),this.setMinAndMax(),this.addAccessibility(),this.updateCeilLab(),this.updateFloorLab(),this.initHandles(),this.manageEventsBindings(),this.scope.$on("reCalcViewDimensions",f),a.element(d).on("resize",f),this.initHasRun=!0,b=g(function(){e.onLowHandleChange()},e.options.interval),c=g(function(){e.onHighHandleChange()},e.options.interval),this.scope.$on("rzSliderForceRender",function(){e.resetLabelsValue(),b(),e.range&&c(),e.resetSlider()}),this.scope.$watch("rzSliderOptions()",function(a,b){a!==b&&(e.applyOptions(),e.resetSlider())},!0),this.scope.$watch("rzSliderModel",function(a,c){e.internalChange||a!==c&&b()}),this.scope.$watch("rzSliderHigh",function(a,b){e.internalChange||a!==b&&(null!=a&&c(),(e.range&&null==a||!e.range&&null!=a)&&(e.applyOptions(),e.resetSlider()))}),this.scope.$on("$destroy",function(){e.unbindEvents(),a.element(d).off("resize",f)})},onLowHandleChange:function(){this.setMinAndMax(),this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.updateSelectionBar(),this.updateTicksScale(),this.updateAriaAttributes(),this.range&&this.updateCmbLabel()},onHighHandleChange:function(){this.setMinAndMax(),this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateSelectionBar(),this.updateTicksScale(),this.updateCmbLabel(),this.updateAriaAttributes()},applyOptions:function(){var a;a=this.scope.rzSliderOptions?this.scope.rzSliderOptions():{},this.options=f.getOptions(a),this.options.step<=0&&(this.options.step=1),this.range=void 0!==this.scope.rzSliderModel&&void 0!==this.scope.rzSliderHigh,this.options.draggableRange=this.range&&this.options.draggableRange,this.options.draggableRangeOnly=this.range&&this.options.draggableRangeOnly,this.options.draggableRangeOnly&&(this.options.draggableRange=!0),this.options.showTicks=this.options.showTicks||this.options.showTicksValues,this.scope.showTicks=this.options.showTicks,this.options.showSelectionBar=this.options.showSelectionBar||this.options.showSelectionBarEnd||null!==this.options.showSelectionBarFromValue,this.options.stepsArray?(this.options.floor=0,this.options.ceil=this.options.stepsArray.length-1,this.options.step=1,this.customTrFn=function(a){return this.options.stepsArray[a]}):this.options.translate?this.customTrFn=this.options.translate:this.customTrFn=function(a){return String(a)},this.options.vertical&&(this.positionProperty="bottom",this.dimensionProperty="height")},resetSlider:function(){this.manageElementsStyle(),this.addAccessibility(),this.setMinAndMax(),this.updateCeilLab(),this.updateFloorLab(),this.unbindEvents(),this.manageEventsBindings(),this.setDisabledState(),this.calcViewDimensions()},initElemHandles:function(){a.forEach(this.sliderElem.children(),function(b,c){var d=a.element(b);switch(c){case 0:this.fullBar=d;break;case 1:this.selBar=d;break;case 2:this.minH=d;break;case 3:this.maxH=d;break;case 4:this.flrLab=d;break;case 5:this.ceilLab=d;break;case 6:this.minLab=d;break;case 7:this.maxLab=d;break;case 8:this.cmbLab=d;break;case 9:this.ticks=d}},this),this.selBar.rzsp=0,this.minH.rzsp=0,this.maxH.rzsp=0,this.flrLab.rzsp=0,this.ceilLab.rzsp=0,this.minLab.rzsp=0,this.maxLab.rzsp=0,this.cmbLab.rzsp=0},manageElementsStyle:function(){this.range?this.maxH.css("display",""):this.maxH.css("display","none"),this.alwaysHide(this.flrLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.ceilLab,this.options.showTicksValues||this.options.hideLimitLabels),this.alwaysHide(this.minLab,this.options.showTicksValues),this.alwaysHide(this.maxLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.cmbLab,this.options.showTicksValues||!this.range),this.alwaysHide(this.selBar,!this.range&&!this.options.showSelectionBar),this.options.vertical&&this.sliderElem.addClass("vertical"),this.options.draggableRange?this.selBar.addClass("rz-draggable"):this.selBar.removeClass("rz-draggable")},alwaysHide:function(a,b){a.rzAlwaysHide=b,b?this.hideEl(a):this.showEl(a)},manageEventsBindings:function(){this.options.disabled||this.options.readOnly?this.unbindEvents():this.bindEvents()},setDisabledState:function(){this.options.disabled?this.sliderElem.attr("disabled","disabled"):this.sliderElem.attr("disabled",null)},resetLabelsValue:function(){this.minLab.rzsv=void 0,this.maxLab.rzsv=void 0},initHandles:function(){this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.range&&this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateSelectionBar(),this.range&&this.updateCmbLabel(),this.updateTicksScale()},translateFn:function(a,b,c,d){d=void 0===d?!0:d;var e=String(d?this.customTrFn(a,this.options.id,c):a),f=!1;(void 0===b.rzsv||b.rzsv.length!==e.length||b.rzsv.length>0&&0===b.rzsd)&&(f=!0,b.rzsv=e),b.html(e),f&&this.getDimension(b)},setMinAndMax:function(){this.step=+this.options.step,this.precision=+this.options.precision,this.minValue=this.options.floor,this.options.enforceStep&&(this.scope.rzSliderModel=this.roundStep(this.scope.rzSliderModel),this.range&&(this.scope.rzSliderHigh=this.roundStep(this.scope.rzSliderHigh))),null!=this.options.ceil?this.maxValue=this.options.ceil:this.maxValue=this.options.ceil=this.range?this.scope.rzSliderHigh:this.scope.rzSliderModel,this.options.enforceRange&&(this.scope.rzSliderModel=this.sanitizeValue(this.scope.rzSliderModel),this.range&&(this.scope.rzSliderHigh=this.sanitizeValue(this.scope.rzSliderHigh))),this.valueRange=this.maxValue-this.minValue},addAccessibility:function(){this.minH.attr("role","slider"),this.updateAriaAttributes(),!this.options.keyboardSupport||this.options.readOnly||this.options.disabled?this.minH.attr("tabindex",""):this.minH.attr("tabindex","0"),this.options.vertical&&this.minH.attr("aria-orientation","vertical"),this.range&&(this.maxH.attr("role","slider"),!this.options.keyboardSupport||this.options.readOnly||this.options.disabled?this.maxH.attr("tabindex",""):this.maxH.attr("tabindex","0"),this.options.vertical&&this.maxH.attr("aria-orientation","vertical"))},updateAriaAttributes:function(){this.minH.attr({"aria-valuenow":this.scope.rzSliderModel,"aria-valuetext":this.customTrFn(this.scope.rzSliderModel,this.options.id,"model"),"aria-valuemin":this.minValue,"aria-valuemax":this.maxValue}),this.range&&this.maxH.attr({"aria-valuenow":this.scope.rzSliderHigh,"aria-valuetext":this.customTrFn(this.scope.rzSliderHigh,this.options.id,"high"),"aria-valuemin":this.minValue,"aria-valuemax":this.maxValue})},calcViewDimensions:function(){var a=this.getDimension(this.minH);this.handleHalfDim=a/2,this.barDimension=this.getDimension(this.fullBar),this.maxPos=this.barDimension-a,this.getDimension(this.sliderElem),this.sliderElem.rzsp=this.sliderElem[0].getBoundingClientRect()[this.positionProperty],this.initHasRun&&(this.updateFloorLab(),this.updateCeilLab(),this.initHandles())},updateTicksScale:function(){if(this.options.showTicks){var a=Math.round((this.maxValue-this.minValue)/this.step)+1;this.scope.ticks=[];for(var b=0;a>b;b++){var c=this.roundStep(this.minValue+b*this.step),d={selected:this.isTickSelected(c)};d.selected&&this.options.getSelectionBarColor&&(d.style={"background-color":this.getSelectionBarColor()}),this.options.ticksTooltip&&(d.tooltip=this.options.ticksTooltip(c),d.tooltipPlacement=this.options.vertical?"right":"top"),this.options.showTicksValues&&(d.value=this.getDisplayValue(c,"tick-value"),this.options.ticksValuesTooltip&&(d.valueTooltip=this.options.ticksValuesTooltip(c),d.valueTooltipPlacement=this.options.vertical?"right":"top")),this.options.rightToLeft?this.scope.ticks.unshift(d):this.scope.ticks.push(d)}}},isTickSelected:function(a){if(!this.range)if(null!==this.options.showSelectionBarFromValue){var b=this.options.showSelectionBarFromValue;if(this.scope.rzSliderModel>b&&a>=b&&a<=this.scope.rzSliderModel)return!0;if(this.scope.rzSliderModel<b&&b>=a&&a>=this.scope.rzSliderModel)return!0}else if(this.options.showSelectionBarEnd){if(a>=this.scope.rzSliderModel)return!0}else if(this.options.showSelectionBar&&a<=this.scope.rzSliderModel)return!0;return this.range&&a>=this.scope.rzSliderModel&&a<=this.scope.rzSliderHigh?!0:!1},updateFloorLab:function(){this.translateFn(this.minValue,this.flrLab,"floor"),this.getDimension(this.flrLab);var a=this.options.rightToLeft?this.barDimension-this.flrLab.rzsd:0;this.setPosition(this.flrLab,a)},updateCeilLab:function(){this.translateFn(this.maxValue,this.ceilLab,"ceil"),this.getDimension(this.ceilLab);var a=this.options.rightToLeft?0:this.barDimension-this.ceilLab.rzsd;this.setPosition(this.ceilLab,a)},updateHandles:function(a,b){"rzSliderModel"===a?this.updateLowHandle(b):this.updateHighHandle(b),this.updateSelectionBar(),this.updateTicksScale(),this.range&&this.updateCmbLabel()},getHandleLabelPos:function(a,b){var c=this[a].rzsd,d=b-c/2+this.handleHalfDim,e=this.barDimension-c;return this.options.rightToLeft&&"minLab"===a||!this.options.rightToLeft&&"maxLab"===a?Math.min(d,e):Math.min(Math.max(d,0),e)},updateLowHandle:function(a){if(this.setPosition(this.minH,a),this.translateFn(this.scope.rzSliderModel,this.minLab,"model"),this.setPosition(this.minLab,this.getHandleLabelPos("minLab",a)),this.options.getPointerColor){var b=this.getPointerColor("min");this.scope.minPointerStyle={backgroundColor:b}}this.shFloorCeil()},updateHighHandle:function(a){if(this.setPosition(this.maxH,a),this.translateFn(this.scope.rzSliderHigh,this.maxLab,"high"),this.setPosition(this.maxLab,this.getHandleLabelPos("maxLab",a)),this.options.getPointerColor){var b=this.getPointerColor("max");this.scope.maxPointerStyle={backgroundColor:b}}this.shFloorCeil()},shFloorCeil:function(){var a=!1,b=!1,c=this.options.rightToLeft,d=this.flrLab.rzsp,e=this.flrLab.rzsd,f=this.minLab.rzsp,g=this.minLab.rzsd,h=this.maxLab.rzsp,i=this.maxLab.rzsd,j=this.ceilLab.rzsp,k=this.handleHalfDim,l=c?f+g>=d-e-5:d+e+5>=f,m=c?j+k+10>=f-g:f+g>=j-k-10,n=c?h>=d-e-k:d+e+k>=h,o=c?j+10>=h-i:h+i>=j-10;l?(a=!0,this.hideEl(this.flrLab)):(a=!1,this.showEl(this.flrLab)),m?(b=!0,this.hideEl(this.ceilLab)):(b=!1,this.showEl(this.ceilLab)),this.range&&(o?this.hideEl(this.ceilLab):b||this.showEl(this.ceilLab),n?this.hideEl(this.flrLab):a||this.showEl(this.flrLab))},updateSelectionBar:function(){var a=0,b=0,c=this.options.rightToLeft?!this.options.showSelectionBarEnd:this.options.showSelectionBarEnd,d=this.options.rightToLeft?this.maxH.rzsp+this.handleHalfDim:this.minH.rzsp+this.handleHalfDim;if(this.range)b=Math.abs(this.maxH.rzsp-this.minH.rzsp),a=d;else if(null!==this.options.showSelectionBarFromValue){var e=this.options.showSelectionBarFromValue,f=this.valueToOffset(e),g=this.options.rightToLeft?this.scope.rzSliderModel<=e:this.scope.rzSliderModel>e;g?(b=this.minH.rzsp-f,a=f+this.handleHalfDim):(b=f-this.minH.rzsp,a=this.minH.rzsp+this.handleHalfDim)}else c?(b=Math.abs(this.maxPos-this.minH.rzsp)+this.handleHalfDim,a=this.minH.rzsp+this.handleHalfDim):(b=Math.abs(this.maxH.rzsp-this.minH.rzsp)+this.handleHalfDim,a=0);if(this.setDimension(this.selBar,b),this.setPosition(this.selBar,a),this.options.getSelectionBarColor){var h=this.getSelectionBarColor();this.scope.barStyle={backgroundColor:h}}},getSelectionBarColor:function(){return this.range?this.options.getSelectionBarColor(this.scope.rzSliderModel,this.scope.rzSliderHigh):this.options.getSelectionBarColor(this.scope.rzSliderModel)},getPointerColor:function(a){return"max"===a?this.options.getPointerColor(this.scope.rzSliderHigh,a):this.options.getPointerColor(this.scope.rzSliderModel,a)},updateCmbLabel:function(){var a=null;if(a=this.options.rightToLeft?this.minLab.rzsp-this.minLab.rzsd-10<=this.maxLab.rzsp:this.minLab.rzsp+this.minLab.rzsd+10>=this.maxLab.rzsp){var b=this.getDisplayValue(this.scope.rzSliderModel,"model"),c=this.getDisplayValue(this.scope.rzSliderHigh,"high"),d="";d=b===c?b:this.options.rightToLeft?c+" - "+b:b+" - "+c,this.translateFn(d,this.cmbLab,"cmb",!1);var e=Math.min(Math.max(this.selBar.rzsp+this.selBar.rzsd/2-this.cmbLab.rzsd/2,0),this.barDimension-this.cmbLab.rzsd);this.setPosition(this.cmbLab,e),this.hideEl(this.minLab),this.hideEl(this.maxLab),this.showEl(this.cmbLab)}else this.showEl(this.maxLab),this.showEl(this.minLab),this.hideEl(this.cmbLab)},getDisplayValue:function(a,b){return this.customTrFn(a,this.options.id,b)},roundStep:function(a){var b=parseFloat((a-this.minValue)/this.step).toPrecision(12);b=Math.round(b)*this.step;var c=(this.minValue+b).toFixed(this.precision);return+c},hideEl:function(a){return a.css({opacity:0})},showEl:function(a){return a.rzAlwaysHide?a:a.css({opacity:1})},setPosition:function(a,b){a.rzsp=b;var c={};return c[this.positionProperty]=b+"px",a.css(c),b},getDimension:function(a){var b=a[0].getBoundingClientRect();return this.options.vertical?a.rzsd=(b.bottom-b.top)*this.options.scale:a.rzsd=(b.right-b.left)*this.options.scale,a.rzsd},setDimension:function(a,b){a.rzsd=b;var c={};return c[this.dimensionProperty]=b+"px",a.css(c),b},valueToOffset:function(a){return this.options.rightToLeft?(this.maxValue-this.sanitizeValue(a))*this.maxPos/this.valueRange||0:(this.sanitizeValue(a)-this.minValue)*this.maxPos/this.valueRange||0},sanitizeValue:function(a){return Math.min(Math.max(a,this.minValue),this.maxValue)},offsetToValue:function(a){return this.options.rightToLeft?(1-a/this.maxPos)*this.valueRange+this.minValue:a/this.maxPos*this.valueRange+this.minValue},getEventXY:function(a){var b=this.options.vertical?"clientY":"clientX";return b in a?a[b]:void 0===a.originalEvent?a.touches[0][b]:a.originalEvent.touches[0][b]},getEventPosition:function(a){var b=this.sliderElem.rzsp,c=0;return c=this.options.vertical?-this.getEventXY(a)+b:this.getEventXY(a)-b,(c-this.handleHalfDim)*this.options.scale},getEventNames:function(a){var b={moveEvent:"",endEvent:""};return a.touches||void 0!==a.originalEvent&&a.originalEvent.touches?(b.moveEvent="touchmove",b.endEvent="touchend"):(b.moveEvent="mousemove",b.endEvent="mouseup"),b},getNearestHandle:function(a){if(!this.range)return this.minH;var b=this.getEventPosition(a),c=Math.abs(b-this.minH.rzsp),d=Math.abs(b-this.maxH.rzsp);return d>c?this.minH:c>d?this.maxH:this.options.rightToLeft?b>this.minH.rzsp?this.minH:this.maxH:b<this.minH.rzsp?this.minH:this.maxH},focusElement:function(a){var b=0;a[b].focus()},bindEvents:function(){var b,c,d;this.options.draggableRange?(b="rzSliderDrag",c=this.onDragStart,d=this.onDragMove):(b="rzSliderModel",c=this.onStart,d=this.onMove),this.options.onlyBindHandles||(this.selBar.on("mousedown",a.bind(this,c,null,b)),this.selBar.on("mousedown",a.bind(this,d,this.selBar))),this.options.draggableRangeOnly?(this.minH.on("mousedown",a.bind(this,c,null,b)),this.maxH.on("mousedown",a.bind(this,c,null,b))):(this.minH.on("mousedown",a.bind(this,this.onStart,this.minH,"rzSliderModel")),this.range&&this.maxH.on("mousedown",a.bind(this,this.onStart,this.maxH,"rzSliderHigh")),this.options.onlyBindHandles||(this.fullBar.on("mousedown",a.bind(this,this.onStart,null,null)),this.fullBar.on("mousedown",a.bind(this,this.onMove,this.fullBar)),this.ticks.on("mousedown",a.bind(this,this.onStart,null,null)),this.ticks.on("mousedown",a.bind(this,this.onMove,this.ticks)))),this.options.onlyBindHandles||(this.selBar.on("touchstart",a.bind(this,c,null,b)),this.selBar.on("touchstart",a.bind(this,d,this.selBar))),this.options.draggableRangeOnly?(this.minH.on("touchstart",a.bind(this,c,null,b)),this.maxH.on("touchstart",a.bind(this,c,null,b))):(this.minH.on("touchstart",a.bind(this,this.onStart,this.minH,"rzSliderModel")),this.range&&this.maxH.on("touchstart",a.bind(this,this.onStart,this.maxH,"rzSliderHigh")),this.options.onlyBindHandles||(this.fullBar.on("touchstart",a.bind(this,this.onStart,null,null)),this.fullBar.on("touchstart",a.bind(this,this.onMove,this.fullBar)),this.ticks.on("touchstart",a.bind(this,this.onStart,null,null)),this.ticks.on("touchstart",a.bind(this,this.onMove,this.ticks)))),this.options.keyboardSupport&&(this.minH.on("focus",a.bind(this,this.onPointerFocus,this.minH,"rzSliderModel")),this.range&&this.maxH.on("focus",a.bind(this,this.onPointerFocus,this.maxH,"rzSliderHigh")))},unbindEvents:function(){this.minH.off(),this.maxH.off(),this.fullBar.off(),this.selBar.off(),this.ticks.off()},onStart:function(b,d,e){var f,g,h=this.getEventNames(e);e.stopPropagation(),e.preventDefault(),this.calcViewDimensions(),b?this.tracking=d:(b=this.getNearestHandle(e),this.tracking=b===this.minH?"rzSliderModel":"rzSliderHigh"),b.addClass("rz-active"),this.options.keyboardSupport&&this.focusElement(b),f=a.bind(this,this.dragging.active?this.onDragMove:this.onMove,b),g=a.bind(this,this.onEnd,f),c.on(h.moveEvent,f),c.one(h.endEvent,g),this.callOnStart()},onMove:function(a,b){var c,d=this.getEventPosition(b),e=this.options.rightToLeft?this.minValue:this.maxValue,f=this.options.rightToLeft?this.maxValue:this.minValue;0>=d?c=f:d>=this.maxPos?c=e:(c=this.offsetToValue(d),c=this.roundStep(c)),this.positionTrackingHandle(c)},onEnd:function(a,b){var d=this.getEventNames(b).moveEvent;this.options.keyboardSupport||(this.minH.removeClass("rz-active"),this.maxH.removeClass("rz-active"),this.tracking=""),this.dragging.active=!1,c.off(d,a),this.scope.$emit("slideEnded"),this.callOnEnd()},onPointerFocus:function(b,c){this.tracking=c,b.one("blur",a.bind(this,this.onPointerBlur,b)),b.on("keydown",a.bind(this,this.onKeyboardEvent)),b.addClass("rz-active")},onPointerBlur:function(a){a.off("keydown"),this.tracking="",a.removeClass("rz-active")},getKeyActions:function(a){var b=a+this.step,c=a-this.step,d=a+this.valueRange/10,e=a-this.valueRange/10,f={UP:b,DOWN:c,LEFT:c,RIGHT:b,PAGEUP:d,PAGEDOWN:e,HOME:this.minValue,END:this.maxValue};return this.options.rightToLeft&&(f.LEFT=b,f.RIGHT=c,this.options.vertical&&(f.UP=c,f.DOWN=b)),f},onKeyboardEvent:function(a){var b=this.scope[this.tracking],c=a.keyCode||a.which,d={38:"UP",40:"DOWN",37:"LEFT",39:"RIGHT",33:"PAGEUP",34:"PAGEDOWN",36:"HOME",35:"END"},e=this.getKeyActions(b),f=d[c],g=e[f];if(null!=g&&""!==this.tracking){a.preventDefault();var h=this.roundStep(this.sanitizeValue(g));if(this.options.draggableRangeOnly){var i,j,k=this.scope.rzSliderHigh-this.scope.rzSliderModel;"rzSliderModel"===this.tracking?(i=h,j=h+k,j>this.maxValue&&(j=this.maxValue,i=j-k)):(j=h,i=h-k,i<this.minValue&&(i=this.minValue,j=i+k)),this.positionTrackingBar(i,j)}else this.positionTrackingHandle(h)}},onDragStart:function(a,b,c){var d=this.getEventPosition(c);this.dragging={active:!0,value:this.offsetToValue(d),difference:this.scope.rzSliderHigh-this.scope.rzSliderModel,lowLimit:this.options.rightToLeft?this.minH.rzsp-d:d-this.minH.rzsp,highLimit:this.options.rightToLeft?d-this.maxH.rzsp:this.maxH.rzsp-d},this.onStart(a,b,c)},getValue:function(a,b,c,d){var e=this.options.rightToLeft,f=null;return f="min"===a?c?d?e?f:this.maxValue-this.dragging.difference:e?this.maxValue-this.dragging.difference:f:e?this.offsetToValue(b+this.dragging.lowLimit):this.offsetToValue(b-this.dragging.lowLimit):c?d?e?this.minValue+this.dragging.difference:this.maxValue:e?this.maxValue:this.minValue+this.dragging.difference:e?this.offsetToValue(b+this.dragging.lowLimit)+this.dragging.difference:this.offsetToValue(b-this.dragging.lowLimit)+this.dragging.difference,this.roundStep(f)},onDragMove:function(a,b){var c,d,e,f,g,h,i,j,k=this.getEventPosition(b);if(this.options.rightToLeft?(e=this.dragging.lowLimit,f=this.dragging.highLimit,i=this.maxH,j=this.minH):(e=this.dragging.highLimit,f=this.dragging.lowLimit,i=this.minH,j=this.maxH),g=f>=k,h=k>=this.maxPos-e,g){if(0===i.rzsp)return;c=this.getValue("min",k,!0,!1),d=this.getValue("max",k,!0,!1)}else if(h){if(j.rzsp===this.maxPos)return;d=this.getValue("max",k,!0,!0),c=this.getValue("min",k,!0,!0)}else c=this.getValue("min",k,!1),d=this.getValue("max",k,!1);this.positionTrackingBar(c,d)},positionTrackingBar:function(a,b){this.scope.rzSliderModel=a,this.scope.rzSliderHigh=b,this.updateHandles("rzSliderModel",this.valueToOffset(a)),this.updateHandles("rzSliderHigh",this.valueToOffset(b)),this.applyModel()},positionTrackingHandle:function(a){var b=!1;this.range&&(a=this.applyMinRange(a),"rzSliderModel"===this.tracking&&a>this.scope.rzSliderHigh?(this.options.noSwitching&&this.scope.rzSliderHigh!==this.minValue?a=this.applyMinRange(this.scope.rzSliderHigh):(this.scope[this.tracking]=this.scope.rzSliderHigh,this.updateHandles(this.tracking,this.maxH.rzsp),this.updateAriaAttributes(),this.tracking="rzSliderHigh",this.minH.removeClass("rz-active"),this.maxH.addClass("rz-active"),this.options.keyboardSupport&&this.focusElement(this.maxH)),b=!0):"rzSliderHigh"===this.tracking&&a<this.scope.rzSliderModel&&(this.options.noSwitching&&this.scope.rzSliderModel!==this.maxValue?a=this.applyMinRange(this.scope.rzSliderModel):(this.scope[this.tracking]=this.scope.rzSliderModel,this.updateHandles(this.tracking,this.minH.rzsp),this.updateAriaAttributes(),this.tracking="rzSliderModel",this.maxH.removeClass("rz-active"),this.minH.addClass("rz-active"),this.options.keyboardSupport&&this.focusElement(this.minH)),b=!0)),this.scope[this.tracking]!==a&&(this.scope[this.tracking]=a,this.updateHandles(this.tracking,this.valueToOffset(a)),this.updateAriaAttributes(),b=!0),b&&this.applyModel()},applyMinRange:function(a){if(0!==this.options.minRange){var b="rzSliderModel"===this.tracking?this.scope.rzSliderHigh:this.scope.rzSliderModel,c=Math.abs(a-b);if(c<this.options.minRange)return"rzSliderModel"===this.tracking?this.scope.rzSliderHigh-this.options.minRange:this.scope.rzSliderModel+this.options.minRange}return a},applyModel:function(){this.internalChange=!0,this.scope.$apply(),this.callOnChange(),this.internalChange=!1},callOnStart:function(){if(this.options.onStart){var a=this;this.scope.$evalAsync(function(){a.options.onStart(a.options.id,a.scope.rzSliderModel,a.scope.rzSliderHigh)})}},callOnChange:function(){if(this.options.onChange){var a=this;this.scope.$evalAsync(function(){a.options.onChange(a.options.id,a.scope.rzSliderModel,a.scope.rzSliderHigh)})}},callOnEnd:function(){if(this.options.onEnd){var a=this;this.scope.$evalAsync(function(){a.options.onEnd(a.options.id,a.scope.rzSliderModel,a.scope.rzSliderHigh)})}}},h}]).directive("rzslider",["RzSlider",function(a){return{restrict:"E",scope:{rzSliderModel:"=?",rzSliderHigh:"=?",rzSliderOptions:"&?",rzSliderTplUrl:"@"},templateUrl:function(a,b){return b.rzSliderTplUrl||"rzSliderTpl.html"},link:function(b,c){b.slider=new a(b,c)}}}]);return b.run(["$templateCache",function(a){a.put("rzSliderTpl.html",'<span class=rz-bar-wrapper><span class=rz-bar></span></span> <span class=rz-bar-wrapper><span class="rz-bar rz-selection" ng-style=barStyle></span></span> <span class="rz-pointer rz-pointer-min" ng-style=minPointerStyle></span> <span class="rz-pointer rz-pointer-max" ng-style=maxPointerStyle></span> <span class="rz-bubble rz-limit"></span> <span class="rz-bubble rz-limit"></span> <span class=rz-bubble></span> <span class=rz-bubble></span> <span class=rz-bubble></span><ul ng-show=showTicks class=rz-ticks><li ng-repeat="t in ticks track by $index" class=tick ng-class="{selected: t.selected}" ng-style=t.style ng-attr-uib-tooltip="{{ t.tooltip }}" ng-attr-tooltip-placement={{t.tooltipPlacement}} ng-attr-tooltip-append-to-body="{{ t.tooltip ? true : undefined}}"><span ng-if="t.value != null" class=tick-value ng-attr-uib-tooltip="{{ t.valueTooltip }}" ng-attr-tooltip-placement={{t.valueTooltipPlacement}}>{{ t.value }}</span></li></ul>')}]),b});
\ No newline at end of file
{
"name": "angularjs-slider",
"version": "2.9.0",
"version": "2.10.0",
"description": "AngularJS slider directive with no external dependencies. Mobile friendly!.",
"main": "dist/rzslider.js",
"repository": {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment