Skip to content

Instantly share code, notes, and snippets.

@kencaron
Created August 7, 2015 04:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kencaron/7c3e64c5251472ea6dd3 to your computer and use it in GitHub Desktop.
Save kencaron/7c3e64c5251472ea6dd3 to your computer and use it in GitHub Desktop.
(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 + "&nbsp;&ndash;&nbsp;" + 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