- touchable RengeSlider.js and RangeSlider.css

- addition utility methods
- domEvent.js: add multiple handler with one initialization
This commit is contained in:
Arno Kaimbacher 2021-01-08 16:35:26 +01:00
parent e62d4908f0
commit 7c50b75099
5 changed files with 168 additions and 149 deletions

View File

@ -1,7 +1,6 @@
import { Control } from "./Control"; import { Control } from "./Control";
import * as dom from '../core/domUtil'; import * as dom from '../core/domUtil';
import * as util from '../core/utilities'; import * as util from '../core/utilities';
import * as domEvent from '../core/domEvent';
import { RangeSlider } from '../core/RangeSlider'; import { RangeSlider } from '../core/RangeSlider';
import './SliderControl.css'; import './SliderControl.css';
@ -79,13 +78,14 @@ export class SliderControl extends Control {
// this.slider.setAttribute("step", this.options.step); // this.slider.setAttribute("step", this.options.step);
// this.slider.setAttribute("value", this.options.value); // this.slider.setAttribute("value", this.options.value);
this.slider = new RangeSlider(this._sliderContainer, { this.slider = new RangeSlider({
orientation: "vertical", orientation: "vertical",
value: 1, value: 1,
max: 5, min: 1, max: 5, min: 1,
inverse: true, inverse: true,
id: "z-slider" id: "z-slider"
}); });
this.slider.addTo(this._sliderContainer);
//if (this.options.syncSlider) { //if (this.options.syncSlider) {
// L.DomEvent.on(this.slider, "input", function (e) { // L.DomEvent.on(this.slider, "input", function (e) {

View File

@ -7,7 +7,8 @@
.slider.slider-vertical { .slider.slider-vertical {
height: 160px; height: 160px;
width: 30px; width: 35px;
z-index: 9;
} }
.slider.slider-vertical .range-slider-track { .slider.slider-vertical .range-slider-track {

View File

@ -1,7 +1,8 @@
import { EventEmitter } from './EventEmitter'; import { EventEmitter } from './EventEmitter';
import * as dom from '../core/domUtil'; import * as dom from './domUtil';
import * as util from '../core/utilities'; import * as util from './utilities';
import * as domEvent from '../core/domEvent'; import * as domEvent from './domEvent';
import * as browser from './browser';
import './RangeSlider.css'; import './RangeSlider.css';
@ -9,6 +10,7 @@ class RangeSlider extends EventEmitter {
over = false; over = false;
inDrag = false; inDrag = false;
touchCapable = false;
options = { options = {
value: 0, // set default value on initiation from `0` to `100` (percentage based) value: 0, // set default value on initiation from `0` to `100` (percentage based)
@ -22,16 +24,21 @@ class RangeSlider extends EventEmitter {
stepSize: 1 stepSize: 1
}; };
constructor(elem, options) { constructor(options) {
super(); super();
util.setOptions(this, options); util.setOptions(this, options);
this.value = this.options.value; this.value = this.options.value;
this.element = elem; if (browser.touch && browser.mobile) {
this.touchCapable = true;
}
}
addTo(parentDiv) {
//this._initLayout(); //this._initLayout();
this.picker = dom.createDom("div", { this.element = parentDiv;
this.template = dom.createDom("div", {
"class": 'slider', innerHTML: "class": 'slider', innerHTML:
'<div class="range-slider-track">' + '<div class="range-slider-track">' +
'<div class="slider-selection"></div>' + '<div class="slider-selection"></div>' +
@ -41,24 +48,23 @@ class RangeSlider extends EventEmitter {
'<div class="slider-ticks"></div>' + '<div class="slider-ticks"></div>' +
'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
}, this.element); }, parentDiv);
this.id = this.options.id; this.id = this.options.id;
// var tooltip = this.options.tooltip; this.tooltip = this.template.getElementsByClassName('tooltip')[0];
this.tooltip = this.picker.getElementsByClassName('tooltip')[0];
this.tooltipInner = this.tooltip.getElementsByClassName('tooltip-inner')[0]; this.tooltipInner = this.tooltip.getElementsByClassName('tooltip-inner')[0];
this.sliderTrack = this.picker.getElementsByClassName('range-slider-track')[0]; this.sliderTrack = this.template.getElementsByClassName('range-slider-track')[0];
this.sliderTicks = this.picker.getElementsByClassName('slider-ticks')[0]; this.sliderTicks = this.template.getElementsByClassName('slider-ticks')[0];
this.orientation = this.options.orientation; this.orientation = this.options.orientation;
if (this.orientation === "horizontal") { if (this.orientation === "horizontal") {
dom.addClass(this.picker, "slider-horizontal"); dom.addClass(this.template, "slider-horizontal");
//.addClass('slider-horizontal')
//.css('width', this.element.outerWidth()); //.css('width', this.element.outerWidth());
//$(this.picker).css('width', $(this.element).outerWidth()); //$(this.template).css('width', $(this.element).outerWidth());
//this.picker.style.width = this.element['offsetWidth'] + 'px'; //this.template.style.width = this.element['offsetWidth'] + 'px';
this.orientation = 'horizontal'; this.orientation = 'horizontal';
this.stylePos = 'left'; this.stylePos = 'left';
this.mousePos = 'pageX'; this.mousePos = 'pageX';
@ -67,11 +73,10 @@ class RangeSlider extends EventEmitter {
dom.addClass(this.tooltip, "top"); dom.addClass(this.tooltip, "top");
this.tooltip.style.top = -this.tooltip['offsetHeight'] - 14 + 'px'; this.tooltip.style.top = -this.tooltip['offsetHeight'] - 14 + 'px';
} else { } else {
dom.addClass(this.picker, "slider-vertical"); dom.addClass(this.template, "slider-vertical");
this.stylePos = 'top'; this.stylePos = 'top';
this.mousePos = 'pageY'; this.mousePos = 'pageY';
this.sizePos = 'offsetHeight'; this.sizePos = 'offsetHeight';
// this.tooltip.addClass('right')[0].style.left = '100%';
dom.addClass(this.tooltip, "right"); dom.addClass(this.tooltip, "right");
this.tooltip.style.left = "100%"; this.tooltip.style.left = "100%";
} }
@ -84,7 +89,7 @@ class RangeSlider extends EventEmitter {
// this.range = true; // this.range = true;
//} //}
let positionStep = 160/4; let positionStep = 160 / 4;
let topPosition = 0; let topPosition = 0;
for (let i = this.min; i <= this.max; i = i + this.stepSize) { for (let i = this.min; i <= this.max; i = i + this.stepSize) {
let sliderTick = dom.createDom("div", { let sliderTick = dom.createDom("div", {
@ -95,16 +100,15 @@ class RangeSlider extends EventEmitter {
} }
this.selection = this.options.selection; this.selection = this.options.selection;
this.selectionEl = this.picker.getElementsByClassName('slider-selection')[0]; this.selectionEl = this.template.getElementsByClassName('slider-selection')[0];
if (this.selection === 'none') { if (this.selection === 'none') {
//this.selectionEl.addClass('hide');
dom.addClass(this.selectionEl, "hide"); dom.addClass(this.selectionEl, "hide");
} }
this.selectionElStyle = this.selectionEl.style; this.selectionElStyle = this.selectionEl.style;
this.handle1 = this.picker.getElementsByClassName('slider-handle')[0]; this.handle1 = this.template.getElementsByClassName('slider-handle')[0];
this.handle1Stype = this.handle1.style; this.handle1Stype = this.handle1.style;
this.handle2 = this.picker.getElementsByClassName('slider-handle')[1]; this.handle2 = this.template.getElementsByClassName('slider-handle')[1];
this.handle2Stype = this.handle2.style; this.handle2Stype = this.handle2.style;
var handle = this.options.handle; var handle = this.options.handle;
@ -141,17 +145,39 @@ class RangeSlider extends EventEmitter {
this.stepSize * 100 / this.diff this.stepSize * 100 / this.diff
]; ];
//this.offset = this.picker.offset(); //this.offset = this.template.offset();
// this.offset = $(this.picker).offset(); // this.offset = $(this.template).offset();
this.offset = this._getOffset(this.picker); this.offset = this._getOffset(this.template);
this.size = this.template[this.sizePos];
this.size = this.picker[this.sizePos];
//this.formater = options.formater; //this.formater = options.formater;
this.layout(); this.layout();
domEvent.on(this.picker, "mousedown", this.mousedown, this);
// domEvent
// .on(this.template, 'mousedown touchstart', domEvent.stopPropagation)
// .on(this.template, 'click', domEvent.stopPropagation)
// .on(this.template, 'dblclick', domEvent.stopPropagation)
// .on(this.template, 'mousedown touchstart', domEvent.preventDefault)
// .on(this.template, 'mousedown touchstart', this.mousedown, this);
if (this.touchCapable) {
// Touch: Bind touch events:
domEvent.on(this.template, 'touchstart', domEvent.stopPropagation)
domEvent.on(this.template, 'touchstart', domEvent.preventDefault);
domEvent.on(this.template, 'touchstart', this.mousedown, this);
} else {
domEvent.on(this.template, 'mousedown', domEvent.stopPropagation);
domEvent.on(this.template, 'click', domEvent.stopPropagation);
domEvent.on(this.template, 'dblclick', domEvent.stopPropagation);
domEvent.on(this.template, 'mousedown', domEvent.preventDefault);
domEvent.on(this.template, 'mousedown', this.mousedown, this);
}
// domEvent.on(this.template, "mousedown touchstart", this.mousedown, this);
dom.addClass(this.tooltip, "hide"); dom.addClass(this.tooltip, "hide");
} }
@ -197,17 +223,16 @@ class RangeSlider extends EventEmitter {
} }
mousedown(ev) { mousedown(ev) {
// Touch: Get the original event: // Touch: Get the original event:
if (this.touchCapable && ev.type === 'touchstart') { // if (this.touchCapable && ev.type === 'touchstart') {
ev = ev.originalEvent; // ev = ev.originalEvent;
} // }
//this.offset = this.picker.offset(); //this.offset = this.template.offset();
// this.offset = $(this.picker).offset(); // this.offset = $(this.template).offset();
this.offset = this._getOffset(this.picker); this.offset = this._getOffset(this.template);
this.size = this.picker[this.sizePos]; this.size = this.template[this.sizePos];
let percentage = this.getPercentage(ev); let percentage = this.getPercentage(ev);
@ -223,12 +248,19 @@ class RangeSlider extends EventEmitter {
// this.percentage[this.dragged] = percentage; // this.percentage[this.dragged] = percentage;
// this.layout(); // this.layout();
domEvent.on(this.picker, "mousemove", this.mousemove, this); if (this.touchCapable) {
domEvent.on(this.picker, 'mouseup', this.mouseup, this); // Touch: Bind touch events:
domEvent.on(this.picker, 'mouseleave', this.onMouseLeave, this); domEvent.on(this.template, 'touchmove', this.mousemove, this);
domEvent.on(this.template, 'touchend', this.mouseup, this);
// domEvent.on(this.template, 'touchcancel', this.onMouseLeave, this);
} else {
domEvent.on(this.template, 'mousemove', this.mousemove, this);
domEvent.on(this.template, 'mouseup', this.mouseup, this);
domEvent.on(this.template, 'mouseleave', this.onMouseLeave, this);
}
this.inDrag = true; this.inDrag = true;
let value = this.calculateValue(); // let value = this.calculateValue();
//if (this.options.inverse === true) { //if (this.options.inverse === true) {
// val = val * -1; // val = val * -1;
//} //}
@ -250,9 +282,9 @@ class RangeSlider extends EventEmitter {
this.sliderTrack.style.cursor = "grab"; this.sliderTrack.style.cursor = "grab";
// Touch: Get the original event: // Touch: Get the original event:
if (this.touchCapable && ev.type === 'touchmove') { // if (this.touchCapable && ev.type === 'touchmove') {
ev = ev.originalEvent; // ev = ev.originalEvent;
} // }
let percentage = this.getPercentage(ev); let percentage = this.getPercentage(ev);
// if (this.range) { // if (this.range) {
@ -286,9 +318,18 @@ class RangeSlider extends EventEmitter {
this.handle1.style.cursor = "pointer"; this.handle1.style.cursor = "pointer";
this.sliderTrack.style.cursor = "pointer"; this.sliderTrack.style.cursor = "pointer";
domEvent.off(this.picker, "mousemove", this.mousemove, this);
domEvent.off(this.picker, 'mouseup', this.mouseup, this);
domEvent.off(this.picker, 'mouseleave', this.onMouseLeave, this); if (this.touchCapable) {
// Touch: Bind touch events:
domEvent.off(this.template, "touchmove", this.mousemove, this);
domEvent.off(this.template, 'touchend', this.mouseup, this);
// domEvent.off(this.template, 'touchcancel', this.onMouseLeave, this);
} else {
domEvent.off(this.template, "mousemove", this.mousemove, this);
domEvent.off(this.template, 'mouseup', this.mouseup, this);
domEvent.off(this.template, 'mouseleave', this.onMouseLeave, this);
}
this.inDrag = false; this.inDrag = false;
//if (this.over == false) { //if (this.over == false) {
@ -304,9 +345,17 @@ class RangeSlider extends EventEmitter {
this.handle1.style.cursor = "pointer"; this.handle1.style.cursor = "pointer";
this.sliderTrack.style.cursor = "pointer"; this.sliderTrack.style.cursor = "pointer";
domEvent.off(this.picker, "mousemove", this.mousemove, this);
domEvent.off(this.picker, 'mouseup', this.mouseup, this); if (this.touchCapable) {
domEvent.off(this.picker, 'mouseleave', this.onMouseLeave, this); // Touch: Bind touch events:
domEvent.off(this.template, "touchmove", this.mousemove, this);
domEvent.off(this.template, 'touchend', this.mouseup, this);
// domEvent.off(this.template, 'touchcancel', this.onMouseLeave, this);
} else {
domEvent.off(this.template, "mousemove", this.mousemove, this);
domEvent.off(this.template, 'mouseup', this.mouseup, this);
domEvent.off(this.template, 'mouseleave', this.onMouseLeave, this);
}
this.inDrag = false; this.inDrag = false;
@ -324,15 +373,16 @@ class RangeSlider extends EventEmitter {
]; ];
this.value = val; this.value = val;
} else { } else {
val = (this.min + Math.round((this.diff * this.percentage[0] / 100) / this.stepSize) * this.stepSize); val = (this.
min + Math.round((this.diff * this.percentage[0] / 100) / this.stepSize) * this.stepSize);
this.value = [val, this.value[1]]; this.value = [val, this.value[1]];
} }
return val; return val;
} }
getPercentage(ev) { getPercentage(ev) {
if (this.touchCapable) { if (this.touchCapable && ev.touches) {
ev = ev.touches[0]; ev = ev.touches[0];
} }
let percentage = (ev[this.mousePos] - this.offset[this.stylePos]) * 100 / this.size; let percentage = (ev[this.mousePos] - this.offset[this.stylePos]) * 100 / this.size;
percentage = Math.round(percentage / this.percentage[2]) * this.percentage[2]; percentage = Math.round(percentage / this.percentage[2]) * this.percentage[2];

View File

@ -1,19 +1,32 @@
import * as browser from '../core/browser'; import * as browser from '../core/browser';
import * as util from '../core/utilities'; import * as util from '../core/utilities';
//static function
var stampForFn = (function () {
var lastId = 0,
key = '_id';
return function (obj) {
obj[key] = obj[key] || ++lastId;
return obj[key];
};
}());
export function addListener(obj, type, fn, context) { // (HTMLElement, String, Function[, Object]) var mouseSubst = {
mouseenter: 'mouseover',
mouseleave: 'mouseout',
wheel: !('onwheel' in window) && 'mousewheel'
};
var id = stampForFn(fn); export function addListener(obj, types, fn, context) {
if (typeof types === 'object') {
for (let type in types) {
addaddOneListenerne(obj, type, types[type], fn);
}
} else {
types = util.splitWords(types);
for (let i = 0, len = types.length; i < len; i++) {
addOneListener(obj, types[i], fn, context);
}
}
return this;
}
export function addOneListener(obj, type, fn, context) { // (HTMLElement, String, Function[, Object])
var id = util.stamp(fn);
var key = '_gba_' + type + id; var key = '_gba_' + type + id;
var handler, originalHandler, newType; var handler, originalHandler, newType;
@ -23,19 +36,15 @@ export function addListener(obj, type, fn, context) { // (HTMLElement, String, F
return fn.call(context || obj, e || domEvent._getEvent()); return fn.call(context || obj, e || domEvent._getEvent());
}; };
//if (L.Browser.pointer && type.indexOf('touch') === 0) {
// return this.addPointerListener(obj, type, handler, id);
//}
//if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) {
// this.addDoubleTapListener(obj, handler, id);
//}
if ('addEventListener' in obj) { if ('addEventListener' in obj) {
if (type === 'mousewheel') { // if (type === 'mousewheel') {
obj.addEventListener('DOMMouseScroll', handler, false); // obj.addEventListener('DOMMouseScroll', handler, false);
obj.addEventListener(type, handler, false); // obj.addEventListener(type, handler, false);
// }
if (type === 'touchstart' || type === 'touchmove' || type === 'wheel' || type === 'mousewheel') {
obj.addEventListener(mouseSubst[type] || type, handler, false);
} }
else if ((type === 'mouseenter') || (type === 'mouseleave')) { else if ((type === 'mouseenter') || (type === 'mouseleave')) {
@ -49,25 +58,15 @@ export function addListener(obj, type, fn, context) { // (HTMLElement, String, F
obj.addEventListener(newType, handler, false); obj.addEventListener(newType, handler, false);
} } else {
//else if (type === 'click' && L.Browser.android) {
// originalHandler = handler;
// handler = function (e) {
// return L.DomEvent._filterClick(e, originalHandler);
// };
// obj.addEventListener(type, handler, false);
//}
else {
obj.addEventListener(type, handler, false); obj.addEventListener(type, handler, false);
} }
} } else if ('attachEvent' in obj) {
else if ('attachEvent' in obj) {
obj.attachEvent('on' + type, handler); obj.attachEvent('on' + type, handler);
} }
obj[key] = obj[key] || {};
obj[key] = handler; obj[key] = handler;
return this; return this;
@ -77,62 +76,14 @@ export function addListener(obj, type, fn, context) { // (HTMLElement, String, F
// Alias to [`L.DomEvent.on`](#domevent-on) // Alias to [`L.DomEvent.on`](#domevent-on)
export { addListener as on }; export { addListener as on };
function addOne(obj, type, fn, context) {
var id = type + util.stamp(fn) + (context ? '_' + util.stamp(context) : '');
var eventsKey = '_gba_' + type + id;
if (obj[eventsKey] && obj[eventsKey][id]) { return this; }
var handler = function (e) {
return fn.call(context || obj, e || window.event);
};
var originalHandler = handler;
if (browser.pointer && type.indexOf('touch') === 0) {
// Needs DomEvent.Pointer.js
addPointerListener(obj, type, handler, id);
} else if (browser.touch && (type === 'dblclick') && !browserFiresNativeDblClick()) {
addDoubleTapListener(obj, handler, id);
} else if ('addEventListener' in obj) {
if (type === 'touchstart' || type === 'touchmove' || type === 'wheel' || type === 'mousewheel') {
obj.addEventListener(mouseSubst[type] || type, handler, Browser.passiveEvents ? {passive: false} : false);
} else if (type === 'mouseenter' || type === 'mouseleave') {
handler = function (e) {
e = e || window.event;
if (isExternalTarget(obj, e)) {
originalHandler(e);
}
};
obj.addEventListener(mouseSubst[type], handler, false);
} else {
obj.addEventListener(type, originalHandler, false);
}
} else if ('attachEvent' in obj) {
obj.attachEvent('on' + type, handler);
}
obj[eventsKey] = obj[eventsKey] || {};
obj[eventsKey][id] = handler;
}
export function removeListener(obj, type, fn) { // (HTMLElement, String, Function) export function removeListener(obj, type, fn) { // (HTMLElement, String, Function)
var id = stampForFn(fn); var id = util.stamp(fn);
var key = '_gba_' + type + id; var key = '_gba_' + type + id;
var handler = obj[key]; var handler = obj[key];
if (!handler) { return this; } if (!handler) { return this; }
if ('removeEventListener' in obj) { if ('removeEventListener' in obj) {
if (type === 'mousewheel') { if (type === 'mousewheel') {
obj.removeEventListener('DOMMouseScroll', handler, false); obj.removeEventListener('DOMMouseScroll', handler, false);
@ -187,9 +138,9 @@ export function stopPropagation(e) {
// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`, // Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,
// `'mousedown'` and `'touchstart'` events (plus browser variants). // `'mousedown'` and `'touchstart'` events (plus browser variants).
export function disableClickPropagation(el) { export function disableClickPropagation(el) {
addListener(el, 'mousedown touchstart dblclick', stopPropagation); addListener(el, 'mousedown touchstart dblclick', stopPropagation);
addOne(el, 'click', fakeStop); addOneListener(el, 'click', fakeStop);
return this; return this;
} }
export function preventDefault(e) { export function preventDefault(e) {
@ -205,8 +156,8 @@ export function preventDefault(e) {
var skipEvents = {}; var skipEvents = {};
export function fakeStop(e) { export function fakeStop(e) {
// fakes stopPropagation by setting a special event flag, checked/reset with skipped(e) // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)
skipEvents[e.type] = true; skipEvents[e.type] = true;
} }
export function skipped(e) { export function skipped(e) {
var skipped = skipEvents[e.type]; var skipped = skipEvents[e.type];

View File

@ -147,7 +147,7 @@ export function setOptions(obj, options) {
// Last unique ID used by [`stamp()`](#util-stamp) // Last unique ID used by [`stamp()`](#util-stamp)
export var lastId = 0; export var lastId = 0;
// @function stamp(obj: Object): Number // @function stampForFn(obj: Object): Number
// Returns the unique ID of an object, assigning it one if it doesn't have it. // Returns the unique ID of an object, assigning it one if it doesn't have it.
export function stamp(obj) { export function stamp(obj) {
let key = '_gba_id'; let key = '_gba_id';
@ -156,6 +156,17 @@ export function stamp(obj) {
} }
// //static function
// var stamp = (function () {
// //var lastId = 0,
// let key = '_gba_id';
// return function (obj) {
// obj[key] = obj[key] || ++lastId;
// return obj[key];
// };
// }());
// export { stamp };
export function hasTouch() { export function hasTouch() {
let phantomjs = navigator.userAgent.toLowerCase().indexOf('phantom') !== -1; let phantomjs = navigator.userAgent.toLowerCase().indexOf('phantom') !== -1;
@ -171,4 +182,10 @@ export function hasTouch() {
// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) // Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
export function trim(str) { export function trim(str) {
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
}
// @function splitWords(str: String): String[]
// Trims and splits the string on whitespace and returns the array of parts.
export function splitWords(str) {
return trim(str).split(/\s+/);
} }