rmc-select-list
Version:
m-select-list ui component for react
535 lines (471 loc) • 13.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CLICK = exports.CANCEL = exports.END = exports.MOVE = exports.START = exports.isTouchable = undefined;
exports.EventManager = EventManager;
exports.handleScrolling = handleScrolling;
exports.handleTapping = handleTapping;
exports.handleQuickBar = handleQuickBar;
var _objectAssign = require('object-assign');
var _objectAssign2 = _interopRequireDefault(_objectAssign);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var isTouchable = exports.isTouchable = 'ontouchstart' in window; /* eslint no-param-reassign:0*/
var START = exports.START = isTouchable ? 'touchstart' : 'mousedown';
var MOVE = exports.MOVE = isTouchable ? 'touchmove' : 'mousemove';
var END = exports.END = isTouchable ? 'touchend' : 'mouseup';
var CANCEL = exports.CANCEL = isTouchable ? 'touchcancel' : 'mousecancel';
var CLICK = exports.CLICK = isTouchable ? 'touchstart' : 'click';
var VALVE = 10;
var isBadMobile = /Android[^\d]*(1|2|3|4\.0)/.test(window.navigator.appVersion) || /iPhone[^\d]*(5)/.test(window.navigator.appVersion);
var getTime = Date.now || function () {
return +new Date();
};
function addEvent(el, type, callback) {
var t = type.split(' ');
for (var i = 0; i < t.length; i++) {
el.addEventListener(t[i], callback, false);
}
}
function removeEvent(el, type, callback) {
var t = type.split(' ');
for (var i = 0; i < t.length; i++) {
el.removeEventListener(t[i], callback, false);
}
}
function _event(e) {
if (e.touches && e.touches.length) {
return e.touches[0];
}
if (e.changedTouches && e.changedTouches.length) {
return e.changedTouches[0];
}
return e;
}
function _pageX(e) {
return _event(e).pageX;
}
function _getPageY(e) {
return _event(e).pageY;
}
function momentum(current, start, time, deceleration) {
var distance = current - start;
var speed = Math.abs(distance) / time;
var d = deceleration === undefined ? 0.0006 : deceleration;
var destination = current + speed * speed / (2 * d) * (distance < 0 ? -1 : 1);
var duration = speed / d;
return {
destination: Math.round(destination),
duration: duration
};
}
// event management helper
function EventManager(target) {
this.target = target;
this._startEvents = [];
this._moveEvents = [];
this._endEvents = [];
this.startEvent();
}
EventManager.prototype = {
addHandler: function addHandler(event) {
if (event.start) {
this._startEvents.push(event.start);
}
if (event.move) {
this._moveEvents.push(event.move);
}
if (event.end) {
this._endEvents.push(event.end);
}
},
startEvent: function startEvent() {
var self = this;
function _startEvent() {
addEvent(window, MOVE, self._move = function (e) {
self._moveEvents.forEach(function (callback) {
callback.call(self, e);
});
}, false);
addEvent(window, END, self._end = function (e) {
self._endEvents.forEach(function (callback) {
callback.call(self, e);
callback._isEnded = true;
});
self.endEvent(true);
}, false);
addEvent(window, CANCEL, self._cancel = function (e) {
self._endEvents.forEach(function (callback) {
if (!callback._isEnded) {
callback.call(self, e);
}
callback._isEnded = true;
});
self.endEvent(true);
}, false);
}
// catch event starting from target
addEvent(self.target, START, self._start = function (e) {
self._startEvents.forEach(function (callback) {
callback.call(self, e);
});
self._endEvents.forEach(function (callback) {
callback._isEnded = false;
});
_startEvent();
});
},
endEvent: function endEvent(keepStart) {
if (!keepStart && this._start) {
removeEvent(this.target, START, this._start, false);
this._start = null;
}
if (this._move) {
removeEvent(window, MOVE, this._move, false);
this._move = null;
}
if (this._end) {
removeEvent(window, END, this._end, false);
this._end = null;
}
if (this._cancel) {
removeEvent(window, CANCEL, this._cancel, false);
this._cancel = null;
}
}
};
function handleScrolling(eventManager, instance) {
var _lastEl = undefined;
var _startY = undefined;
var _pageY = undefined;
var _distY = undefined;
var _isAnimating = undefined;
var _startTime = undefined;
var _endTime = undefined;
instance._y = 0;
instance.refs.viewport.style.overflow = 'hidden';
var rException = /^(INPUT|TEXTAREA|BUTTON|SELECT)$/;
var rAF = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
function _easing(k) {
var kk = k;
return Math.sqrt(1 - --kk * kk);
}
function _translate(y) {
var _currentPos = y;
var MAX_HEIGHT = instance.refs.container.offsetHeight - instance.refs.viewport.offsetHeight;
if (_currentPos < -MAX_HEIGHT) {
_currentPos = -MAX_HEIGHT;
}
if (_currentPos > 0) {
_currentPos = 0;
}
instance._y = Math.round(_currentPos);
instance.refs.container.style.top = instance._y + 'px';
}
function _animate(destY, startY, duration) {
var startTime = getTime();
var destTime = startTime + duration;
function step() {
var now = getTime();
var newY = undefined;
var easing = undefined;
if (now >= destTime) {
_translate(destY);
return;
}
now = (now - startTime) / duration;
easing = _easing(now);
newY = (destY - startY) * easing + startY;
_translate(newY);
if (_isAnimating) {
rAF(step);
}
}
_isAnimating = true;
step();
}
function _start(e) {
var target = e.target;
if (rException.test(target.tagName) || target.getAttribute('data-cid') === 'sinput') {
return;
}
if (target.getAttribute('data-cid') === 'clear' || target.parentNode.getAttribute('data-cid') === 'clear') {
instance.onClear();
return;
}
var _e = _event(e);
_lastEl = _e.target;
_startTime = getTime();
_startY = instance._y;
_pageY = _e.pageY;
_distY = 0;
if (_isAnimating) {
_isAnimating = false;
_translate(_startY);
}
e.preventDefault();
}
function _move(e) {
if (!_lastEl) {
return;
}
var _e = _event(e);
var _diff = Math.round(_e.pageY - _pageY);
_distY += _diff;
_pageY = _e.pageY;
instance._y += _diff;
_translate(instance._y);
}
function _end() {
if (!_lastEl) {
return;
}
_lastEl = null;
if (Math.abs(_distY) < VALVE) {
return;
}
_endTime = getTime();
var _duration = _endTime - _startTime;
if (_duration < 300) {
var _momentum = momentum(instance._y, _startY, _duration);
if (Math.abs(_momentum.destination) > 0) {
instance._y = _momentum.destination;
_duration = Math.max(_duration, _momentum.duration);
_animate(instance._y, _startY, _duration);
}
}
}
eventManager.addHandler({
start: _start,
move: _move,
end: _end
});
}
function handleTapping(eventManager, instance) {
var _el = null;
var _isEnded = false;
var _deltaX = 0;
var _deltaY = 0;
var _lastPageX = 0;
var _lastPageY = 0;
var _noop = false;
function _touchStart(e) {
if ((e.touches || [e]).length !== 1) {
_noop = true;
return;
}
var target = e.target;
while (target) {
if (!target.getAttribute || target.getAttribute('data-key')) {
break;
}
target = target.parentNode;
}
if (!target.getAttribute) {
target = e.target;
}
_el = {
_src: target,
target: target,
pageX: _pageX(e),
pageY: _getPageY(e),
time: getTime()
};
_noop = false;
_lastPageX = _el.pageX;
_lastPageY = _el.pageY;
_isEnded = false;
_deltaX = 0;
_deltaY = 0;
}
function _touchMove(e) {
if (_isEnded || _noop || !_el) {
return;
}
_deltaX += _pageX(e) - _lastPageX;
_deltaY += _getPageY(e) - _lastPageY;
_lastPageX = _pageX(e);
_lastPageY = _getPageY(e);
if (Math.abs(_deltaY) > VALVE || Math.abs(_deltaX) > VALVE) {
_el = null;
}
}
function _touchEnd(e) {
_isEnded = true;
if (_noop || !_el) {
return;
}
_deltaX += _pageX(e) - _lastPageX;
_deltaY += _getPageY(e) - _lastPageY;
_lastPageX = _pageX(e);
_lastPageY = _getPageY(e);
if (Math.abs(_deltaY) > VALVE || Math.abs(_deltaX) > VALVE) {
_el = null;
return;
}
var target = _el.target;
var id = target.getAttribute('data-key');
var isHit = false;
if (id) {
// todo. setTimeout is necessary ?
setTimeout(function () {
instance.onChange(instance.cache[id + '_' + target.getAttribute('data-spell')]);
}, 0);
isHit = true;
} else if (target.getAttribute('data-cid') === 'sinput') {
setTimeout(function () {
target.focus();
instance.onSearch();
}, 0);
} else if (target.getAttribute('data-cid') === 'clear' || target.parentNode.getAttribute('data-cid') === 'clear') {
instance.onClear();
isHit = true;
}
_el = null;
if (isHit) {
e.preventDefault();
}
}
eventManager.addHandler({
start: _touchStart,
move: _touchMove,
end: _touchEnd
});
if (isBadMobile || !isTouchable) {
return handleScrolling(eventManager, instance);
}
instance._useNative = true;
(0, _objectAssign2.default)(instance.refs.viewport.style, {
'-webkit-overflow-scrolling': 'touch',
'z-index': '998',
overflow: 'auto'
});
}
function handleQuickBar(instance, element) {
var hCache = [];
var quickSearchBar = instance.refs.quickSearchBar;
var height = quickSearchBar.offsetHeight;
[].slice.call(quickSearchBar.querySelectorAll('[data-qf-target]')).forEach(function (d) {
hCache.push([d]);
});
var _avgH = height / hCache.length;
var _top = 0;
for (var i = 0, len = hCache.length; i < len; i++) {
_top = i * _avgH;
hCache[i][1] = [_top, _top + _avgH];
}
// relative to container
function _getEle(e, basePos) {
var _pos = undefined;
if (e.pageY >= basePos.top && e.pageY <= basePos.top + height) {
_pos = Math.floor((e.pageY - basePos.top) / _avgH);
if (_pos in hCache) {
return hCache[_pos][0];
}
}
return null;
}
var _inMoving = false;
var _isProcessed = false;
var _basePos = undefined;
var tAttr = 'data-qf-target';
function _updatePosition(ele) {
var pos = ele.offsetTop;
if (instance._useNative) {
setTimeout(function () {
instance.refs.viewport.scrollTop = pos;
}, 20);
} else {
instance._y = -pos;
instance.refs.container.style.top = -pos + 'px';
}
}
var _timer = undefined;
function _updateLighter(ele, isEnd) {
var el = ele;
if (!el.getAttribute(tAttr)) {
el = el.parentNode;
}
instance.refs.lighter.innerText = el.innerText.trim();
instance.setState({
showLighter: true
});
clearTimeout(_timer);
_timer = setTimeout(function () {
instance.setState({
showLighter: false
});
}, 1000);
var cls = 'quick-search-over';
hCache.forEach(function (d) {
d[0].className = d[0].className.replace(cls, '');
});
if (!isEnd) {
el.className = el.className + ' ' + cls;
}
}
var _target = undefined;
function _start(e) {
_target = e.target;
if (_target.getAttribute(tAttr) || _target.parentNode.getAttribute(tAttr)) {
_inMoving = true;
_isProcessed = false;
_basePos = quickSearchBar.getBoundingClientRect();
_updateLighter(_target);
}
e.preventDefault();
instance.setState({
clickFeedBack: true
});
}
function _move(e) {
var ele = undefined;
var id = undefined;
var target = undefined;
if (_inMoving && _target) {
target = _getEle(_event(e), _basePos);
if (target) {
_isProcessed = true;
id = target.getAttribute(tAttr);
ele = element.querySelector(id);
if (ele) {
_updatePosition(ele);
}
_updateLighter(target);
_target = target;
}
}
e.preventDefault();
}
function _end() {
if (!_target) {
return;
}
var id = _target.getAttribute(tAttr) || _target.parentNode.getAttribute(tAttr);
var ele = undefined;
if (id) {
if (_inMoving && !_isProcessed) {
ele = element.querySelector(id);
if (ele) {
_updatePosition(ele);
}
}
_updateLighter(_target, true);
}
_isProcessed = true;
_inMoving = false;
_target = null;
instance.setState({
clickFeedBack: false
});
}
var eventManager = new EventManager(quickSearchBar);
eventManager.addHandler({
start: _start,
move: _move,
end: _end
});
return eventManager;
}