Created
August 7, 2015 04:52
-
-
Save kencaron/7c3e64c5251472ea6dd3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (angular) { | |
'use strict'; | |
angular.module('angularAwesomeSlider', []) | |
// DIRECTIVE | |
.directive('slider', [ | |
'$compile', '$templateCache','$timeout', '$window', 'slider', | |
function(compile, templateCache, timeout, win, Slider) { | |
return { | |
restrict : 'AE', | |
require: '?ngModel', | |
scope: { options:'=', ngDisabled: '='}, | |
priority: 1, | |
link : function(scope, element, attrs, ngModel) { | |
if(!ngModel) return; | |
if (!scope.options) | |
throw new Error('You must provide a value for "options" attribute.'); | |
var injector = angular.injector(); | |
// options as inline variable | |
if (angular.isString(scope.options)) { | |
scope.options = angular.toJson(scope.options); | |
} | |
scope.mainSliderClass = 'jslider'; | |
scope.mainSliderClass += scope.options.skin ? ' jslider_' + scope.options.skin : ' '; | |
scope.mainSliderClass += scope.options.vertical ? ' vertical ' : ''; | |
scope.mainSliderClass += scope.options.css ? ' sliderCSS' : ''; | |
scope.mainSliderClass += scope.options.className ? ' ' + scope.options.className : ''; | |
// handle limit labels visibility | |
scope.options.limits = angular.isDefined(scope.options.limits) ? scope.options.limits : true; | |
// compile template | |
element.after(compile(templateCache.get('ng-slider/slider-bar.tmpl.html'))(scope, function(clonedElement, scope) { | |
scope.tmplElt = clonedElement; | |
})); | |
// init | |
var initialized = false; | |
var init = function() { | |
scope.from = ''+scope.options.from; | |
scope.to = ''+scope.options.to; | |
if (scope.options.calculate && typeof scope.options.calculate === 'function') { | |
scope.from = scope.options.calculate(scope.from); | |
scope.to = scope.options.calculate(scope.to); | |
} | |
var OPTIONS = { | |
from: !scope.options.round ? parseInt(scope.options.from, 10) : parseFloat(scope.options.from), | |
to: !scope.options.round ? parseInt(scope.options.to, 10) : parseFloat(scope.options.to), | |
step: scope.options.step, | |
smooth: scope.options.smooth, | |
limits: scope.options.limits, | |
round: scope.options.round || false, | |
value: ngModel.$viewValue, | |
dimension: "", | |
scale: scope.options.scale, | |
modelLabels: scope.options.modelLabels, | |
vertical: scope.options.vertical, | |
css: scope.options.css, | |
className: scope.options.className, | |
realtime: scope.options.realtime, | |
cb: forceApply, | |
threshold: scope.options.threshold, | |
heterogeneity: scope.options.heterogeneity | |
}; | |
OPTIONS.calculate = scope.options.calculate || undefined; | |
OPTIONS.onstatechange = scope.options.onstatechange || undefined; | |
// slider | |
scope.slider = !scope.slider ? slidering(element, scope.tmplElt, OPTIONS) : scope.slider.init(element, scope.tmplElt, OPTIONS); | |
if (!initialized) { | |
initListener(); | |
} | |
// scale | |
var scaleDiv = scope.tmplElt.find('div')[7]; | |
angular.element(scaleDiv).html(scope.slider.generateScale()); | |
scope.slider.drawScale(scaleDiv); | |
if (scope.ngDisabled) { | |
disabler(scope.ngDisabled); | |
} | |
initialized = true; | |
}; | |
function initListener() { | |
// window resize listener | |
angular.element(win).bind('resize', function(event) { | |
scope.slider.onresize(); | |
}); | |
} | |
// model -> view | |
ngModel.$render = function () { | |
//elm.html(ctrl.$viewValue); | |
var singleValue = false; | |
if (!ngModel.$viewValue && ngModel.$viewValue !== 0) { | |
return; | |
} | |
if (typeof(ngModel.$viewValue) === 'number') { | |
ngModel.$viewValue = ''+ngModel.$viewValue; | |
} | |
if( !ngModel.$viewValue.split(";")[1]) { | |
scope.mainSliderClass += ' jslider-single'; | |
} | |
if (scope.slider) { | |
var firstPtr = scope.slider.getPointers()[0]; | |
// reset to lowest value | |
firstPtr.set(scope.from, true); | |
if (ngModel.$viewValue.split(';')[1]) { | |
var secondPtr = scope.slider.getPointers()[1]; | |
// reset to biggest value | |
firstPtr.set(scope.to, true); | |
secondPtr.set(ngModel.$viewValue.split(';')[1], true); | |
} | |
firstPtr.set(ngModel.$viewValue.split(';')[0], true); | |
} | |
}; | |
// view -> model | |
var forceApply = function(value, released) { | |
if (scope.disabled) | |
return; | |
scope.$apply(function() { | |
ngModel.$setViewValue(value); | |
}); | |
if (scope.options.callback){ | |
scope.options.callback(value, released); | |
} | |
}; | |
// watch options | |
scope.$watch('options', function(value) { | |
timeout(function(){ | |
init(); | |
}); | |
}, scope.watchOptions || true); | |
// disabling | |
var disabler = function(value) { | |
scope.disabled = value; | |
if (scope.slider) { | |
scope.tmplElt.toggleClass('disabled'); | |
scope.slider.disable(value); | |
} | |
}; | |
scope.$watch('ngDisabled', function(value) { | |
disabler(value); | |
}); | |
scope.limitValue = function(value) { | |
if (scope.options.modelLabels) { | |
if (angular.isFunction(scope.options.modelLabels)) { | |
return scope.options.modelLabels(value); | |
} | |
return scope.options.modelLabels[value] !== undefined ? scope.options.modelLabels[value] : value; | |
} | |
return value; | |
}; | |
var slidering = function( inputElement, element, settings) { | |
return new Slider( inputElement, element, settings ); | |
}; | |
} | |
}; | |
}]) | |
.config(function() {}) | |
.run(function() {}); | |
})(angular); | |
;(function(angular){ | |
'use strict'; | |
angular.module('angularAwesomeSlider').constant('sliderConstants', { | |
SLIDER: { | |
settings: { | |
from: 1, | |
to: 40, | |
step: 1, | |
smooth: true, | |
limits: false, | |
round: false, | |
value: "3", | |
dimension: "", | |
vertical: false, | |
calculate: false, | |
onstatechange: false, | |
callback: false, | |
realtime: false | |
}, | |
className: "jslider", | |
selector: ".jslider-", | |
css: { | |
visible : { visibility: "visible" }, | |
hidden : { visibility: "hidden" } | |
} | |
}, | |
EVENTS: { | |
} | |
}); | |
}(angular));;(function(angular){ | |
'use strict'; | |
angular.module('angularAwesomeSlider').factory('sliderUtils', ['$window', function(win) { | |
return { | |
offset: function(elm) { | |
// try {return elm.offset();} catch(e) {} | |
var rawDom = elm[0]; | |
var _x = 0; | |
var _y = 0; | |
var body = document.documentElement || document.body; | |
var scrollX = window.pageXOffset || body.scrollLeft; | |
var scrollY = window.pageYOffset || body.scrollTop; | |
_x = rawDom.getBoundingClientRect().left + scrollX; | |
_y = rawDom.getBoundingClientRect().top + scrollY; | |
return { left: _x, top:_y }; | |
}, | |
browser: function() { | |
// TODO finish browser detection and this case | |
var userAgent = win.navigator.userAgent; | |
var browsers = {mozilla: /mozilla/i, chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i}; | |
for(var key in browsers) { | |
if (browsers[key].test(userAgent)) { | |
return key; | |
} | |
} | |
return 'unknown'; | |
} | |
}; | |
}]); | |
})(angular); | |
;(function(angular){ | |
'use strict'; | |
angular.module('angularAwesomeSlider').factory('sliderDraggable', ['sliderUtils', function(utils) { | |
function Draggable(){ | |
this._init.apply( this, arguments ); | |
} | |
Draggable.prototype.oninit = function(){ | |
}; | |
Draggable.prototype.events = function(){ | |
}; | |
Draggable.prototype.onmousedown = function(){ | |
this.ptr.css({ position: 'absolute' }); | |
}; | |
Draggable.prototype.onmousemove = function( evt, x, y ){ | |
this.ptr.css({ left: x, top: y }); | |
}; | |
Draggable.prototype.onmouseup = function(){}; | |
Draggable.prototype.isDefault = { | |
drag: false, | |
clicked: false, | |
toclick: true, | |
mouseup: false | |
}; | |
Draggable.prototype._init = function() { | |
if( arguments.length > 0 ){ | |
this.ptr = arguments[0]; | |
this.parent = arguments[2]; | |
if (!this.ptr) | |
return; | |
//this.outer = $(".draggable-outer"); | |
this.is = {}; | |
angular.extend( this.is, this.isDefault ); | |
var offset = utils.offset(this.ptr); | |
this.d = { | |
left: offset.left, | |
top: offset.top, | |
width: this.ptr[0].clientWidth, | |
height: this.ptr[0].clientHeight | |
}; | |
this.oninit.apply( this, arguments ); | |
this._events(); | |
} | |
}; | |
Draggable.prototype._getPageCoords = function( event ){ | |
if( event.targetTouches && event.targetTouches[0] ){ | |
return { x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY }; | |
} else | |
return { x: event.pageX, y: event.pageY }; | |
}; | |
Draggable.prototype._bindEvent = function( ptr, eventType, handler ){ | |
var self = this; | |
// PS need to bind to touch and non-touch events for devices which support both | |
if( this.supportTouches_ ){ | |
ptr[0].addEventListener( this.events_[ eventType ].touch, handler, false ); | |
} | |
ptr.bind( this.events_[ eventType ].nonTouch, handler ); | |
}; | |
Draggable.prototype._events = function(){ | |
var self = this; | |
this.supportTouches_ = 'ontouchend' in document; | |
this.events_ = { | |
'click': { touch : 'touchstart', nonTouch : 'click' }, | |
'down': { touch : 'touchstart', nonTouch : 'mousedown' }, | |
'move': { touch : 'touchmove', nonTouch : 'mousemove' }, | |
'up' : { touch : 'touchend', nonTouch: 'mouseup'}, | |
'mousedown' : { touch : 'mousedown', nonTouch : 'mousedown' } | |
}; | |
var documentElt = angular.element(window.document); | |
this._bindEvent(documentElt, 'move', function(event) { | |
if(self.is.drag) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
if (!self.parent.disabled) { | |
self._mousemove(event); | |
} | |
} | |
}); | |
this._bindEvent(documentElt, 'down', function(event) { | |
if(self.is.drag) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
} | |
}); | |
this._bindEvent(documentElt, 'up', function(event) { | |
self._mouseup(event); | |
}); | |
this._bindEvent( this.ptr, 'down', function(event) { | |
self._mousedown( event ); | |
return false; | |
}); | |
this._bindEvent( this.ptr, 'up', function(event) { | |
self._mouseup( event ); | |
}); | |
// TODO see if needed | |
this.events(); | |
}; | |
Draggable.prototype._mousedown = function( evt ){ | |
this.is.drag = true; | |
this.is.clicked = false; | |
this.is.mouseup = false; | |
var coords = this._getPageCoords( evt ); | |
this.cx = coords.x - this.ptr[0].offsetLeft; | |
this.cy = coords.y - this.ptr[0].offsetTop; | |
angular.extend(this.d, { | |
left: coords.x, | |
top: coords.y, | |
width: this.ptr[0].clientWidth, | |
height: this.ptr[0].clientHeight | |
}); | |
if( this.outer && this.outer.get(0) ){ | |
this.outer.css({ height: Math.max(this.outer.height(), $(document.body).height()), overflow: 'hidden' }); | |
} | |
this.onmousedown( evt ); | |
}; | |
Draggable.prototype._mousemove = function( evt ){ | |
this.is.toclick = false; | |
var coords = this._getPageCoords( evt ); | |
this.onmousemove( evt, coords.x - this.cx, coords.y - this.cy ); | |
}; | |
Draggable.prototype._mouseup = function( evt ){ | |
var oThis = this; | |
if( this.is.drag ){ | |
this.is.drag = false; | |
var browser = utils.browser(); | |
if( this.outer && this.outer.get(0) ) { | |
if( browser === 'mozilla' ){ | |
this.outer.css({ overflow: "hidden" }); | |
} else { | |
this.outer.css({ overflow: "visible" }); | |
} | |
// TODO finish browser detection and this case, remove following line | |
this.outer.css({ height: "auto" }); | |
// if( browser === 'ie' && $.browser.version == '6.0' ){ | |
// this.outer.css({ height: "100%" }); | |
// } else { | |
// this.outer.css({ height: "auto" }); | |
// } | |
} | |
this.onmouseup( evt ); | |
} | |
}; | |
return Draggable; | |
}]); | |
}(angular));;(function(angular){ | |
'use strict'; | |
angular.module('angularAwesomeSlider').factory('sliderPointer', ['sliderDraggable', 'sliderUtils', function(Draggable, utils) { | |
function SliderPointer() { | |
Draggable.apply(this, arguments); | |
} | |
SliderPointer.prototype = new Draggable(); | |
SliderPointer.prototype.oninit = function( ptr, id, vertical, _constructor ) { | |
this.uid = id; | |
this.parent = _constructor; | |
this.value = {}; | |
this.vertical = vertical; | |
this.settings = angular.copy(_constructor.settings); | |
this.threshold = this.settings.threshold; | |
}; | |
SliderPointer.prototype.onmousedown = function( evt ) { | |
var off = utils.offset(this.parent.domNode); | |
var offset = { | |
left: off.left, | |
top: off.top, | |
width: this.parent.domNode[0].clientWidth, | |
height: this.parent.domNode[0].clientHeight | |
}; | |
this._parent = { | |
offset: offset, | |
width: offset.width, | |
height: offset.height | |
}; | |
this.ptr.addClass('jslider-pointer-hover'); | |
}; | |
SliderPointer.prototype.onmousemove = function( evt, x, y ){ | |
var coords = this._getPageCoords( evt ); | |
this._set(!this.vertical ? this.calc( coords.x ) : this.calc( coords.y )); | |
if( this.settings.realtime && this.settings.cb && angular.isFunction(this.settings.cb) ) | |
this.settings.cb.call( this.parent, this.parent.getValue(), !this.is.drag ); | |
}; | |
SliderPointer.prototype.onmouseup = function(evt){ | |
if( this.settings.cb && angular.isFunction(this.settings.cb)) | |
this.settings.cb.call( this.parent, this.parent.getValue(), !this.is.drag ); | |
if (!this.is.drag) | |
this.ptr.removeClass('jslider-pointer-hover'); | |
}; | |
SliderPointer.prototype.limits = function( x ){ | |
return this.parent.limits(x, this); | |
}; | |
SliderPointer.prototype.calc = function( coords ){ | |
return !this.vertical ? | |
this.limits(((coords-this._parent.offset.left)*100)/this._parent.width) | |
: | |
this.limits(((coords-this._parent.offset.top)*100)/this._parent.height); | |
}; | |
SliderPointer.prototype.set = function( value, opt_origin ){ | |
this.value.origin = this.parent.round(value); | |
this._set(this.parent.valueToPrc(value,this), opt_origin); | |
}; | |
SliderPointer.prototype._set = function( prc, opt_origin ){ | |
this.allowed = true; | |
var oldOrigin = this.value.origin; | |
var oldPerc = this.value.prc; | |
this.value.origin = this.parent.prcToValue(prc); | |
this.value.prc = prc; | |
// check threshold | |
if (this.threshold && this.parent.o.pointers[1]) { | |
var v1 = this.value.origin, | |
v2 = this.parent.o.pointers[this.uid === 0 ? 1:0].value.origin; | |
this.allowed = Math.abs(v2 - v1) >= this.threshold; | |
if (!this.allowed && oldOrigin !== undefined && oldPerc !== undefined){ | |
this.value.origin = oldOrigin; | |
this.value.prc = oldPerc; | |
} | |
} | |
if (!this.vertical) | |
this.ptr.css({left:this.value.prc+'%'}); | |
else | |
this.ptr.css({top:this.value.prc+'%', marginTop: -5}); | |
this.parent.redraw(this); | |
}; | |
return SliderPointer; | |
}]); | |
}(angular));;(function(angular){ | |
'use strict'; | |
angular.module('angularAwesomeSlider').factory('slider', ['sliderPointer', 'sliderConstants', 'sliderUtils', function(SliderPointer, sliderConstants, utils) { | |
function Slider(){ | |
return this.init.apply(this, arguments); | |
} | |
Slider.prototype.init = function( inputNode, templateNode, settings ){ | |
this.settings = settings; | |
this.inputNode = inputNode; | |
this.inputNode.addClass("ng-hide"); | |
this.settings.interval = this.settings.to-this.settings.from; | |
if(this.settings.calculate && angular.isFunction(this.settings.calculate)) | |
this.nice = this.settings.calculate; | |
if(this.settings.onstatechange && angular.isFunction(this.settings.onstatechange)) | |
this.onstatechange = this.settings.onstatechange; | |
this.css = sliderConstants.SLIDER.css; | |
this.is = {init: false}; | |
this.o = {}; | |
this.initValue = {}; | |
this.isAsc = settings.from < settings.to; | |
this.create(templateNode); | |
return this; | |
}; | |
Slider.prototype.create = function( templateNode ){ | |
// set skin class | |
// if( this.settings.skin && this.settings.skin.length > 0 ) | |
// this.setSkin( this.settings.skin ); | |
var self = this; | |
this.domNode = templateNode; | |
var divs = this.domNode.find('div'), | |
is = this.domNode.find('i'), | |
angElt = angular.element, | |
angExt = angular.extend, | |
angForEach = angular.forEach, | |
pointer1 = angElt(divs[1]), | |
pointer2 = angElt(divs[2]), | |
pointerLabel1 = angElt(divs[5]), | |
pointerLabel2 = angElt(divs[6]), | |
indicatorLeft = angElt(is[0]), | |
indicatorRight = angElt(is[1]), | |
range = angElt(is[2]), | |
indicator1 = angElt(is[3]), | |
indicator2 = angElt(is[4]), | |
indicator3 = angElt(is[5]), | |
indicator4 = angElt(is[6]), | |
pointers = [pointer1, pointer2], | |
off = utils.offset(this.domNode), | |
offset = { | |
left: off.left, | |
top: off.top, | |
width: this.domNode[0].clientWidth, | |
height: this.domNode[0].clientHeight | |
}, | |
values = self.settings.value.split(';'); | |
this.sizes = { | |
domWidth: this.domNode[0].clientWidth, | |
domHeight: this.domNode[0].clientHeight, | |
domOffset: offset | |
}; | |
// find some objects | |
angExt(this.o, { | |
pointers: {}, | |
labels: { 0: { o : pointerLabel1 }, 1: { o : pointerLabel2 } }, | |
limits: { 0: angular.element(divs[3]), 1: angular.element(divs[4]) }, | |
indicators: { 0: indicator1, 1: indicator2, 2: indicator3, 3: indicator4 } | |
}); | |
angExt(this.o.labels[0], { | |
value: this.o.labels[0].o.find("span") | |
}); | |
angExt(this.o.labels[1], { | |
value: this.o.labels[1].o.find("span") | |
}); | |
// single pointer | |
this.settings.single = !self.settings.value.split(";")[1]; | |
if (this.settings.single) { | |
range.addClass('ng-hide'); | |
} | |
angForEach(pointers, function(pointer, key) { | |
self.settings = angular.copy(self.settings); | |
var value = values[key], | |
prev, | |
prevValue, | |
test, | |
value1, | |
offset; | |
if(value) { | |
self.o.pointers[key] = new SliderPointer(pointer, key, self.settings.vertical, self); | |
prev = values[key-1]; | |
prevValue = prev ? parseInt(prev, 10 ) : undefined; | |
value = self.settings.round ? parseFloat(value) : parseInt(value, 10); | |
if( prev && self.isAsc ? value < prevValue : value > prevValue ) { | |
value = prev; | |
} | |
// limit threshold adjust | |
/* test = self.isAsc ? value < self.settings.from : value > self.settings.from, | |
value1 = test ? self.settings.from : value; */ | |
test = self.isAsc ? value > self.settings.to : value < self.settings.to; | |
value1 = test ? self.settings.to : value; | |
self.o.pointers[key].set( value1, true ); | |
// reinit position d | |
offset = utils.offset(self.o.pointers[key].ptr); | |
self.o.pointers[key].d = { | |
left: offset.left, | |
top: offset.top | |
}; | |
} | |
}); | |
self.domNode.bind('mousedown', self.clickHandler.apply(self)); | |
this.o.value = angElt(this.domNode.find("i")[2]); | |
this.is.init = true; | |
// CSS SKIN | |
if (this.settings.css) { | |
indicatorLeft.css(this.settings.css.background ? this.settings.css.background : {}); | |
indicatorRight.css(this.settings.css.background ? this.settings.css.background : {}); | |
if (!this.o.pointers[1]) { | |
indicator1.css(this.settings.css.before ? this.settings.css.before : {}); | |
indicator4.css(this.settings.css.after ? this.settings.css.after : {}); | |
} | |
indicator2.css(this.settings.css.default ? this.settings.css.default : {}); | |
indicator3.css(this.settings.css.default ? this.settings.css.default : {}); | |
range.css(this.settings.css.range ? this.settings.css.range : {}); | |
pointer1.css(this.settings.css.pointer ? this.settings.css.pointer : {}); | |
pointer2.css(this.settings.css.pointer ? this.settings.css.pointer : {}); | |
} | |
angForEach(this.o.pointers, function(pointer, key){ | |
self.redraw(pointer); | |
}); | |
}; | |
Slider.prototype.clickHandler = function() { | |
var self = this; | |
// in case of showing/hiding | |
var resetPtrSize = function( ptr ) { | |
var ptr1 = self.o.pointers[0].ptr, | |
ptr2 = self.o.pointers[1].ptr, | |
offset1 = utils.offset(ptr1), | |
offset2 = utils.offset(ptr2); | |
self.o.pointers[0].d = { | |
left: offset1.left, | |
top: offset1.top, | |
width: ptr1[0].clientWidth, | |
height: ptr1[0].clientHeight | |
}; | |
self.o.pointers[1].d = { | |
left: offset2.left, | |
top: offset2.top, | |
width: ptr2[0].clientWidth, | |
height: ptr2[0].clientHeight | |
}; | |
}; | |
return function(evt) { | |
if (self.disabled) | |
return; | |
var vertical = self.settings.vertical, | |
targetIdx = 0, | |
_off = utils.offset(self.domNode), | |
firstPtr = self.o.pointers[0], | |
secondPtr = self.o.pointers[1] ? self.o.pointers[1] : null, | |
tmpPtr, | |
evtPosition = evt.originalEvent ? evt.originalEvent: evt, | |
mouse = vertical ? evtPosition.pageY : evtPosition.pageX, | |
css = vertical ? 'top' : 'left', | |
offset = { left: _off.left, top: _off.top, width: self.domNode[0].clientWidth, height: self.domNode[0].clientHeight }, | |
targetPtr = self.o.pointers[targetIdx]; | |
if (secondPtr) { | |
if (!secondPtr.d.width) { | |
resetPtrSize(); | |
} | |
var firstPtrPosition = utils.offset(firstPtr.ptr)[css]; | |
var secondPtrPosition = utils.offset(secondPtr.ptr)[css]; | |
var middleGap = Math.abs((secondPtrPosition - firstPtrPosition) / 2); | |
var testSecondPtrToMove = mouse >= secondPtrPosition || mouse >= (secondPtrPosition - middleGap); | |
if (testSecondPtrToMove) { | |
targetPtr = secondPtr; | |
} | |
} | |
targetPtr._parent = {offset: offset, width: offset.width, height: offset.height}; | |
var coords = firstPtr._getPageCoords( evt ); | |
targetPtr.cx = coords.x - targetPtr.d.left; | |
targetPtr.cy = coords.y - targetPtr.d.top; | |
targetPtr.onmousemove( evt, coords.x, coords.y); | |
targetPtr.onmouseup(); | |
angular.extend(targetPtr.d, { | |
left: coords.x, | |
top: coords.y | |
}); | |
self.redraw(targetPtr); | |
return false; | |
}; | |
}; | |
Slider.prototype.disable = function( bool ) { | |
this.disabled = bool; | |
}; | |
Slider.prototype.nice = function( value ){ | |
return value; | |
}; | |
Slider.prototype.onstatechange = function(){}; | |
Slider.prototype.limits = function( x, pointer ){ | |
// smooth | |
if(!this.settings.smooth){ | |
var step = this.settings.step*100 / ( this.settings.interval ); | |
x = Math.round( x/step ) * step; | |
} | |
if (pointer) { | |
var another = this.o.pointers[1-pointer.uid]; | |
if(another && pointer.uid && x < another.value.prc) x = another.value.prc; | |
if(another && !pointer.uid && x > another.value.prc) x = another.value.prc; | |
} | |
// base limit | |
if(x < 0) x = 0; | |
if(x > 100) x = 100; | |
return Math.round(x*10) / 10; | |
}; | |
Slider.prototype.getPointers = function(){ | |
return this.o.pointers; | |
}; | |
Slider.prototype.generateScale = function(){ | |
if (this.settings.scale && this.settings.scale.length > 0){ | |
var str = '', | |
s = this.settings.scale, | |
// FIX Big Scale Failure #34 | |
// var prc = Math.round((100/(s.length-1))*10)/10; | |
prc, | |
label, | |
duplicate = {}, | |
position = this.settings.vertical ? 'top' : 'left', | |
i=0; | |
for(; i < s.length; i++) { | |
if (!s[i].val) { | |
prc = (100/(s.length-1)).toFixed(2); | |
str += '<span style="'+ position + ': ' + i*prc + '%">' + ( s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '' ) + '</span>'; | |
} | |
if (s[i].val <= this.settings.to && s[i].val >= this.settings.from && ! duplicate[s[i].val]) { | |
duplicate[s[i].val] = true; | |
prc = this.valueToPrc(s[i].val); | |
label = s[i].label ? s[i].label : s[i].val; | |
str += '<span style="'+ position + ': ' + prc + '%">' + '<ins>' + label + '</ins>' + '</span>'; | |
} | |
} | |
return str; | |
} | |
return ''; | |
}; | |
Slider.prototype.onresize = function(){ | |
var self = this; | |
this.sizes = { | |
domWidth: this.domNode[0].clientWidth, | |
domHeight: this.domNode[0].clientHeight, | |
domOffset: { | |
left: this.domNode[0].offsetLeft, | |
top: this.domNode[0].offsetTop, | |
width: this.domNode[0].clientWidth, | |
height: this.domNode[0].clientHeight | |
} | |
}; | |
angular.forEach(this.o.pointers, function(ptr, key) { | |
self.redraw(ptr); | |
}); | |
}; | |
Slider.prototype.update = function(){ | |
this.onresize(); | |
this.drawScale(); | |
}; | |
Slider.prototype.drawScale = function( scaleDiv ){ | |
angular.forEach(angular.element(scaleDiv).find('ins'), function(scaleLabel, key) { | |
scaleLabel.style.marginLeft = - scaleLabel.clientWidth / 2; | |
}); | |
}; | |
Slider.prototype.redraw = function( pointer ){ | |
if(!this.is.init) { | |
// this.settings.single | |
if(this.o.pointers[0] && !this.o.pointers[1]) { | |
this.originValue = this.o.pointers[0].value.prc; | |
this.o.indicators[0].css(!this.settings.vertical ? {left:0, width:this.o.pointers[0].value.prc + "%"} : {top:0, height:this.o.pointers[0].value.prc + "%"}); | |
this.o.indicators[1].css(!this.settings.vertical ? {left:this.o.pointers[0].value.prc + "%"} : {top:this.o.pointers[0].value.prc + "%"}); | |
this.o.indicators[3].css(!this.settings.vertical ? {left:this.o.pointers[0].value.prc + "%"} : {top:this.o.pointers[0].value.prc + "%"}); | |
} else { | |
this.o.indicators[2].css(!this.settings.vertical ? {left:this.o.pointers[1].value.prc + "%"} : {top:this.o.pointers[1].value.prc + "%"}); | |
this.o.indicators[0].css(!this.settings.vertical ? {left:0, width:"0"} : {top:0, height:"0"}); | |
this.o.indicators[3].css(!this.settings.vertical ? {left:"0", width:"0"} : {top:"0", height:"0"}); | |
} | |
return false; | |
} | |
this.setValue(); | |
var newPos, | |
newWidth; | |
// redraw range line | |
if(this.o.pointers[0] && this.o.pointers[1]) { | |
newPos = !this.settings.vertical ? | |
{ left: this.o.pointers[0].value.prc + "%", width: ( this.o.pointers[1].value.prc - this.o.pointers[0].value.prc ) + "%" } | |
: | |
{ top: this.o.pointers[0].value.prc + "%", height: ( this.o.pointers[1].value.prc - this.o.pointers[0].value.prc ) + "%" }; | |
this.o.value.css(newPos); | |
// both pointer overlap on limits | |
if (this.o.pointers[0].value.prc === this.o.pointers[1].value.prc) { | |
this.o.pointers[1].ptr.css("z-index", this.o.pointers[0].value.prc === 0 ? '3' : '1'); | |
} | |
} | |
if(this.o.pointers[0] && !this.o.pointers[1]) { | |
newWidth = this.o.pointers[0].value.prc - this.originValue; | |
if (newWidth >= 0) { | |
this.o.indicators[3].css(!this.settings.vertical ? {width: newWidth + "%"} : {height: newWidth + "%"}); | |
} | |
else { | |
this.o.indicators[3].css(!this.settings.vertical ? {width: 0} : {height: 0}); | |
} | |
if (this.o.pointers[0].value.prc < this.originValue) { | |
this.o.indicators[0].css(!this.settings.vertical ? {width: this.o.pointers[0].value.prc + "%"} : {height: this.o.pointers[0].value.prc + "%"}); | |
} | |
else { | |
this.o.indicators[0].css(!this.settings.vertical ? {width: this.originValue + "%"} : {height: this.originValue + "%"}); | |
} | |
} | |
var value = this.nice(pointer.value.origin); | |
if (this.settings.modelLabels) { | |
if (angular.isFunction(this.settings.modelLabels)) { | |
value = this.settings.modelLabels(value); | |
} | |
else { | |
value = this.settings.modelLabels[value] !== undefined ? this.settings.modelLabels[value] : value; | |
} | |
} | |
this.o.labels[pointer.uid].value.html(value); | |
// redraw position of labels | |
this.redrawLabels( pointer ); | |
}; | |
Slider.prototype.redrawLabels = function( pointer ) { | |
function setPosition( label, sizes, prc ) { | |
sizes.margin = -sizes.label/2; | |
var domSize = !self.settings.vertical ? self.sizes.domWidth : self.sizes.domHeight; | |
if (self.sizes.domWidth) { | |
// left limit | |
var label_left = sizes.border + sizes.margin; | |
if(label_left < 0) | |
sizes.margin -= label_left; | |
// right limit | |
if(self.sizes.domWidth > 0 && sizes.border+sizes.label / 2 > domSize){ | |
sizes.margin = 0; | |
sizes.right = true; | |
} else | |
sizes.right = false; | |
} | |
if (!self.settings.vertical) | |
label.o.css({ left: prc + "%", marginLeft: sizes.margin+"px", right: "auto" }); | |
else | |
label.o.css({ top: prc + "%", marginLeft: "20px", marginTop: sizes.margin, bottom: "auto" }); | |
if(sizes.right && self.sizes.domWidth > 0) { | |
if (!self.settings.vertical) | |
label.o.css({ left: "auto", right: 0 }); | |
else | |
label.o.css({ top: "auto", bottom: 0 }); | |
} | |
return sizes; | |
} | |
var self = this, | |
label = this.o.labels[pointer.uid], | |
prc = pointer.value.prc, | |
// case hidden | |
labelWidthSize = label.o[0].offsetWidth === 0 ? (label.o[0].textContent.length)*7 : label.o[0].offsetWidth; | |
this.sizes.domWidth = this.domNode[0].clientWidth; | |
this.sizes.domHeight = this.domNode[0].clientHeight; | |
var sizes = { | |
label: !self.settings.vertical ? labelWidthSize : label.o[0].offsetHeight, | |
right: false, | |
border: (prc * (!self.settings.vertical ? this.sizes.domWidth: this.sizes.domHeight)) / 100 | |
}; | |
var anotherIdx = pointer.uid === 0 ? 1:0, | |
anotherLabel, | |
anotherPtr; | |
if (!this.settings.single && !this.settings.vertical){ | |
// glue if near; | |
anotherLabel = this.o.labels[anotherIdx]; | |
anotherPtr = this.o.pointers[anotherIdx]; | |
var label1 = this.o.labels[0], | |
label2 = this.o.labels[1], | |
ptr1 = this.o.pointers[0], | |
ptr2 = this.o.pointers[1], | |
gapBetweenLabel = ptr2.ptr[0].offsetLeft - ptr1.ptr[0].offsetLeft, | |
value = this.nice(anotherPtr.value.origin); | |
label1.o.css(this.css.visible); | |
label2.o.css(this.css.visible); | |
value = this.getLabelValue(value); | |
if (gapBetweenLabel + 10 < label1.o[0].offsetWidth+label2.o[0].offsetWidth) { | |
anotherLabel.o.css(this.css.hidden); | |
anotherLabel.value.html(value); | |
prc = (anotherPtr.value.prc - prc) / 2 + prc; | |
if(anotherPtr.value.prc != pointer.value.prc){ | |
value = this.nice(this.o.pointers[0].value.origin); | |
var value1 = this.nice(this.o.pointers[1].value.origin); | |
value = this.getLabelValue(value); | |
value1 = this.getLabelValue(value1); | |
label.value.html(value + " – " + value1); | |
sizes.label = label.o[0].offsetWidth; | |
sizes.border = (prc * domSize) / 100; | |
} | |
} | |
else { | |
anotherLabel.value.html(value); | |
anotherLabel.o.css(this.css.visible); | |
} | |
} | |
sizes = setPosition(label, sizes, prc); | |
var domSize = !self.settings.vertical ? self.sizes.domWidth : self.sizes.domHeight; | |
/* draw second label */ | |
if(anotherLabel){ | |
// case hidden | |
var labelWidthSize2 = label.o[0].offsetWidth === 0 ? (label.o[0].textContent.length/2)*7 : label.o[0].offsetWidth, | |
sizes2 = { | |
label: !self.settings.vertical ? labelWidthSize2: anotherLabel.o[0].offsetHeight, | |
right: false, | |
border: (anotherPtr.value.prc * this.sizes.domWidth) / 100 | |
}; | |
sizes = setPosition(anotherLabel, sizes2, anotherPtr.value.prc); | |
} | |
this.redrawLimits(); | |
}; | |
Slider.prototype.redrawLimits = function() { | |
if (this.settings.limits) { | |
var limits = [true, true], | |
i = 0; | |
for(var key in this.o.pointers){ | |
if(!this.settings.single || key === 0){ | |
var pointer = this.o.pointers[key], | |
label = this.o.labels[pointer.uid], | |
label_left = label.o[0].offsetLeft - this.sizes.domOffset.left, | |
limit = this.o.limits[0]; | |
if(label_left < limit[0].clientWidth) { | |
limits[0] = false; | |
} | |
limit = this.o.limits[1]; | |
if(label_left + label.o[0].clientWidth > this.sizes.domWidth - limit[0].clientWidth){ | |
limits[1] = false; | |
} | |
} | |
} | |
for(; i < limits.length; i++){ | |
if(limits[i]){ // TODO animate | |
angular.element(this.o.limits[i]).addClass("animate-show"); | |
} | |
else{ | |
angular.element(this.o.limits[i]).addClass("animate-hidde"); | |
} | |
} | |
} | |
}; | |
Slider.prototype.setValue = function(){ | |
var value = this.getValue(); | |
this.inputNode.attr("value", value); | |
this.onstatechange.call(this, value, this.inputNode); | |
}; | |
Slider.prototype.getValue = function(){ | |
if(!this.is.init) return false; | |
var $this = this; | |
var value = ""; | |
angular.forEach(this.o.pointers, function(pointer, key){ | |
if(pointer.value.prc !== undefined && !isNaN(pointer.value.prc)) | |
value += (key > 0 ? ";" : "") + $this.prcToValue(pointer.value.prc); | |
}); | |
return value; | |
}; | |
Slider.prototype.getLabelValue = function(value){ | |
if (this.settings.modelLabels) { | |
if (angular.isFunction(this.settings.modelLabels)) { | |
return this.settings.modelLabels(value); | |
} | |
else { | |
return this.settings.modelLabels[value] !== undefined ? this.settings.modelLabels[value] : value; | |
} | |
} | |
return value; | |
}; | |
Slider.prototype.getPrcValue = function(){ | |
if(!this.is.init) return false; | |
var $this = this; | |
var value = ""; | |
// TODO remove jquery and see if % value is nice feature | |
/*$.each(this.o.pointers, function(i){ | |
if(this.value.prc !== undefined && !isNaN(this.value.prc)) value += (i > 0 ? ";" : "") + this.value.prc; | |
});*/ | |
return value; | |
}; | |
Slider.prototype.prcToValue = function( prc ){ | |
var value; | |
if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0){ | |
var h = this.settings.heterogeneity, | |
_start = 0, | |
_from = this.settings.round ? parseFloat(this.settings.from) : parseInt(this.settings.from, 10), | |
_to = this.settings.round ? parseFloat(this.settings.to) : parseInt(this.settings.to, 10), | |
i = 0; | |
for (; i <= h.length; i++){ | |
var v; | |
if(h[i]) | |
v = h[i].split('/'); | |
else | |
v = [100, _to]; | |
var v1 = this.settings.round ? parseFloat(v[0]) : parseInt(v[0], 10); | |
var v2 = this.settings.round ? parseFloat(v[1]) : parseInt(v[1], 10); | |
if (prc >= _start && prc <= v1) { | |
value = _from + ((prc-_start) * (v2-_from)) / (v1-_start); | |
} | |
_start = v1; | |
_from = v2; | |
} | |
} | |
else { | |
value = this.settings.from + (prc * this.settings.interval) / 100; | |
} | |
return this.round(value); | |
}; | |
Slider.prototype.valueToPrc = function( value, pointer ){ | |
var prc, | |
_from = this.settings.round ? parseFloat(this.settings.from) : parseInt(this.settings.from, 10); | |
if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0){ | |
var h = this.settings.heterogeneity, | |
_start = 0, | |
i = 0; | |
for (; i <= h.length; i++) { | |
var v; | |
if(h[i]) | |
v = h[i].split('/'); | |
else | |
v = [100, this.settings.to]; | |
var v1 = this.settings.round ? parseFloat(v[0]) : parseInt(v[0], 10); | |
var v2 = this.settings.round ? parseFloat(v[1]) : parseInt(v[1], 10); | |
if(value >= _from && value <= v2){ | |
if (pointer) { | |
prc = pointer.limits(_start + (value-_from)*(v1-_start)/(v2-_from)); | |
} else { | |
prc = this.limits(_start + (value-_from)*(v1-_start)/(v2-_from)); | |
} | |
} | |
_start = v1; _from = v2; | |
} | |
} else { | |
if (pointer) { | |
prc = pointer.limits((value-_from)*100/this.settings.interval); | |
} else { | |
prc = this.limits((value-_from)*100/this.settings.interval); | |
} | |
} | |
return prc; | |
}; | |
Slider.prototype.round = function( value ){ | |
value = Math.round(value / this.settings.step) * this.settings.step; | |
if(this.settings.round) | |
value = Math.round(value * Math.pow(10, this.settings.round)) / Math.pow(10, this.settings.round); | |
else | |
value = Math.round(value); | |
return value; | |
}; | |
return Slider; | |
}]); | |
}(angular));;(function(angular, undefined) { | |
'use strict'; | |
angular.module('angularAwesomeSlider') | |
.run(['$templateCache', function ($templateCache) { | |
$templateCache.put('ng-slider/slider-bar.tmpl.html', | |
'<span ng-class="mainSliderClass" id="{{sliderTmplId}}">' + | |
'<table><tr><td>' + | |
'<div class="jslider-bg">' + | |
'<i class="left"></i>'+ | |
'<i class="right"></i>'+ | |
'<i class="range"></i>'+ | |
'<i class="before"></i>'+ | |
'<i class="default"></i>'+ | |
'<i class="default"></i>'+ | |
'<i class="after"></i>'+ | |
'</div>' + | |
'<div class="jslider-pointer"></div>' + | |
'<div class="jslider-pointer jslider-pointer-to"></div>' + | |
'<div class="jslider-label" ng-show="options.limits"><span ng-bind="limitValue(options.from)"></span>{{options.dimension}}</div>' + | |
'<div class="jslider-label jslider-label-to" ng-show="options.limits"><span ng-bind="limitValue(options.to)"></span>{{options.dimension}}</div>' + | |
'<div class="jslider-value"><span></span>{{options.dimension}}</div>' + | |
'<div class="jslider-value jslider-value-to"><span></span>{{options.dimension}}</div>' + | |
'<div class="jslider-scale" id="{{sliderScaleDivTmplId}}"></div>' + | |
'</td></tr></table>' + | |
'</span>'); | |
}]); | |
})(window.angular); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment