diff --git a/README.md b/README.md
index c02ff18..5f37e89 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Check out the [demo](http://andreruffert.github.io/rangeslider.js/).
##Browser Support
-* Tested in IE8+
+* Tested in IE8+ and all modern Browsers
##Installation
diff --git a/bower.json b/bower.json
index 2a04bd9..a0c3bd5 100644
--- a/bower.json
+++ b/bower.json
@@ -1,15 +1,18 @@
{
"name": "rangeslider.js",
- "version": "0.2.7",
+ "version": "0.2.8",
"main": "dist/rangeslider.js",
"homepage": "https://github.com/andreruffert/rangeslider.js",
"author": "André Ruffert",
"license": "MIT",
+ "description": "Simple, small and fast JavaScript/jQuery polyfill for the HTML5 slider element",
"keywords": [
"input",
"range",
"slider",
- "rangeslider"
+ "rangeslider",
+ "rangeslider.js",
+ "polyfill"
],
"ignore": [
"**/.*",
diff --git a/dist/rangeslider.js b/dist/rangeslider.js
index 815a782..6049870 100644
--- a/dist/rangeslider.js
+++ b/dist/rangeslider.js
@@ -1,4 +1,4 @@
-/*! rangeslider.js - v0.2.7 | (c) 2014 @andreruffert | MIT license | https://github.com/andreruffert/rangeslider.js */
+/*! rangeslider.js - v0.2.8 | (c) 2014 @andreruffert | MIT license | https://github.com/andreruffert/rangeslider.js */
'use strict';
(function (module) {
@@ -21,31 +21,17 @@
return input.type !== 'text';
}
- /**
- * Touchscreen detection
- * @return {Boolean}
- */
- function isTouchScreen() {
- var bool = false,
- DocumentTouch = DocumentTouch || {};
- if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
- bool = true;
- }
- return bool;
- }
-
var pluginName = 'rangeslider',
pluginInstances = [],
- touchevents = isTouchScreen(),
inputrange = supportsRange(),
defaults = {
polyfill: true,
rangeClass: 'rangeslider',
fillClass: 'rangeslider__fill',
handleClass: 'rangeslider__handle',
- startEvent: ((!touchevents) ? 'mousedown' : 'touchstart') + '.' + pluginName,
- moveEvent: ((!touchevents) ? 'mousemove' : 'touchmove') + '.' + pluginName,
- endEvent: ((!touchevents) ? 'mouseup' : 'touchend') + '.' + pluginName
+ startEvent: ['mousedown', 'touchstart', 'pointerdown'],
+ moveEvent: ['mousemove', 'touchmove', 'pointermove'],
+ endEvent: ['mouseup', 'touchend', 'pointerup']
};
/**
@@ -97,6 +83,9 @@
this.options = $.extend( {}, defaults, options );
this._defaults = defaults;
this._name = pluginName;
+ this.startEvent = this.options.startEvent.join('.' + pluginName + ' ') + '.' + pluginName;
+ this.moveEvent = this.options.moveEvent.join('.' + pluginName + ' ') + '.' + pluginName;
+ this.endEvent = this.options.endEvent.join('.' + pluginName + ' ') + '.' + pluginName;
this.polyfill = this.options.polyfill;
this.onInit = this.options.onInit;
this.onSlide = this.options.onSlide;
@@ -109,9 +98,9 @@
}
this.identifier = 'js-' + pluginName + '-' +(+new Date());
- this.value = parseFloat(this.$element[0].value) || 0;
this.min = parseFloat(this.$element[0].getAttribute('min')) || 0;
this.max = parseFloat(this.$element[0].getAttribute('max')) || 100;
+ this.value = parseFloat(this.$element[0].value) || this.min + (this.max-this.min)/2;
this.step = parseFloat(this.$element[0].getAttribute('step')) || 1;
this.$fill = $('
');
this.$handle = $('');
@@ -140,7 +129,7 @@
delay(function() { _this.update(); }, 300);
}, 20));
- this.$document.on(this.options.startEvent, '#' + this.identifier, this.handleDown);
+ this.$document.on(this.startEvent, '#' + this.identifier, this.handleDown);
// Listen to programmatic value changes
this.$element.on('change' + '.' + pluginName, function(e, data) {
@@ -174,8 +163,8 @@
Plugin.prototype.handleDown = function(e) {
e.preventDefault();
- this.$document.on(this.options.moveEvent, this.handleMove);
- this.$document.on(this.options.endEvent, this.handleEnd);
+ this.$document.on(this.moveEvent, this.handleMove);
+ this.$document.on(this.endEvent, this.handleEnd);
// If we click on the handle don't set the new position
if ((' ' + e.target.className + ' ').replace(/[\n\t]/g, ' ').indexOf(this.options.handleClass) > -1) {
@@ -200,8 +189,8 @@
Plugin.prototype.handleEnd = function(e) {
e.preventDefault();
- this.$document.off(this.options.moveEvent, this.handleMove);
- this.$document.off(this.options.endEvent, this.handleEnd);
+ this.$document.off(this.moveEvent, this.handleMove);
+ this.$document.off(this.endEvent, this.handleEnd);
var posX = this.getRelativePosition(this.$range[0], e);
if (this.onSlideEnd && typeof this.onSlideEnd === 'function') {
@@ -216,14 +205,11 @@
};
Plugin.prototype.setPosition = function(pos) {
- var left = this.cap(pos, 0, this.maxHandleX),
- value = this.getValueFromPosition(left);
+ var value, left;
// Snapping steps
- if (this.step !== 1) {
- left = this.getPositionFromValue(value);
- value = (this.getValueFromPosition(left) / this.step) * this.step;
- }
+ value = (this.getValueFromPosition(this.cap(pos, 0, this.maxHandleX)) / this.step) * this.step;
+ left = this.getPositionFromValue(value);
// Update ui
this.$fill[0].style.width = (left + this.grabX) + 'px';
@@ -271,7 +257,7 @@
};
Plugin.prototype.destroy = function() {
- this.$document.off(this.options.startEvent, '#' + this.identifier, this.handleDown);
+ this.$document.off(this.startEvent, '#' + this.identifier, this.handleDown);
this.$element
.off('.' + pluginName)
.removeAttr('style')
diff --git a/dist/rangeslider.min.js b/dist/rangeslider.min.js
index c5c5e02..06239fa 100644
--- a/dist/rangeslider.min.js
+++ b/dist/rangeslider.min.js
@@ -1,2 +1,2 @@
-/*! rangeslider.js - v0.2.7 | (c) 2014 @andreruffert | MIT license | https://github.com/andreruffert/rangeslider.js */
-"use strict";!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(){var a=document.createElement("input");return a.setAttribute("type","range"),"text"!==a.type}function c(){var a=!1,b=b||{};return("ontouchstart"in window||window.DocumentTouch&&document instanceof b)&&(a=!0),a}function d(a,b){var c=Array.prototype.slice.call(arguments,2);return setTimeout(function(){return a.apply(null,c)},b)}function e(a,b){return b=b||100,function(){if(!a.debouncing){var c=Array.prototype.slice.apply(arguments);a.lastReturnVal=a.apply(window,c),a.debouncing=!0}return clearTimeout(a.debounceTimeout),a.debounceTimeout=setTimeout(function(){a.debouncing=!1},b),a.lastReturnVal}}function f(b,c){if(this.$window=a(window),this.$document=a(document),this.$element=a(b),this.options=a.extend({},k,c),this._defaults=k,this._name=g,this.polyfill=this.options.polyfill,this.onInit=this.options.onInit,this.onSlide=this.options.onSlide,this.onSlideEnd=this.options.onSlideEnd,this.polyfill&&j)return!1;this.identifier="js-"+g+"-"+ +new Date,this.value=parseFloat(this.$element[0].value)||0,this.min=parseFloat(this.$element[0].getAttribute("min"))||0,this.max=parseFloat(this.$element[0].getAttribute("max"))||100,this.step=parseFloat(this.$element[0].getAttribute("step"))||1,this.$fill=a(''),this.$handle=a(''),this.$range=a('').insertBefore(this.$element).prepend(this.$fill,this.$handle),this.$element.css({position:"absolute",width:"1px",height:"1px",overflow:"hidden",visibility:"hidden"}),this.handleDown=a.proxy(this.handleDown,this),this.handleMove=a.proxy(this.handleMove,this),this.handleEnd=a.proxy(this.handleEnd,this),this.init();var f=this;this.$window.on("resize."+g,e(function(){d(function(){f.update()},300)},20)),this.$document.on(this.options.startEvent,"#"+this.identifier,this.handleDown),this.$element.on("change."+g,function(a,b){if(!b||b.origin!==g){var c=a.target.value,d=f.getPositionFromValue(c);f.setPosition(d)}})}var g="rangeslider",h=[],i=c(),j=b(),k={polyfill:!0,rangeClass:"rangeslider",fillClass:"rangeslider__fill",handleClass:"rangeslider__handle",startEvent:(i?"touchstart":"mousedown")+"."+g,moveEvent:(i?"touchmove":"mousemove")+"."+g,endEvent:(i?"touchend":"mouseup")+"."+g};f.prototype.init=function(){this.update(),this.onInit&&"function"==typeof this.onInit&&this.onInit()},f.prototype.update=function(){this.handleWidth=this.$handle[0].offsetWidth,this.rangeWidth=this.$range[0].offsetWidth,this.maxHandleX=this.rangeWidth-this.handleWidth,this.grabX=this.handleWidth/2,this.position=this.getPositionFromValue(this.value),this.setPosition(this.position)},f.prototype.handleDown=function(a){if(a.preventDefault(),this.$document.on(this.options.moveEvent,this.handleMove),this.$document.on(this.options.endEvent,this.handleEnd),!((" "+a.target.className+" ").replace(/[\n\t]/g," ").indexOf(this.options.handleClass)>-1)){var b=this.getRelativePosition(this.$range[0],a),c=this.getPositionFromNode(this.$handle[0])-this.getPositionFromNode(this.$range[0]);this.setPosition(b-this.grabX),b>=c&&ba?b:a>c?c:a},f.prototype.setPosition=function(a){var b=this.cap(a,0,this.maxHandleX),c=this.getValueFromPosition(b);1!==this.step&&(b=this.getPositionFromValue(c),c=this.getValueFromPosition(b)/this.step*this.step),this.$fill[0].style.width=b+this.grabX+"px",this.$handle[0].style.left=b+"px",this.setValue(c),this.position=b,this.value=c,this.onSlide&&"function"==typeof this.onSlide&&this.onSlide(b,c)},f.prototype.getPositionFromNode=function(a){for(var b=0;null!==a;)b+=a.offsetLeft,a=a.offsetParent;return b},f.prototype.getRelativePosition=function(a,b){return(b.pageX||b.originalEvent.clientX||b.originalEvent.touches[0].clientX||b.currentPoint.x)-this.getPositionFromNode(a)},f.prototype.getPositionFromValue=function(a){var b,c;return b=(a-this.min)/(this.max-this.min),c=b*this.maxHandleX},f.prototype.getValueFromPosition=function(a){var b,c;return b=a/this.maxHandleX,c=this.step*Math.ceil((b*(this.max-this.min)+this.min)/this.step),Number(c.toFixed(2))},f.prototype.setValue=function(a){this.$element.val(a).trigger("change",{origin:g})},f.prototype.destroy=function(){this.$document.off(this.options.startEvent,"#"+this.identifier,this.handleDown),this.$element.off("."+g).removeAttr("style").removeData("plugin_"+g),this.$range&&this.$range.length&&this.$range[0].parentNode.removeChild(this.$range[0]),h.splice(h.indexOf(this.$element[0]),1),h.length||this.$window.off("."+g)},a.fn[g]=function(b){return this.each(function(){var c=a(this),d=c.data("plugin_"+g);d||(c.data("plugin_"+g,d=new f(this,b)),h.push(this)),"string"==typeof b&&d[b]()})}});
\ No newline at end of file
+/*! rangeslider.js - v0.2.8 | (c) 2014 @andreruffert | MIT license | https://github.com/andreruffert/rangeslider.js */
+"use strict";!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(){var a=document.createElement("input");return a.setAttribute("type","range"),"text"!==a.type}function c(a,b){var c=Array.prototype.slice.call(arguments,2);return setTimeout(function(){return a.apply(null,c)},b)}function d(a,b){return b=b||100,function(){if(!a.debouncing){var c=Array.prototype.slice.apply(arguments);a.lastReturnVal=a.apply(window,c),a.debouncing=!0}return clearTimeout(a.debounceTimeout),a.debounceTimeout=setTimeout(function(){a.debouncing=!1},b),a.lastReturnVal}}function e(b,e){if(this.$window=a(window),this.$document=a(document),this.$element=a(b),this.options=a.extend({},i,e),this._defaults=i,this._name=f,this.startEvent=this.options.startEvent.join("."+f+" ")+"."+f,this.moveEvent=this.options.moveEvent.join("."+f+" ")+"."+f,this.endEvent=this.options.endEvent.join("."+f+" ")+"."+f,this.polyfill=this.options.polyfill,this.onInit=this.options.onInit,this.onSlide=this.options.onSlide,this.onSlideEnd=this.options.onSlideEnd,this.polyfill&&h)return!1;this.identifier="js-"+f+"-"+ +new Date,this.min=parseFloat(this.$element[0].getAttribute("min"))||0,this.max=parseFloat(this.$element[0].getAttribute("max"))||100,this.value=parseFloat(this.$element[0].value)||this.min+(this.max-this.min)/2,this.step=parseFloat(this.$element[0].getAttribute("step"))||1,this.$fill=a(''),this.$handle=a(''),this.$range=a('').insertBefore(this.$element).prepend(this.$fill,this.$handle),this.$element.css({position:"absolute",width:"1px",height:"1px",overflow:"hidden",visibility:"hidden"}),this.handleDown=a.proxy(this.handleDown,this),this.handleMove=a.proxy(this.handleMove,this),this.handleEnd=a.proxy(this.handleEnd,this),this.init();var g=this;this.$window.on("resize."+f,d(function(){c(function(){g.update()},300)},20)),this.$document.on(this.startEvent,"#"+this.identifier,this.handleDown),this.$element.on("change."+f,function(a,b){if(!b||b.origin!==f){var c=a.target.value,d=g.getPositionFromValue(c);g.setPosition(d)}})}var f="rangeslider",g=[],h=b(),i={polyfill:!0,rangeClass:"rangeslider",fillClass:"rangeslider__fill",handleClass:"rangeslider__handle",startEvent:["mousedown","touchstart","pointerdown"],moveEvent:["mousemove","touchmove","pointermove"],endEvent:["mouseup","touchend","pointerup"]};e.prototype.init=function(){this.update(),this.onInit&&"function"==typeof this.onInit&&this.onInit()},e.prototype.update=function(){this.handleWidth=this.$handle[0].offsetWidth,this.rangeWidth=this.$range[0].offsetWidth,this.maxHandleX=this.rangeWidth-this.handleWidth,this.grabX=this.handleWidth/2,this.position=this.getPositionFromValue(this.value),this.setPosition(this.position)},e.prototype.handleDown=function(a){if(a.preventDefault(),this.$document.on(this.moveEvent,this.handleMove),this.$document.on(this.endEvent,this.handleEnd),!((" "+a.target.className+" ").replace(/[\n\t]/g," ").indexOf(this.options.handleClass)>-1)){var b=this.getRelativePosition(this.$range[0],a),c=this.getPositionFromNode(this.$handle[0])-this.getPositionFromNode(this.$range[0]);this.setPosition(b-this.grabX),b>=c&&ba?b:a>c?c:a},e.prototype.setPosition=function(a){var b,c;b=this.getValueFromPosition(this.cap(a,0,this.maxHandleX))/this.step*this.step,c=this.getPositionFromValue(b),this.$fill[0].style.width=c+this.grabX+"px",this.$handle[0].style.left=c+"px",this.setValue(b),this.position=c,this.value=b,this.onSlide&&"function"==typeof this.onSlide&&this.onSlide(c,b)},e.prototype.getPositionFromNode=function(a){for(var b=0;null!==a;)b+=a.offsetLeft,a=a.offsetParent;return b},e.prototype.getRelativePosition=function(a,b){return(b.pageX||b.originalEvent.clientX||b.originalEvent.touches[0].clientX||b.currentPoint.x)-this.getPositionFromNode(a)},e.prototype.getPositionFromValue=function(a){var b,c;return b=(a-this.min)/(this.max-this.min),c=b*this.maxHandleX},e.prototype.getValueFromPosition=function(a){var b,c;return b=a/this.maxHandleX,c=this.step*Math.ceil((b*(this.max-this.min)+this.min)/this.step),Number(c.toFixed(2))},e.prototype.setValue=function(a){this.$element.val(a).trigger("change",{origin:f})},e.prototype.destroy=function(){this.$document.off(this.startEvent,"#"+this.identifier,this.handleDown),this.$element.off("."+f).removeAttr("style").removeData("plugin_"+f),this.$range&&this.$range.length&&this.$range[0].parentNode.removeChild(this.$range[0]),g.splice(g.indexOf(this.$element[0]),1),g.length||this.$window.off("."+f)},a.fn[f]=function(b){return this.each(function(){var c=a(this),d=c.data("plugin_"+f);d||(c.data("plugin_"+f,d=new e(this,b)),g.push(this)),"string"==typeof b&&d[b]()})}});
\ No newline at end of file
diff --git a/example/index.html b/example/index.html
index 337af5c..ef2e507 100644
--- a/example/index.html
+++ b/example/index.html
@@ -29,9 +29,20 @@
+
+
+
+
+
+
+
+
+
+
+
Programmatic value changes
-
+
diff --git a/package.json b/package.json
index 3c9a576..1cdfdbf 100644
--- a/package.json
+++ b/package.json
@@ -2,14 +2,16 @@
"name": "rangeslider.js",
"title": "rangeslider.js",
"description": "Simple, small and fast JavaScript/jQuery polyfill for the HTML5 slider element",
- "version": "0.2.7",
+ "version": "0.2.8",
"homepage": "https://github.com/andreruffert/rangeslider.js",
"license": "MIT",
"keywords": [
"input",
"range",
"slider",
- "rangeslider"
+ "rangeslider",
+ "rangeslider.js",
+ "polyfill"
],
"author": {
"name": "André Ruffert",
diff --git a/src/rangeslider.js b/src/rangeslider.js
index 93ad8db..fa7aa83 100644
--- a/src/rangeslider.js
+++ b/src/rangeslider.js
@@ -20,31 +20,17 @@
return input.type !== 'text';
}
- /**
- * Touchscreen detection
- * @return {Boolean}
- */
- function isTouchScreen() {
- var bool = false,
- DocumentTouch = DocumentTouch || {};
- if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
- bool = true;
- }
- return bool;
- }
-
var pluginName = 'rangeslider',
pluginInstances = [],
- touchevents = isTouchScreen(),
inputrange = supportsRange(),
defaults = {
polyfill: true,
rangeClass: 'rangeslider',
fillClass: 'rangeslider__fill',
handleClass: 'rangeslider__handle',
- startEvent: ((!touchevents) ? 'mousedown' : 'touchstart') + '.' + pluginName,
- moveEvent: ((!touchevents) ? 'mousemove' : 'touchmove') + '.' + pluginName,
- endEvent: ((!touchevents) ? 'mouseup' : 'touchend') + '.' + pluginName
+ startEvent: ['mousedown', 'touchstart', 'pointerdown'],
+ moveEvent: ['mousemove', 'touchmove', 'pointermove'],
+ endEvent: ['mouseup', 'touchend', 'pointerup']
};
/**
@@ -96,6 +82,9 @@
this.options = $.extend( {}, defaults, options );
this._defaults = defaults;
this._name = pluginName;
+ this.startEvent = this.options.startEvent.join('.' + pluginName + ' ') + '.' + pluginName;
+ this.moveEvent = this.options.moveEvent.join('.' + pluginName + ' ') + '.' + pluginName;
+ this.endEvent = this.options.endEvent.join('.' + pluginName + ' ') + '.' + pluginName;
this.polyfill = this.options.polyfill;
this.onInit = this.options.onInit;
this.onSlide = this.options.onSlide;
@@ -108,9 +97,9 @@
}
this.identifier = 'js-' + pluginName + '-' +(+new Date());
- this.value = parseFloat(this.$element[0].value) || 0;
this.min = parseFloat(this.$element[0].getAttribute('min')) || 0;
this.max = parseFloat(this.$element[0].getAttribute('max')) || 100;
+ this.value = parseFloat(this.$element[0].value) || this.min + (this.max-this.min)/2;
this.step = parseFloat(this.$element[0].getAttribute('step')) || 1;
this.$fill = $('');
this.$handle = $('');
@@ -139,7 +128,7 @@
delay(function() { _this.update(); }, 300);
}, 20));
- this.$document.on(this.options.startEvent, '#' + this.identifier, this.handleDown);
+ this.$document.on(this.startEvent, '#' + this.identifier, this.handleDown);
// Listen to programmatic value changes
this.$element.on('change' + '.' + pluginName, function(e, data) {
@@ -173,8 +162,8 @@
Plugin.prototype.handleDown = function(e) {
e.preventDefault();
- this.$document.on(this.options.moveEvent, this.handleMove);
- this.$document.on(this.options.endEvent, this.handleEnd);
+ this.$document.on(this.moveEvent, this.handleMove);
+ this.$document.on(this.endEvent, this.handleEnd);
// If we click on the handle don't set the new position
if ((' ' + e.target.className + ' ').replace(/[\n\t]/g, ' ').indexOf(this.options.handleClass) > -1) {
@@ -199,8 +188,8 @@
Plugin.prototype.handleEnd = function(e) {
e.preventDefault();
- this.$document.off(this.options.moveEvent, this.handleMove);
- this.$document.off(this.options.endEvent, this.handleEnd);
+ this.$document.off(this.moveEvent, this.handleMove);
+ this.$document.off(this.endEvent, this.handleEnd);
var posX = this.getRelativePosition(this.$range[0], e);
if (this.onSlideEnd && typeof this.onSlideEnd === 'function') {
@@ -215,14 +204,11 @@
};
Plugin.prototype.setPosition = function(pos) {
- var left = this.cap(pos, 0, this.maxHandleX),
- value = this.getValueFromPosition(left);
+ var value, left;
// Snapping steps
- if (this.step !== 1) {
- left = this.getPositionFromValue(value);
- value = (this.getValueFromPosition(left) / this.step) * this.step;
- }
+ value = (this.getValueFromPosition(this.cap(pos, 0, this.maxHandleX)) / this.step) * this.step;
+ left = this.getPositionFromValue(value);
// Update ui
this.$fill[0].style.width = (left + this.grabX) + 'px';
@@ -270,7 +256,7 @@
};
Plugin.prototype.destroy = function() {
- this.$document.off(this.options.startEvent, '#' + this.identifier, this.handleDown);
+ this.$document.off(this.startEvent, '#' + this.identifier, this.handleDown);
this.$element
.off('.' + pluginName)
.removeAttr('style')