(function(factory){
'use strict';
if(typeof define==='function'&&define.amd){
define(['jquery'], factory);
}else if(typeof exports==='object'){
module.exports=factory(require('jquery'));
}else{
factory(jQuery);
}}(function($){
'use strict';
Number.isNaN=Number.isNaN||function(value){
return typeof value==='number'&&value!==value;
};
function supportsRange(){
var input=document.createElement('input');
input.setAttribute('type', 'range');
return input.type!=='text';
}
var pluginName='rangeslider',
pluginIdentifier=0,
hasInputRangeSupport=supportsRange(),
defaults={
polyfill: true,
orientation: 'horizontal',
rangeClass: 'rangeslider',
disabledClass: 'rangeslider--disabled',
activeClass: 'rangeslider--active',
horizontalClass: 'rangeslider--horizontal',
verticalClass: 'rangeslider--vertical',
dirRTLClass:'rangeslider__rtl',
dirTTBClass:'rangeslider__ttb',
fillClass: 'rangeslider__fill',
handleClass: 'rangeslider__handle',
startEvent: ['mousedown', 'touchstart', 'pointerdown'],
moveEvent: ['mousemove', 'touchmove', 'pointermove'],
endEvent: ['mouseup', 'touchend', 'pointerup']
},
constants={
orientation: {
horizontal: {
dimension: 'width',
direction: { ltr: 'left', rtl: 'right'},
directionStyle: { ltr: 'left', rtl: 'right' },
coordinate: 'x'
},
vertical: {
dimension: 'height',
direction: { btt:'top', ttb:'bottom' },
directionStyle: { btt:'bottom', ttb:'top' },
coordinate: 'y'
}}
};
function delay(fn, wait){
var args=Array.prototype.slice.call(arguments, 2);
return setTimeout(function(){ return fn.apply(null, args); }, wait);
}
function debounce(fn, debounceDuration){
debounceDuration=debounceDuration||100;
return function(){
if(!fn.debouncing){
var args=Array.prototype.slice.apply(arguments);
fn.lastReturnVal=fn.apply(window, args);
fn.debouncing=true;
}
clearTimeout(fn.debounceTimeout);
fn.debounceTimeout=setTimeout(function(){
fn.debouncing=false;
}, debounceDuration);
return fn.lastReturnVal;
};}
function isHidden(element){
return (
element&&(
element.offsetWidth===0 ||
element.offsetHeight===0 ||
element.open===false
)
);
}
function getHiddenParentNodes(element){
var parents=[],
node=element.parentNode;
while (isHidden(node)){
parents.push(node);
node=node.parentNode;
}
return parents;
}
function getDimension(element, key){
var hiddenParentNodes=getHiddenParentNodes(element),
hiddenParentNodesLength=hiddenParentNodes.length,
inlineStyle=[],
dimension=element[key];
function toggleOpenProperty(element){
if(typeof element.open!=='undefined'){
element.open=(element.open) ? false:true;
}}
if(hiddenParentNodesLength){
for (var i=0; i < hiddenParentNodesLength; i++){
inlineStyle[i]=hiddenParentNodes[i].style.cssText;
if(hiddenParentNodes[i].style.setProperty){
hiddenParentNodes[i].style.setProperty('display', 'block', 'important');
}else{
hiddenParentNodes[i].style.cssText +=';display: block !important';
}
hiddenParentNodes[i].style.height='0';
hiddenParentNodes[i].style.overflow='hidden';
hiddenParentNodes[i].style.visibility='hidden';
toggleOpenProperty(hiddenParentNodes[i]);
}
dimension=element[key];
for (var j=0; j < hiddenParentNodesLength; j++){
hiddenParentNodes[j].style.cssText=inlineStyle[j];
toggleOpenProperty(hiddenParentNodes[j]);
}}
return dimension;
}
function tryParseFloat(str, defaultValue){
var value=parseFloat(str);
return Number.isNaN(value) ? defaultValue:value;
}
function ucfirst(str){
return str.charAt(0).toUpperCase() + str.substr(1);
}
function getDirection(element, orientation){
var direction=element[0].getAttribute('data-direction')||(orientation==='vertical' ? 'btt':'ltr');
if(constants.orientation[orientation].direction[direction]){
return direction;
}else{
return orientation==='vertical' ? 'btt':'ltr';
}}
function Plugin(element, options){
this.$window=$(window);
this.$document=$(document);
this.$element=$(element);
this.options=$.extend({}, defaults, options);
this.polyfill=this.options.polyfill;
this.orientation=this.$element[0].getAttribute('data-orientation')||this.options.orientation;
this.dir=getDirection(this.$element,this.orientation);
this.onInit=this.options.onInit;
this.onSlide=this.options.onSlide;
this.onSlideEnd=this.options.onSlideEnd;
this.DIMENSION=constants.orientation[this.orientation].dimension;
this.DIRECTION=constants.orientation[this.orientation].direction[this.dir];
this.DIRECTION_STYLE=constants.orientation[this.orientation].directionStyle[this.dir];
this.COORDINATE=constants.orientation[this.orientation].coordinate;
if(this.polyfill){
if(hasInputRangeSupport){ return false; }}
this.identifier='js-' + pluginName + '-' +(pluginIdentifier++);
this.startEvent=this.options.startEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
this.moveEvent=this.options.moveEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
this.endEvent=this.options.endEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
this.toFixed=(this.step + '').replace('.', '').length - 1;
this.$fill=$('<div class="' + this.options.fillClass +' '+(this.dir==='ttb'&&this.orientation==='vertical'? this.options.dirTTBClass: '') +'" />');
this.$handle=$('<div class="' + this.options.handleClass + '" />');
this.$range=$('<div class="' + this.options.rangeClass +' ' +(this.dir==='rtl'&&this.orientation==='horizontal'? this.options.dirRTLClass: '') + ' ' + this.options[this.orientation + 'Class'] + '" id="' + this.identifier + '" />').insertAfter(this.$element).prepend(this.$fill, this.$handle);
this.$element.css({
'position': 'absolute',
'width': '1px',
'height': '1px',
'overflow': 'hidden',
'opacity': '0'
});
this.handleDown=$.proxy(this.handleDown, this);
this.handleMove=$.proxy(this.handleMove, this);
this.handleEnd=$.proxy(this.handleEnd, this);
this.init();
var _this=this;
this.$window.on('resize.' + this.identifier, debounce(function(){
delay(function(){ _this.update(false, false); }, 300);
}, 20));
this.$document.on(this.startEvent, '#' + this.identifier + ':not(.' + this.options.disabledClass + ')', this.handleDown);
this.$element.on('change.' + this.identifier, function(e, data){
if(data&&data.origin===_this.identifier){
return;
}
var value=e.target.value,
pos=_this.getPositionFromValue(value);
_this.setPosition(pos);
});
}
Plugin.prototype.init=function(){
this.update(true, false);
if(this.onInit&&typeof this.onInit==='function'){
this.onInit();
}};
Plugin.prototype.update=function(updateAttributes, triggerSlide){
updateAttributes=updateAttributes||false;
if(updateAttributes){
this.min=tryParseFloat(this.$element[0].getAttribute('min'), 0);
this.max=tryParseFloat(this.$element[0].getAttribute('max'), 100);
this.value=tryParseFloat(this.$element[0].value, Math.round(this.min + (this.max-this.min)/2));
this.step=tryParseFloat(this.$element[0].getAttribute('step'), 1);
}
this.handleDimension=getDimension(this.$handle[0], 'offset' + ucfirst(this.DIMENSION));
this.rangeDimension=getDimension(this.$range[0], 'offset' + ucfirst(this.DIMENSION));
this.maxHandlePos=this.rangeDimension - this.handleDimension;
this.grabPos=this.handleDimension / 2;
this.position=this.getPositionFromValue(this.value);
if(this.$element[0].disabled){
this.$range.addClass(this.options.disabledClass);
}else{
this.$range.removeClass(this.options.disabledClass);
}
this.setPosition(this.position, triggerSlide);
};
Plugin.prototype.handleDown=function(e){
e.preventDefault();
if(e.button&&e.button!==0){ return; }
this.$document.on(this.moveEvent, this.handleMove);
this.$document.on(this.endEvent, this.handleEnd);
this.$range.addClass(this.options.activeClass);
if((' ' + e.target.className + ' ').replace(/[\n\t]/g, ' ').indexOf(this.options.handleClass) > -1){
return;
}
var pos=this.getRelativePosition(e),
rangePos=this.$range[0].getBoundingClientRect()[this.DIRECTION],
handlePos=this.getPositionFromNode(this.$handle[0]) - rangePos,
setPos=(this.orientation==='vertical') ? (this.maxHandlePos - (pos - this.grabPos)):(pos - this.grabPos);
this.setPosition(setPos);
if(pos >=handlePos&&pos < handlePos + this.handleDimension){
this.grabPos=pos - handlePos;
}};
Plugin.prototype.handleMove=function(e){
e.preventDefault();
var pos=this.getRelativePosition(e);
var setPos=(this.orientation==='vertical') ? (this.maxHandlePos - (pos - this.grabPos)):(pos - this.grabPos);
this.setPosition(setPos);
};
Plugin.prototype.handleEnd=function(e){
e.preventDefault();
this.$document.off(this.moveEvent, this.handleMove);
this.$document.off(this.endEvent, this.handleEnd);
this.$range.removeClass(this.options.activeClass);
this.$element.trigger('change', { origin: this.identifier });
if(this.onSlideEnd&&typeof this.onSlideEnd==='function'){
this.onSlideEnd(this.position, this.value);
}};
Plugin.prototype.cap=function(pos, min, max){
if(pos < min){ return min; }
if(pos > max){ return max; }
return pos;
};
Plugin.prototype.setPosition=function(pos, triggerSlide){
var value, newPos;
if(triggerSlide===undefined){
triggerSlide=true;
}
value=this.getValueFromPosition(this.cap(pos, 0, this.maxHandlePos));
newPos=this.getPositionFromValue(value);
this.$fill[0].style[this.DIMENSION]=(newPos + this.grabPos) + 'px';
this.$handle[0].style[this.DIRECTION_STYLE]=newPos + 'px';
this.setValue(value);
this.position=newPos;
this.value=value;
if(triggerSlide&&this.onSlide&&typeof this.onSlide==='function'){
this.onSlide(newPos, value);
}};
Plugin.prototype.getPositionFromNode=function(node){
var i=0;
while (node!==null){
i +=node.offsetLeft;
node=node.offsetParent;
}
return i;
};
Plugin.prototype.getRelativePosition=function(e){
var ucCoordinate=ucfirst(this.COORDINATE),
rangePos=this.$range[0].getBoundingClientRect()[this.DIRECTION],
pageCoordinate=0;
if(typeof e.originalEvent['client' + ucCoordinate]!=='undefined'){
pageCoordinate=e.originalEvent['client' + ucCoordinate];
}
else if(e.originalEvent.touches &&
e.originalEvent.touches[0] &&
typeof e.originalEvent.touches[0]['client' + ucCoordinate]!=='undefined'
){
pageCoordinate=e.originalEvent.touches[0]['client' + ucCoordinate];
}
else if(e.currentPoint&&typeof e.currentPoint[this.COORDINATE]!=='undefined'){
pageCoordinate=e.currentPoint[this.COORDINATE];
}
return (this.dir==='rtl'||this.dir==='ttb') ? rangePos - pageCoordinate:pageCoordinate - rangePos;
};
Plugin.prototype.getPositionFromValue=function(value){
var percentage, pos;
percentage=(value - this.min)/(this.max - this.min);
pos=(!Number.isNaN(percentage)) ? percentage * this.maxHandlePos:0;
return pos;
};
Plugin.prototype.getValueFromPosition=function(pos){
var percentage, value;
percentage=((pos) / (this.maxHandlePos||1));
value=this.step * Math.round(percentage * (this.max - this.min) / this.step) + this.min;
return Number((value).toFixed(this.toFixed));
};
Plugin.prototype.setValue=function(value){
if(value===this.value&&this.$element[0].value!==''){
return;
}
this.$element
.val(value)
.trigger('input', { origin: this.identifier });
};
Plugin.prototype.destroy=function(){
this.$document.off('.' + this.identifier);
this.$window.off('.' + this.identifier);
this.$element
.off('.' + this.identifier)
.removeAttr('style')
.removeData('plugin_' + pluginName);
if(this.$range&&this.$range.length){
this.$range[0].parentNode.removeChild(this.$range[0]);
}};
$.fn[pluginName]=function(options){
var args=Array.prototype.slice.call(arguments, 1);
return this.each(function(){
var $this=$(this),
data=$this.data('plugin_' + pluginName);
if(!data){
$this.data('plugin_' + pluginName, (data=new Plugin(this, options)));
}
if(typeof options==='string'){
data[options].apply(data, args);
}});
};
return 'rangeslider.js is available in jQuery context e.g $(selector).rangeslider(options);';
}));