233 lines
10 KiB
JavaScript
233 lines
10 KiB
JavaScript
(function(factory) {
|
|
if (typeof define === 'function' && define.amd) {
|
|
define(['angular', 'bootstrap-slider'], factory);
|
|
} else if (typeof module === 'object' && module.exports) {
|
|
module.exports = factory(require('angular'), require('bootstrap-slider'));
|
|
} else if (window) {
|
|
factory(window.angular, window.Slider);
|
|
}
|
|
})(function (angular, Slider) {
|
|
|
|
angular.module('ui.bootstrap-slider', [])
|
|
.directive('slider', ['$parse', '$timeout', '$rootScope', function ($parse, $timeout, $rootScope) {
|
|
return {
|
|
restrict: 'AE',
|
|
replace: true,
|
|
template: '<div><input class="slider-input" type="text" style="width:100%" /></div>',
|
|
require: 'ngModel',
|
|
scope: {
|
|
max: "=",
|
|
min: "=",
|
|
step: "=",
|
|
value: "=",
|
|
ngModel: '=',
|
|
ngDisabled: '=',
|
|
range: '=',
|
|
sliderid: '=',
|
|
ticks: '=',
|
|
ticksLabels: '=',
|
|
ticksSnapBounds: '=',
|
|
ticksPositions: '=',
|
|
scale: '=',
|
|
focus: '=',
|
|
formatter: '&',
|
|
onStartSlide: '&',
|
|
onStopSlide: '&',
|
|
onSlide: '&'
|
|
},
|
|
link: function ($scope, element, attrs, ngModelCtrl, $compile) {
|
|
var ngModelDeregisterFn, ngDisabledDeregisterFn;
|
|
|
|
var slider = initSlider();
|
|
|
|
function initSlider() {
|
|
var options = {};
|
|
|
|
function setOption(key, value, defaultValue) {
|
|
options[key] = value || defaultValue;
|
|
}
|
|
|
|
function setFloatOption(key, value, defaultValue) {
|
|
options[key] = value || value === 0 ? parseFloat(value) : defaultValue;
|
|
}
|
|
|
|
function setBooleanOption(key, value, defaultValue) {
|
|
options[key] = value ? value + '' === 'true' : defaultValue;
|
|
}
|
|
|
|
function getArrayOrValue(value) {
|
|
return (angular.isString(value) && value.indexOf("[") === 0) ? angular.fromJson(value) : value;
|
|
}
|
|
|
|
setOption('id', $scope.sliderid);
|
|
setOption('orientation', attrs.orientation, 'horizontal');
|
|
setOption('selection', attrs.selection, 'before');
|
|
setOption('handle', attrs.handle, 'round');
|
|
setOption('tooltip', attrs.sliderTooltip || attrs.tooltip, 'show');
|
|
setOption('tooltip_position', attrs.sliderTooltipPosition, 'top');
|
|
setOption('tooltipseparator', attrs.tooltipseparator, ':');
|
|
setOption('ticks', $scope.ticks);
|
|
setOption('ticks_labels', $scope.ticksLabels);
|
|
setOption('ticks_snap_bounds', $scope.ticksSnapBounds);
|
|
setOption('ticks_positions', $scope.ticksPositions);
|
|
setOption('scale', $scope.scale, 'linear');
|
|
setOption('focus', $scope.focus);
|
|
|
|
setFloatOption('min', $scope.min, 0);
|
|
setFloatOption('max', $scope.max, 10);
|
|
setFloatOption('step', $scope.step, 1);
|
|
var strNbr = options.step + '';
|
|
var dotPos = strNbr.search(/[^.,]*$/);
|
|
var decimals = strNbr.substring(dotPos);
|
|
setFloatOption('precision', attrs.precision, decimals.length);
|
|
|
|
setBooleanOption('tooltip_split', attrs.tooltipsplit, false);
|
|
setBooleanOption('enabled', attrs.enabled, true);
|
|
setBooleanOption('naturalarrowkeys', attrs.naturalarrowkeys, false);
|
|
setBooleanOption('reversed', attrs.reversed, false);
|
|
|
|
setBooleanOption('range', $scope.range, false);
|
|
if (options.range) {
|
|
if (angular.isArray($scope.value)) {
|
|
options.value = $scope.value;
|
|
}
|
|
else if (angular.isString($scope.value)) {
|
|
options.value = getArrayOrValue($scope.value);
|
|
if (!angular.isArray(options.value)) {
|
|
var value = parseFloat($scope.value);
|
|
if (isNaN(value)) value = 5;
|
|
|
|
if (value < $scope.min) {
|
|
value = $scope.min;
|
|
options.value = [value, options.max];
|
|
}
|
|
else if (value > $scope.max) {
|
|
value = $scope.max;
|
|
options.value = [options.min, value];
|
|
}
|
|
else {
|
|
options.value = [options.min, options.max];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
options.value = [options.min, options.max]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
|
|
}
|
|
$scope.ngModel = options.value; // needed, otherwise turns value into [null, ##]
|
|
}
|
|
else {
|
|
setFloatOption('value', $scope.value, 5);
|
|
}
|
|
|
|
if (attrs.formatter) {
|
|
options.formatter = function(value) {
|
|
return $scope.formatter({value: value});
|
|
}
|
|
}
|
|
|
|
// check if slider jQuery plugin exists
|
|
if ('$' in window && $.fn.slider) {
|
|
// adding methods to jQuery slider plugin prototype
|
|
$.fn.slider.constructor.prototype.disable = function () {
|
|
this.picker.off();
|
|
};
|
|
$.fn.slider.constructor.prototype.enable = function () {
|
|
this.picker.on();
|
|
};
|
|
}
|
|
|
|
// destroy previous slider to reset all options
|
|
if (element[0].__slider)
|
|
element[0].__slider.destroy();
|
|
|
|
var slider = new Slider(element[0].getElementsByClassName('slider-input')[0], options);
|
|
element[0].__slider = slider;
|
|
|
|
// everything that needs slider element
|
|
var updateEvent = getArrayOrValue(attrs.updateevent);
|
|
if (angular.isString(updateEvent)) {
|
|
// if only single event name in string
|
|
updateEvent = [updateEvent];
|
|
}
|
|
else {
|
|
// default to slide event
|
|
updateEvent = ['slide'];
|
|
}
|
|
angular.forEach(updateEvent, function (sliderEvent) {
|
|
slider.on(sliderEvent, function (ev) {
|
|
ngModelCtrl.$setViewValue(ev);
|
|
});
|
|
});
|
|
slider.on('change', function (ev) {
|
|
ngModelCtrl.$setViewValue(ev.newValue);
|
|
});
|
|
|
|
|
|
// Event listeners
|
|
var sliderEvents = {
|
|
slideStart: 'onStartSlide',
|
|
slide: 'onSlide',
|
|
slideStop: 'onStopSlide'
|
|
};
|
|
angular.forEach(sliderEvents, function (sliderEventAttr, sliderEvent) {
|
|
var fn = $parse(attrs[sliderEventAttr]);
|
|
slider.on(sliderEvent, function (ev) {
|
|
if ($scope[sliderEventAttr]) {
|
|
$scope.$apply(function () {
|
|
fn($scope.$parent, { $event: ev, value: ev });
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// deregister ngDisabled watcher to prevent memory leaks
|
|
if (angular.isFunction(ngDisabledDeregisterFn)) {
|
|
ngDisabledDeregisterFn();
|
|
ngDisabledDeregisterFn = null;
|
|
}
|
|
|
|
ngDisabledDeregisterFn = $scope.$watch('ngDisabled', function (value) {
|
|
if (value) {
|
|
slider.disable();
|
|
}
|
|
else {
|
|
slider.enable();
|
|
}
|
|
});
|
|
|
|
// deregister ngModel watcher to prevent memory leaks
|
|
if (angular.isFunction(ngModelDeregisterFn)) ngModelDeregisterFn();
|
|
ngModelDeregisterFn = $scope.$watch('ngModel', function (value) {
|
|
if($scope.range){
|
|
slider.setValue(value);
|
|
}else{
|
|
slider.setValue(parseFloat(value));
|
|
}
|
|
slider.relayout();
|
|
}, true);
|
|
|
|
return slider;
|
|
}
|
|
|
|
|
|
var watchers = ['min', 'max', 'step', 'range', 'scale', 'ticksLabels', 'ticks'];
|
|
angular.forEach(watchers, function (prop) {
|
|
$scope.$watch(prop, function () {
|
|
slider = initSlider();
|
|
});
|
|
});
|
|
|
|
var globalEvents = ['relayout', 'refresh', 'resize'];
|
|
angular.forEach(globalEvents, function(event) {
|
|
if(angular.isFunction(slider[event])) {
|
|
$scope.$on('slider:' + event, function () {
|
|
slider[event]();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}])
|
|
;
|
|
});
|