Socket
Socket
Sign inDemoInstall

rangetouch

Package Overview
Dependencies
0
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.6 to 2.0.0-beta.1

.eslintrc.json

1

.vscode/extensions.json

@@ -9,4 +9,5 @@ {

"esbenp.prettier-vscode",
"shinnn.stylelint",
"wayou.vscode-todo-highlight"
]
}
# Changelog
## v2.0.0
- Rewritten using ES6 syntax and a proper `RangeTouch` class
- No longer using event delegation do to compatibility issues
## v1.0.6

@@ -4,0 +9,0 @@

2

dist/rangetouch.js

@@ -1,1 +0,1 @@

!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=t(e,document):"function"==typeof define&&define.amd?define(null,function(){t(e,document)}):e.rangetouch=t(e,document)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n={enabled:!0,addCSS:!0,thumbWidth:15,selectors:{range:'[type="range"]',disabled:".rangetouch--disabled"},events:{start:"touchstart",move:"touchmove",end:"touchend"}};function o(e,t,n){e.addEventListener(t,n,!1)}function a(e,t){if(t<1){var n=(o=(""+t).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/))?Math.max(0,(o[1]?o[1].length:0)-(o[2]?+o[2]:0)):0;return parseFloat(e.toFixed(n))}var o;return Math.round(e/t)*t}function d(o){var d;n.enabled&&"range"===o.target.type&&((d=o.target)instanceof HTMLElement&&!d.matches(n.selectors.disabled)&&!d.disabled)&&(o.preventDefault(),o.target.value=function(e){var t,o=e.target,d=e.changedTouches[0],i=parseFloat(o.getAttribute("min"))||0,r=parseFloat(o.getAttribute("max"))||100,u=parseFloat(o.getAttribute("step"))||1,s=r-i,c=o.getBoundingClientRect(),l=100/c.width*(n.thumbWidth/2)/100;return(t=100/c.width*(d.clientX-c.left))<0?t=0:t>100&&(t=100),t<50?t-=(100-2*t)*l:t>50&&(t+=2*(t-50)*l),i+a(s*(t/100),u)}(o),function(n,o,a){if(n&&o){var d;"function"==typeof e.CustomEvent?d=e.CustomEvent:(d=function(e,n){n=n||{bubbles:!1,cancelable:!1,detail:void 0};var o=t.createEvent("CustomEvent");return o.initCustomEvent(e,n.bubbles,n.cancelable,n.detail),o}).prototype=e.Event.prototype;var i=new d(o,{bubbles:!0,detail:a});n.dispatchEvent(i)}}(o.target,o.type===n.events.end?"change":"input"))}return function(){if("ontouchstart"in t.documentElement){var e;n.addCSS&&((e=t.createElement("style")).appendChild(t.createTextNode("")),t.head.appendChild(e),e.sheet).insertRule([n.selectors.range,":not(",n.selectors.disabled,")"].join("")+" { user-select: none; -webkit-user-select: none; touch-action: manipulation; }",0),o(t.body,n.events.start,d),o(t.body,n.events.move,d),o(t.body,n.events.end,d)}}(),{set:function(e,t){n[e]=t}}});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("RangeTouch",t):e.RangeTouch=t()}(this,function(){"use strict";function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var t=function(e){return null!=e?e.constructor:null},n=function(e,t){return!!(e&&t&&e instanceof t)},r=function(e){return null==e},u=function(e){return t(e)===Object},i=function(e){return t(e)===String},o=function(e){return Array.isArray(e)},a=function(e){return n(e,NodeList)},c={nullOrUndefined:r,object:u,number:function(e){return t(e)===Number&&!Number.isNaN(e)},string:i,boolean:function(e){return t(e)===Boolean},function:function(e){return t(e)===Function},array:o,nodeList:a,element:function(e){return n(e,Element)},event:function(e){return n(e,Event)},empty:function(e){return r(e)||(i(e)||o(e)||a(e))&&!e.length||u(e)&&!Object.keys(e).length}};function l(e,t){if(1>t){var n=function(e){var t="".concat(e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0}(t);return parseFloat(e.toFixed(n))}return Math.round(e/t)*t}var s={addCSS:!0,thumbWidth:15,watch:!0};return function(){function t(e,n){(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")})(this,t),c.element(e)?this.element=e:c.string(e)&&(this.element=document.querySelector(e)),c.element(this.element)&&c.empty(this.element.rangeTouch)&&(this.config=Object.assign({},s,n),this.init())}return n=t,u=[{key:"setup",value:function(e){var n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},r=null;if(c.empty(e)||c.string(e)?r=Array.from(document.querySelectorAll(c.string(e)?e:'input[type="range"]')):c.element(e)?r=[e]:c.nodeList(e)?r=Array.from(e):c.array(e)&&(r=e.filter(c.element)),c.empty(r))return null;var u=Object.assign({},s,n);c.string(e)&&u.watch&&new MutationObserver(function(n){Array.from(n).forEach(function(n){Array.from(n.addedNodes).forEach(function(n){c.element(n)&&function(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}(n,e)&&new t(n,u)})})}).observe(document.body,{childList:!0,subtree:!0});return r.map(function(e){return new t(e,n)})}},{key:"enabled",get:function(){return"ontouchstart"in document.documentElement}}],(r=[{key:"init",value:function(){t.enabled&&(this.config.addCSS&&(this.element.style.userSelect="none",this.element.style.webKitUserSelect="none",this.element.style.touchAction="manipulation"),this.listeners(!0),this.element.rangeTouch=this)}},{key:"destroy",value:function(){t.enabled&&(this.listeners(!1),this.element.rangeTouch=null)}},{key:"listeners",value:function(e){var t=this,n=e?"addEventListener":"removeEventListener";["touchstart","touchmove","touchend"].forEach(function(e){t.element[n](e,function(e){return t.set(e)},!1)})}},{key:"get",value:function(e){if(!t.enabled||!c.event(e))return null;var n,r=e.target,u=e.changedTouches[0],i=parseFloat(r.getAttribute("min"))||0,o=parseFloat(r.getAttribute("max"))||100,a=parseFloat(r.getAttribute("step"))||1,s=r.getBoundingClientRect(),f=100/s.width*(this.config.thumbWidth/2)/100;return 0>(n=100/s.width*(u.clientX-s.left))?n=0:100<n&&(n=100),50>n?n-=(100-2*n)*f:50<n&&(n+=2*(n-50)*f),i+l(n/100*(o-i),a)}},{key:"set",value:function(e){t.enabled&&c.event(e)&&!e.target.disabled&&(e.preventDefault(),e.target.value=this.get(e),function(e,t){if(e&&t){var n=new Event(t);e.dispatchEvent(n)}}(e.target,"touchend"===e.type?"change":"input"))}}])&&e(n.prototype,r),u&&e(n,u),t;var n,r,u}()});

@@ -1,1 +0,1 @@

!function(){"use strict";function e(e){var n=new XMLHttpRequest,t=document.body;if("withCredentials"in n)n.open("GET",e,!0);else{if("function"!=typeof XDomainRequest)return;(n=new XDomainRequest).open("GET",e)}n.onload=function(){var e=document.createElement("div");e.setAttribute("hidden",""),e.innerHTML=n.responseText,t.insertBefore(e,t.childNodes[0])},setTimeout(function(){n.send()},0)}var n,t,o,a,i,c;window.loadSprites=function(n){n.forEach(e)},shr.setup({count:{classname:"btn__count"}}),window.rangetouch.set("thumbWidth",20),document.domain.indexOf("rangetouch.com")>-1&&(n=window,t=document,o="script",a="ga",n.GoogleAnalyticsObject=a,n.ga=n.ga||function(){(n.ga.q=n.ga.q||[]).push(arguments)},n.ga.l=1*new Date,i=t.createElement(o),c=t.getElementsByTagName(o)[0],i.async=1,i.src="//www.google-analytics.com/analytics.js",c.parentNode.insertBefore(i,c),ga("create","UA-40881672-15","auto"),ga("send","pageview"))}();
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define("RangeTouch",t):t()}(0,function(){"use strict";function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var t=function(e){return null!=e?e.constructor:null},n=function(e,t){return!!(e&&t&&e instanceof t)},r=function(e){return null==e},i=function(e){return t(e)===Object},u=function(e){return t(e)===String},o=function(e){return Array.isArray(e)},c=function(e){return n(e,NodeList)},a={nullOrUndefined:r,object:i,number:function(e){return t(e)===Number&&!Number.isNaN(e)},string:u,boolean:function(e){return t(e)===Boolean},function:function(e){return t(e)===Function},array:o,nodeList:c,element:function(e){return n(e,Element)},event:function(e){return n(e,Event)},empty:function(e){return r(e)||(u(e)||o(e)||c(e))&&!e.length||i(e)&&!Object.keys(e).length}};function l(e,t){if(1>t){var n=function(e){var t="".concat(e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0}(t);return parseFloat(e.toFixed(n))}return Math.round(e/t)*t}var s={addCSS:!0,thumbWidth:15,watch:!0},f=function(){function t(e,n){(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")})(this,t),a.element(e)?this.element=e:a.string(e)&&(this.element=document.querySelector(e)),a.element(this.element)&&a.empty(this.element.rangeTouch)&&(this.config=Object.assign({},s,n),this.init())}return n=t,i=[{key:"setup",value:function(e){var n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},r=null;if(a.empty(e)||a.string(e)?r=Array.from(document.querySelectorAll(a.string(e)?e:'input[type="range"]')):a.element(e)?r=[e]:a.nodeList(e)?r=Array.from(e):a.array(e)&&(r=e.filter(a.element)),a.empty(r))return null;var i=Object.assign({},s,n);a.string(e)&&i.watch&&new MutationObserver(function(n){Array.from(n).forEach(function(n){Array.from(n.addedNodes).forEach(function(n){a.element(n)&&function(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}(n,e)&&new t(n,i)})})}).observe(document.body,{childList:!0,subtree:!0});return r.map(function(e){return new t(e,n)})}},{key:"enabled",get:function(){return"ontouchstart"in document.documentElement}}],(r=[{key:"init",value:function(){t.enabled&&(this.config.addCSS&&(this.element.style.userSelect="none",this.element.style.webKitUserSelect="none",this.element.style.touchAction="manipulation"),this.listeners(!0),this.element.rangeTouch=this)}},{key:"destroy",value:function(){t.enabled&&(this.listeners(!1),this.element.rangeTouch=null)}},{key:"listeners",value:function(e){var t=this,n=e?"addEventListener":"removeEventListener";["touchstart","touchmove","touchend"].forEach(function(e){t.element[n](e,function(e){return t.set(e)},!1)})}},{key:"get",value:function(e){if(!t.enabled||!a.event(e))return null;var n,r=e.target,i=e.changedTouches[0],u=parseFloat(r.getAttribute("min"))||0,o=parseFloat(r.getAttribute("max"))||100,c=parseFloat(r.getAttribute("step"))||1,s=r.getBoundingClientRect(),f=100/s.width*(this.config.thumbWidth/2)/100;return 0>(n=100/s.width*(i.clientX-s.left))?n=0:100<n&&(n=100),50>n?n-=(100-2*n)*f:50<n&&(n+=2*(n-50)*f),u+l(n/100*(o-u),c)}},{key:"set",value:function(e){t.enabled&&a.event(e)&&!e.target.disabled&&(e.preventDefault(),e.target.value=this.get(e),function(e,t){if(e&&t){var n=new Event(t);e.dispatchEvent(n)}}(e.target,"touchend"===e.type?"change":"input"))}}])&&e(n.prototype,r),i&&e(n,i),t;var n,r,i}();document.addEventListener("DOMContentLoaded",function(){["dist/docs.svg"].forEach(function(e){var t=new XMLHttpRequest,n=document.body;"withCredentials"in t&&(t.open("GET",e,!0),t.onload=function(){var e=document.createElement("div");e.setAttribute("hidden",""),e.innerHTML=t.responseText,n.insertBefore(e,n.childNodes[0])},t.send())}),window.shr.setup({count:{classname:"btn__count"}}),f.setup(".js-example",{thumbWidth:20})})});

@@ -5,27 +5,21 @@ // ==========================================================================

/*global shr*/
import RangeTouch from '../../../src/js/rangetouch';
(function() {
'use strict';
document.addEventListener('DOMContentLoaded', () => {
const loadSprite = url => {
const xhr = new XMLHttpRequest();
const { body } = document;
function loadSprite(url) {
var xhr = new XMLHttpRequest(),
body = document.body;
// Check for CORS support
// If you're loading from same domain, you can remove the whole if/else statement
// XHR for Chrome/Firefox/Opera/Safari/IE10+
if ('withCredentials' in xhr) {
xhr.open('GET', url, true);
if (!('withCredentials' in xhr)) {
return;
}
// XDomainRequest for IE8 & IE9
else if (typeof XDomainRequest == 'function') {
xhr = new XDomainRequest();
xhr.open('GET', url);
}
else { return; }
xhr.open('GET', url, true);
// Inject hidden div with sprite on load
xhr.onload = function() {
var container = document.createElement('div');
xhr.onload = () => {
const container = document.createElement('div');
container.setAttribute('hidden', '');

@@ -36,32 +30,24 @@ container.innerHTML = xhr.responseText;

// Timeout for IE9
setTimeout(function () {
xhr.send();
}, 0);
}
window.loadSprites = function(sprites) {
sprites.forEach(loadSprite);
};
xhr.send();
};
['dist/docs.svg'].forEach(loadSprite);
// Setup shr
shr.setup({
count: {
classname: 'btn__count'
}
});
window.shr.setup({
count: {
classname: 'btn__count',
},
});
// Set range thumb size
window.rangetouch.set('thumbWidth', 20);
RangeTouch.setup('.js-example', { thumbWidth: 20 });
// Google analytics
// For demo site (https://rangetouch.com) only
if(document.domain.indexOf('rangetouch.com') > -1) {
(function(i,s,o,g,r,a,m){i.GoogleAnalyticsObject=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-40881672-15', 'auto');
ga('send', 'pageview');
}
})();
// Test MutationObserver
/* setTimeout(() => {
const input = document.createElement('input');
input.type = 'range';
input.className = 'js-example';
document.getElementById('test').appendChild(input);
}, 2000); */
});

@@ -7,17 +7,32 @@ // ==========================================================================

const gulp = require('gulp');
const plumber = require('gulp-plumber');
const concat = require('gulp-concat');
const terser = require('gulp-terser');
// CSS
const less = require('gulp-less');
const clean = require('gulp-clean-css');
const prefix = require('gulp-autoprefixer');
// JavaScript
const terser = require('gulp-terser');
const rollup = require('gulp-better-rollup');
const babel = require('rollup-plugin-babel');
const commonjs = require('rollup-plugin-commonjs');
const resolve = require('rollup-plugin-node-resolve');
const sourcemaps = require('gulp-sourcemaps');
// SVGs
const svgstore = require('gulp-svgstore');
const svgmin = require('gulp-svgmin');
// Utils
const plumber = require('gulp-plumber');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const replace = require('gulp-replace');
const open = require('gulp-open');
const size = require('gulp-size');
const log = require('fancy-log');
// Deployment
const aws = require('aws-sdk');
const publish = require('gulp-awspublish');
const log = require('fancy-log');
const open = require('gulp-open');

@@ -76,21 +91,68 @@ const pkg = require('./package.json');

// Babel config
const babelrc = {
babelrc: false,
presets: [
'@babel/env',
[
'minify',
{
builtIns: false, // Temporary fix for https://github.com/babel/minify/issues/904
},
],
],
};
// Size plugin
const sizeOptions = { showFiles: true, gzip: true };
// JavaScript
// Formats to build
const formats = {
es: {
ext: 'mjs',
polyfill: false,
},
umd: {
ext: 'js',
polyfill: false,
},
};
const namespace = 'RangeTouch';
const build = {
js: (files, bundle) => {
Object.keys(files).forEach(key => {
const name = `js-${key}`;
tasks.js.push(name);
Object.entries(formats).forEach(([format, task]) => {
Object.keys(files).forEach(key => {
const name = `js-${key}`;
tasks.js.push(name);
gulp.task(name, () => {
return gulp
.src(bundles[bundle].js[key])
.pipe(plumber())
.pipe(concat(key))
.pipe(terser())
.pipe(
size({
showFiles: true,
gzip: true,
}),
)
.pipe(gulp.dest(paths[bundle].output));
gulp.task(name, () => {
return gulp
.src(bundles[bundle].js[key])
.pipe(plumber())
.pipe(concat(key))
.pipe(sourcemaps.init())
.pipe(
rollup(
{
plugins: [resolve(), commonjs(), babel(babelrc)],
},
{
name: namespace,
// exports: 'named',
format,
},
),
)
.pipe(terser())
.pipe(
rename({
extname: `.${task.ext}`,
}),
)
.pipe(size(sizeOptions))
.pipe(gulp.dest(paths[bundle].output));
});
});

@@ -115,8 +177,3 @@ });

.pipe(clean())
.pipe(
size({
showFiles: true,
gzip: true,
}),
)
.pipe(size(sizeOptions))
.pipe(gulp.dest(paths[bundle].output));

@@ -149,8 +206,3 @@ });

)
.pipe(
size({
showFiles: true,
gzip: true,
}),
)
.pipe(size(sizeOptions))
.pipe(gulp.dest(paths[bundle].output));

@@ -200,5 +252,6 @@ });

const regex = '(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)';
const regex =
'(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?';
const semver = new RegExp(`v${regex}`, 'gi');
const cdnpath = new RegExp(`${deploy.cdn.domain}/${regex}`, 'gi');
const semver = new RegExp(`v${regex}`, 'gi');
const localpath = new RegExp('(../)?dist', 'gi');

@@ -303,2 +356,2 @@

// Do everything
gulp.task('publish', gulp.series(gulp.parallel(...tasks.js, ...tasks.less, ...tasks.sprite), 'cdn', 'docs'));
gulp.task('deploy', gulp.series(gulp.parallel(...tasks.js, ...tasks.less, ...tasks.sprite), 'cdn', 'docs'));
{
"name": "rangetouch",
"version": "1.0.6",
"version": "2.0.0-beta.1",
"description": "A super tiny library to make input type='range' sliders work better on touch devices",
"homepage": "https://rangetouch.com",
"author": "Sam Potts <sam@potts.es>",
"license": "MIT",
"main": "src/js/rangetouch.js",

@@ -19,3 +21,2 @@ "browserslist": [

},
"license": "MIT",
"bugs": {

@@ -30,6 +31,9 @@ "url": "https://github.com/sampotts/rangetouch/issues"

},
"author": "Sam Potts <sam@potts.es>",
"dependencies": {},
"devDependencies": {
"aws-sdk": "^2.400.0",
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.3.1",
"babel-eslint": "^10.0.1",
"babel-preset-minify": "^0.5.0",
"eslint": "^5.13.0",

@@ -43,2 +47,3 @@ "eslint-config-airbnb-base": "^13.1.0",

"gulp-awspublish": "^4.0.0",
"gulp-better-rollup": "^3.4.0",
"gulp-clean-css": "^4.0.0",

@@ -51,8 +56,21 @@ "gulp-concat": "^2.6.1",

"gulp-replace": "^1.0.0",
"gulp-s3": "^0.11.0",
"gulp-size": "^3.0.0",
"gulp-sourcemaps": "^2.6.4",
"gulp-svgmin": "^2.1.0",
"gulp-svgstore": "^7.0.1",
"gulp-terser": "^1.1.7",
"gulp-util": "^3.0.8"
"prettier-eslint": "^8.8.2",
"prettier-stylelint": "^0.4.2",
"rollup-plugin-babel": "^4.0.3",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-uglify": "^6.0.0",
"run-sequence": "^2.2.1",
"stylelint": "^9.7.1",
"stylelint-config-prettier": "^4.0.0",
"stylelint-config-recommended": "^2.1.0",
"stylelint-order": "^1.0.0"
}
}

@@ -5,8 +5,6 @@ # RangeTouch

[Donate to support RangeTouch](#donate)
[Donate](#donate) - [Demo](https://rangetouch.com) - [![npm version](https://badge.fury.io/js/rangetouch.svg)](https://badge.fury.io/js/rangetouch)
[Checkout the demo](https://rangetouch.com)
## Why bother?
## Why?
While building [plyr](https://plyr.io) I noticed how bad the experience was trying to use `<input type="range">` is on a touch device (particularly iOS). Touching the track on a desktop will jump the thumb handle to that point. However on some touch devices this simply focuses the input and to adjust the value you need to touch and drag the handle. This is something that I can't help but feel will eventually be fixed by the browser vendors but for now, you can use RangeTouch to fill that gap.

@@ -16,20 +14,18 @@

- No setup required, just include the script
- Less than 1KB minified and gzipped
- No dependencies (written in "vanilla" JavaScript)
- Uses event delgation so no need to re-run after DOM manipulation
## Quick setup
To use RangeTouch, you just need to add `rangetouch.js` (either from the `/dist` (minified) or `/src/js` (unminified) folders). Ideally before the closing `</body>` tag:
### 1. Include the lib
```html
<script src="/path/to/rangetouch.js" async></script>
Either use the ES6 module:
```javascript
import RangeTouch from 'rangetouch';
```
It will automatically bind to all `<input type="range">` elements, even newly injected ones as it uses event delegation.
...or include the script:
### CDN
You can load RangeTouch from our CDN (backed by the awesome [Fastly](https://www.fastly.com/)) if you'd like:
```html

@@ -39,39 +35,62 @@ <script src="https://rangetouch.com/1.0.6/rangetouch.js"></script>

### Node / NPM
### 2. Create instance(s)
[![npm version](https://badge.fury.io/js/rangetouch.svg)](https://badge.fury.io/js/rangetouch)
#### Single instance
```bash
npm install rangetouch
```javascript
const range = new RangeTouch('input[type="range"]', { ...options });
```
[https://www.npmjs.com/package/rangetouch](https://www.npmjs.com/package/rangetouch)
The first argument can either be:
### Bower
- a [valid CSS selector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
- an [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)
[![Bower version](https://badge.fury.io/bo/rangetouch.svg)](https://badge.fury.io/bo/rangetouch)
The second argument is for options.
```bash
bower install rangetouch
This will return a reference to the single instance.
#### Multiple instances
To setup multiple inputs at one time, you can use the following static method:
```javascript
const ranges = RangeTouch.setup('input[type="range"]', { ...options });
```
[http://bower.io/search/?q=rangetouch](http://bower.io/search/?q=rangetouch)
The first argument can either be:
More info on setting up dependencies can be found in the [Bower Docs](http://bower.io/docs/creating-packages/#maintaining-dependencies)
- a [valid CSS selector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
- an [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)
- an [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
- an [Element](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)
## Configuration
The second argument is for options.
If you're customizing your range inputs (easily done - see the demo for an example) and you change the size of the thumb handle, you should specify (in pixels) this after including the script:
This will return an array of RangeTouch instances that it setup.
## Options
| Property | Type | Default | Description |
| ---------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| addCSS | Boolean | `true` | Whether to inject CSS to improve the usability of the inputs. It's recommended you add this yourself if you don't want RangeTouch to take care of it. |
| thumbWidth | Integer | `15` | This value is used as part of the calculation to determine the value the users selects when touching the range track. Unfortunately as JavaScript can't access the shadow DOM, this value can't be automatically determined. I would recommend customisation (and setting the size of the thumb) given all OS and browser combinations seem to render the control differently. |
| watch | Boolean | `true` | Watch for new elements added to the DOM that match your string selector. **Note**: This only applies when using the multiple instance `RangeTouch` setup method and also requires a string selector as the first argument. |
## API
| Method | Arguments | Description |
| --------- | --------- | -------------------------------------------------------- |
| destroy() | N/A | Destroy the current instance and remove event listeners. |
To call an API method, you need a reference to the instance. For example:
```javascript
window.rangetouch.set('thumbWidth', 15);
const range = new RangeTouch('input[type="range"]', { ...options });
range.destroy();
```
This value is used as part of the calculation to determine the value the users selects when touching the range track. Unfortunately as JavaScript can't access the shadow DOM, this value can't be automatically determined. I would recommend customisation (and setting the size of the thumb) given all OS and browser combinations seem to render the control differently (as per usual).
If you want to disable RangeTouch for a particular input, add the `rangetouch--disabled` class name to the element.
## Issues
If you find anything weird with RangeTouch, please let us know using the GitHub issues tracker.
If you find anything weird with RangeTouch, please let us know using the [GitHub issues tracker](https://github.com/sampotts/rangetouch/issues) and be descriptive on how to reproduce, expected result, the browser (and version) used, etc.

@@ -84,3 +103,3 @@ ## Author

RangeTouch costs money to run, not my time - I donate that for free but domains, hosting and more. Any help is appreciated...
RangeTouch costs money to run for domains, hosting and more. Any help is appreciated...
[Donate to support RangeTouch](https://www.paypal.me/pottsy/20usd)

@@ -90,3 +109,3 @@

[![Fastly](https://www.fastly.com/sites/all/themes/custom/fastly2016/logo.png)](https://www.fastly.com/)
[![Fastly](https://cdn.plyr.io/static/fastly-logo.png)](https://www.fastly.com/)

@@ -93,0 +112,0 @@ Thanks to [Fastly](https://www.fastly.com/) for providing the CDN services.

// ==========================================================================
// rangetouch.js v1.0.6
// rangetouch.js v2.0.0-beta.1
// Making <input type="range"> work on touch devices
// https://github.com/selz/rangetouch
// https://github.com/sampotts/rangetouch
// License: The MIT License (MIT)
// ==========================================================================
(function(root, factory) {
'use strict';
/*global define,module*/
import { matches } from './utils/css';
import { trigger } from './utils/events';
import is from './utils/is';
import { round } from './utils/numbers';
if (typeof module === 'object' && typeof module.exports === 'object') {
// Node, CommonJS-like
module.exports = factory(root, document);
} else if (typeof define === 'function' && define.amd) {
// AMD
define(null, function() {
factory(root, document);
});
} else {
// Browser globals (root is window)
root.rangetouch = factory(root, document);
}
})(typeof window !== 'undefined' ? window : this, function(window, document) {
'use strict';
const defaults = {
addCSS: true, // Add CSS to the element to improve usability (required here or in your CSS!)
thumbWidth: 15, // The width of the thumb handle
watch: true, // Watch for new elements that match a string target
};
// Default config
var settings = {
enabled: true,
addCSS: true,
thumbWidth: 15,
selectors: {
range: '[type="range"]',
disabled: '.rangetouch--disabled',
},
events: {
start: 'touchstart',
move: 'touchmove',
end: 'touchend',
},
};
class RangeTouch {
/**
* Setup a new instance
* @param {String|Element} target
* @param {Object} options
*/
constructor(target, options) {
if (is.element(target)) {
// An Element is passed, use it directly
this.element = target;
} else if (is.string(target)) {
// A CSS Selector is passed, fetch it from the DOM
this.element = document.querySelector(target);
}
// Setup
function setup() {
// Bail if not a touch enabled device
if (!('ontouchstart' in document.documentElement)) {
if (!is.element(this.element) || !is.empty(this.element.rangeTouch)) {
return;
}
// Add useful CSS
if (settings.addCSS) {
var stylesheet = createStyleSheet();
stylesheet.insertRule(
getSelector() + ' { user-select: none; -webkit-user-select: none; touch-action: manipulation; }',
0,
);
}
this.config = Object.assign({}, defaults, options);
// Listen for events
listeners();
this.init();
}
// Event listeners
function listeners() {
on(document.body, settings.events.start, set);
on(document.body, settings.events.move, set);
on(document.body, settings.events.end, set);
static get enabled() {
return 'ontouchstart' in document.documentElement;
}
// Create a CSS stylesheet
function createStyleSheet() {
var style = document.createElement('style');
style.appendChild(document.createTextNode(''));
document.head.appendChild(style);
return style.sheet;
}
/**
* Setup multiple instances
* @param {String|Element|NodeList|Array} target
* @param {Object} options
*/
static setup(target, options = {}) {
let targets = null;
// Trigger event
function trigger(element, type, properties) {
// Bail if no element
if (!element || !type) {
return;
if (is.empty(target) || is.string(target)) {
targets = Array.from(document.querySelectorAll(is.string(target) ? target : 'input[type="range"]'));
} else if (is.element(target)) {
targets = [target];
} else if (is.nodeList(target)) {
targets = Array.from(target);
} else if (is.array(target)) {
targets = target.filter(is.element);
}
// Create CustomEvent constructor
var CustomEvent;
if (typeof window.CustomEvent === 'function') {
CustomEvent = window.CustomEvent;
} else {
// Polyfill CustomEvent
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
CustomEvent = function(event, params) {
params = params || {
bubbles: false,
cancelable: false,
detail: undefined,
};
var custom = document.createEvent('CustomEvent');
custom.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return custom;
};
CustomEvent.prototype = window.Event.prototype;
if (is.empty(targets)) {
return null;
}
// Create and dispatch the event
var event = new CustomEvent(type, {
bubbles: true,
detail: properties,
});
const config = Object.assign({}, defaults, options);
// Dispatch the event
element.dispatchEvent(event);
}
if (is.string(target) && config.watch) {
// Create an observer instance
const observer = new MutationObserver(mutations => {
Array.from(mutations).forEach(mutation => {
Array.from(mutation.addedNodes).forEach(node => {
if (!is.element(node) || !matches(node, target)) {
return;
}
// Get the selector for the range
function getSelector() {
return [settings.selectors.range, ':not(', settings.selectors.disabled, ')'].join('');
}
// eslint-disable-next-line no-unused-vars
const range = new RangeTouch(node, config);
});
});
});
// Check if element is disabled
function isDisabled(element) {
if (element instanceof HTMLElement) {
return element.matches(settings.selectors.disabled) || element.disabled;
// Pass in the target node, as well as the observer options
observer.observe(document.body, {
childList: true,
subtree: true,
});
}
return true;
return targets.map(t => new RangeTouch(t, options));
}
// Bind an event listener
function on(element, type, listener) {
element.addEventListener(type, listener, false);
}
init() {
// Bail if not a touch enabled device
if (!RangeTouch.enabled) {
return;
}
// Get the number of decimal places
function getDecimalPlaces(value) {
var match = ('' + value).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match) {
return 0;
// Add useful CSS
if (this.config.addCSS) {
// TODO: Restore original values on destroy
this.element.style.userSelect = 'none';
this.element.style.webKitUserSelect = 'none';
this.element.style.touchAction = 'manipulation';
}
return Math.max(
0,
// Number of digits right of decimal point.
(match[1] ? match[1].length : 0) -
// Adjust for scientific notation.
(match[2] ? +match[2] : 0),
);
this.listeners(true);
this.element.rangeTouch = this;
}
// Round to the nearest step
function round(number, step) {
if (step < 1) {
var places = getDecimalPlaces(step);
return parseFloat(number.toFixed(places));
destroy() {
// Bail if not a touch enabled device
if (!RangeTouch.enabled) {
return;
}
return Math.round(number / step) * step;
this.listeners(false);
this.element.rangeTouch = null;
}
// Get the value based on touch position
function get(event) {
var input = event.target;
var touch = event.changedTouches[0];
var min = parseFloat(input.getAttribute('min')) || 0;
var max = parseFloat(input.getAttribute('max')) || 100;
var step = parseFloat(input.getAttribute('step')) || 1;
var delta = max - min;
listeners(toggle) {
const method = toggle ? 'addEventListener' : 'removeEventListener';
// Listen for events
['touchstart', 'touchmove', 'touchend'].forEach(type => {
this.element[method](type, event => this.set(event), false);
});
}
/**
* Get the value based on touch position
* @param {Event} event
*/
get(event) {
if (!RangeTouch.enabled || !is.event(event)) {
return null;
}
const input = event.target;
const touch = event.changedTouches[0];
const min = parseFloat(input.getAttribute('min')) || 0;
const max = parseFloat(input.getAttribute('max')) || 100;
const step = parseFloat(input.getAttribute('step')) || 1;
const delta = max - min;
// Calculate percentage
var percent;
var clientRect = input.getBoundingClientRect();
var thumbWidth = ((100 / clientRect.width) * (settings.thumbWidth / 2)) / 100;
let percent;
const clientRect = input.getBoundingClientRect();
const thumbWidth = ((100 / clientRect.width) * (this.config.thumbWidth / 2)) / 100;

@@ -195,6 +177,8 @@ // Determine left percentage

// Update range value based on position
function set(event) {
// If not enabled, bail
if (!settings.enabled || event.target.type !== 'range' || isDisabled(event.target)) {
/**
* Update range value based on position
* @param {Event} event
*/
set(event) {
if (!RangeTouch.enabled || !is.event(event) || event.target.disabled) {
return;

@@ -207,16 +191,9 @@ }

// Set value
event.target.value = get(event);
event.target.value = this.get(event);
// Trigger input event
trigger(event.target, event.type === settings.events.end ? 'change' : 'input');
// Trigger event
trigger(event.target, event.type === 'touchend' ? 'change' : 'input');
}
}
// Run setup automatically
setup();
return {
set: function(setting, value) {
settings[setting] = value;
},
};
});
export default RangeTouch;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc