You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
372 lines
12 KiB
372 lines
12 KiB
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
|
|
var _Scroller = require('./Scroller');
|
|
|
|
var _Scroller2 = _interopRequireDefault(_Scroller);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
var MIN_INDICATOR_SIZE = 8;
|
|
var win = typeof window !== 'undefined' ? window : undefined;
|
|
|
|
if (!win) {
|
|
win = typeof global !== 'undefined' ? global : {};
|
|
}
|
|
|
|
function setTransform(nodeStyle, value) {
|
|
nodeStyle.transform = value;
|
|
nodeStyle.webkitTransform = value;
|
|
nodeStyle.MozTransform = value;
|
|
}
|
|
|
|
function setTransformOrigin(nodeStyle, value) {
|
|
nodeStyle.transformOrigin = value;
|
|
nodeStyle.webkitTransformOrigin = value;
|
|
nodeStyle.MozTransformOrigin = value;
|
|
}
|
|
|
|
var supportsPassive = false;
|
|
try {
|
|
var opts = Object.defineProperty({}, 'passive', {
|
|
get: function get() {
|
|
supportsPassive = true;
|
|
}
|
|
});
|
|
win.addEventListener('test', null, opts);
|
|
} catch (e) {
|
|
// empty
|
|
}
|
|
|
|
var isWebView = typeof navigator !== 'undefined' && /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent);
|
|
|
|
function iOSWebViewFix(e, touchendFn) {
|
|
// https://github.com/ant-design/ant-design-mobile/issues/573#issuecomment-339560829
|
|
// iOS UIWebView issue, It seems no problem in WKWebView
|
|
if (isWebView && e.changedTouches[0].clientY < 0) {
|
|
touchendFn(new Event('touchend') || e);
|
|
}
|
|
}
|
|
|
|
var willPreventDefault = supportsPassive ? { passive: false } : false;
|
|
var willNotPreventDefault = supportsPassive ? { passive: true } : false;
|
|
|
|
function addEventListener(target, type, fn, options) {
|
|
target.addEventListener(type, fn, options);
|
|
return function () {
|
|
target.removeEventListener(type, fn, options);
|
|
};
|
|
}
|
|
|
|
function DOMScroller(content) {
|
|
var _this = this;
|
|
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
var scrollbars = void 0;
|
|
var indicators = void 0;
|
|
var indicatorsSize = void 0;
|
|
var scrollbarsSize = void 0;
|
|
var indicatorsPos = void 0;
|
|
var scrollbarsOpacity = void 0;
|
|
var contentSize = void 0;
|
|
var clientSize = void 0;
|
|
|
|
this.content = content;
|
|
var container = this.container = content.parentNode;
|
|
this.options = _extends({}, options, {
|
|
scrollingComplete: function scrollingComplete() {
|
|
_this.clearScrollbarTimer();
|
|
_this.timer = setTimeout(function () {
|
|
if (_this._destroyed) {
|
|
return;
|
|
}
|
|
if (options.scrollingComplete) {
|
|
options.scrollingComplete();
|
|
}
|
|
if (scrollbars) {
|
|
['x', 'y'].forEach(function (k) {
|
|
if (scrollbars[k]) {
|
|
_this.setScrollbarOpacity(k, 0);
|
|
}
|
|
});
|
|
}
|
|
}, 0);
|
|
}
|
|
});
|
|
|
|
if (this.options.scrollbars) {
|
|
scrollbars = this.scrollbars = {};
|
|
indicators = this.indicators = {};
|
|
indicatorsSize = this.indicatorsSize = {};
|
|
scrollbarsSize = this.scrollbarsSize = {};
|
|
indicatorsPos = this.indicatorsPos = {};
|
|
scrollbarsOpacity = this.scrollbarsOpacity = {};
|
|
contentSize = this.contentSize = {};
|
|
clientSize = this.clientSize = {};
|
|
|
|
['x', 'y'].forEach(function (k) {
|
|
var optionName = k === 'x' ? 'scrollingX' : 'scrollingY';
|
|
if (_this.options[optionName] !== false) {
|
|
scrollbars[k] = document.createElement('div');
|
|
scrollbars[k].className = 'zscroller-scrollbar-' + k;
|
|
indicators[k] = document.createElement('div');
|
|
indicators[k].className = 'zscroller-indicator-' + k;
|
|
scrollbars[k].appendChild(indicators[k]);
|
|
indicatorsSize[k] = -1;
|
|
scrollbarsOpacity[k] = 0;
|
|
indicatorsPos[k] = 0;
|
|
container.appendChild(scrollbars[k]);
|
|
}
|
|
});
|
|
}
|
|
|
|
var init = true;
|
|
var contentStyle = content.style;
|
|
|
|
// create Scroller instance
|
|
this.scroller = new _Scroller2['default'](function (left, top, zoom) {
|
|
if (!init && options.onScroll) {
|
|
options.onScroll();
|
|
}
|
|
setTransform(contentStyle, 'translate3d(' + -left + 'px,' + -top + 'px,0) scale(' + zoom + ')');
|
|
if (scrollbars) {
|
|
['x', 'y'].forEach(function (k) {
|
|
if (scrollbars[k]) {
|
|
var pos = k === 'x' ? left : top;
|
|
if (clientSize[k] >= contentSize[k]) {
|
|
_this.setScrollbarOpacity(k, 0);
|
|
} else {
|
|
if (!init) {
|
|
_this.setScrollbarOpacity(k, 1);
|
|
}
|
|
var normalIndicatorSize = clientSize[k] / contentSize[k] * scrollbarsSize[k];
|
|
var size = normalIndicatorSize;
|
|
var indicatorPos = void 0;
|
|
if (pos < 0) {
|
|
size = Math.max(normalIndicatorSize + pos, MIN_INDICATOR_SIZE);
|
|
indicatorPos = 0;
|
|
} else if (pos > contentSize[k] - clientSize[k]) {
|
|
size = Math.max(normalIndicatorSize + contentSize[k] - clientSize[k] - pos, MIN_INDICATOR_SIZE);
|
|
indicatorPos = scrollbarsSize[k] - size;
|
|
} else {
|
|
indicatorPos = pos / contentSize[k] * scrollbarsSize[k];
|
|
}
|
|
_this.setIndicatorSize(k, size);
|
|
_this.setIndicatorPos(k, indicatorPos);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
init = false;
|
|
}, this.options);
|
|
|
|
// bind events
|
|
this.bindEvents();
|
|
|
|
// the content element needs a correct transform origin for zooming
|
|
setTransformOrigin(content.style, 'left top');
|
|
|
|
// reflow for the first time
|
|
this.reflow();
|
|
}
|
|
|
|
DOMScroller.prototype = {
|
|
constructor: DOMScroller,
|
|
setDisabled: function setDisabled(disabled) {
|
|
this.disabled = disabled;
|
|
},
|
|
clearScrollbarTimer: function clearScrollbarTimer() {
|
|
if (this.timer) {
|
|
clearTimeout(this.timer);
|
|
this.timer = null;
|
|
}
|
|
},
|
|
setScrollbarOpacity: function setScrollbarOpacity(axis, opacity) {
|
|
if (this.scrollbarsOpacity[axis] !== opacity) {
|
|
this.scrollbars[axis].style.opacity = opacity;
|
|
this.scrollbarsOpacity[axis] = opacity;
|
|
}
|
|
},
|
|
setIndicatorPos: function setIndicatorPos(axis, value) {
|
|
var indicatorsPos = this.indicatorsPos,
|
|
indicators = this.indicators;
|
|
|
|
if (indicatorsPos[axis] !== value) {
|
|
if (axis === 'x') {
|
|
setTransform(indicators[axis].style, 'translate3d(' + value + 'px,0,0)');
|
|
} else {
|
|
setTransform(indicators[axis].style, 'translate3d(0, ' + value + 'px,0)');
|
|
}
|
|
indicatorsPos[axis] = value;
|
|
}
|
|
},
|
|
setIndicatorSize: function setIndicatorSize(axis, value) {
|
|
var indicatorsSize = this.indicatorsSize,
|
|
indicators = this.indicators;
|
|
|
|
if (indicatorsSize[axis] !== value) {
|
|
indicators[axis].style[axis === 'x' ? 'width' : 'height'] = value + 'px';
|
|
indicatorsSize[axis] = value;
|
|
}
|
|
},
|
|
reflow: function reflow() {
|
|
var container = this.container,
|
|
content = this.content,
|
|
scrollbarsSize = this.scrollbarsSize,
|
|
contentSize = this.contentSize,
|
|
scrollbars = this.scrollbars,
|
|
clientSize = this.clientSize,
|
|
scroller = this.scroller;
|
|
|
|
if (scrollbars) {
|
|
contentSize.x = content.offsetWidth;
|
|
contentSize.y = content.offsetHeight;
|
|
clientSize.x = container.clientWidth;
|
|
clientSize.y = container.clientHeight;
|
|
if (scrollbars.x) {
|
|
scrollbarsSize.x = scrollbars.x.offsetWidth;
|
|
}
|
|
if (scrollbars.y) {
|
|
scrollbarsSize.y = scrollbars.y.offsetHeight;
|
|
}
|
|
}
|
|
// set the right scroller dimensions
|
|
scroller.setDimensions(container.clientWidth, container.clientHeight, content.offsetWidth, content.offsetHeight);
|
|
|
|
// refresh the position for zooming purposes
|
|
var rect = container.getBoundingClientRect();
|
|
scroller.setPosition(rect.x + container.clientLeft, rect.y + container.clientTop);
|
|
},
|
|
destroy: function destroy() {
|
|
this._destroyed = true;
|
|
this.unbindEvent();
|
|
},
|
|
unbindEvent: function unbindEvent(type) {
|
|
var eventHandlers = this.eventHandlers;
|
|
|
|
if (type) {
|
|
if (eventHandlers[type]) {
|
|
eventHandlers[type]();
|
|
delete eventHandlers[type];
|
|
}
|
|
} else {
|
|
Object.keys(eventHandlers).forEach(function (t) {
|
|
eventHandlers[t]();
|
|
delete eventHandlers[t];
|
|
});
|
|
}
|
|
},
|
|
bindEvent: function bindEvent(target, type, fn, options) {
|
|
var eventHandlers = this.eventHandlers;
|
|
|
|
if (eventHandlers[type]) {
|
|
eventHandlers[type]();
|
|
}
|
|
eventHandlers[type] = addEventListener(target, type, fn, options);
|
|
},
|
|
bindEvents: function bindEvents() {
|
|
var _this2 = this;
|
|
|
|
// reflow handling
|
|
this.eventHandlers = {};
|
|
|
|
this.bindEvent(win, 'resize', function () {
|
|
_this2.reflow();
|
|
}, false);
|
|
|
|
var lockMouse = false;
|
|
var releaseLockTimer = void 0;
|
|
|
|
var container = this.container,
|
|
scroller = this.scroller;
|
|
|
|
|
|
this.bindEvent(container, 'touchstart', function (e) {
|
|
lockMouse = true;
|
|
if (releaseLockTimer) {
|
|
clearTimeout(releaseLockTimer);
|
|
releaseLockTimer = null;
|
|
}
|
|
// Don't react if initial down happens on a form element
|
|
if (e.touches[0] && e.touches[0].target && e.touches[0].target.tagName.match(/input|textarea|select/i) || _this2.disabled) {
|
|
return;
|
|
}
|
|
_this2.clearScrollbarTimer();
|
|
// reflow since the container may have changed
|
|
_this2.reflow();
|
|
scroller.doTouchStart(e.touches, e.timeStamp);
|
|
}, willNotPreventDefault);
|
|
|
|
var _options = this.options,
|
|
preventDefaultOnTouchMove = _options.preventDefaultOnTouchMove,
|
|
zooming = _options.zooming;
|
|
|
|
var onTouchEnd = function onTouchEnd(e) {
|
|
scroller.doTouchEnd(e.timeStamp);
|
|
releaseLockTimer = setTimeout(function () {
|
|
lockMouse = false;
|
|
}, 300);
|
|
};
|
|
|
|
if (preventDefaultOnTouchMove !== false) {
|
|
this.bindEvent(container, 'touchmove', function (e) {
|
|
e.preventDefault();
|
|
scroller.doTouchMove(e.touches, e.timeStamp, e.scale);
|
|
iOSWebViewFix(e, onTouchEnd);
|
|
}, willPreventDefault);
|
|
} else {
|
|
this.bindEvent(container, 'touchmove', function (e) {
|
|
scroller.doTouchMove(e.touches, e.timeStamp, e.scale);
|
|
iOSWebViewFix(e, onTouchEnd);
|
|
}, willNotPreventDefault);
|
|
}
|
|
|
|
this.bindEvent(container, 'touchend', onTouchEnd, willNotPreventDefault);
|
|
this.bindEvent(container, 'touchcancel', onTouchEnd, willNotPreventDefault);
|
|
|
|
var onMouseUp = function onMouseUp(e) {
|
|
scroller.doTouchEnd(e.timeStamp);
|
|
_this2.unbindEvent('mousemove');
|
|
_this2.unbindEvent('mouseup');
|
|
};
|
|
|
|
var onMouseMove = function onMouseMove(e) {
|
|
scroller.doTouchMove([{
|
|
pageX: e.pageX,
|
|
pageY: e.pageY
|
|
}], e.timeStamp);
|
|
};
|
|
|
|
this.bindEvent(container, 'mousedown', function (e) {
|
|
if (lockMouse || e.target.tagName.match(/input|textarea|select/i) || _this2.disabled) {
|
|
return;
|
|
}
|
|
_this2.clearScrollbarTimer();
|
|
scroller.doTouchStart([{
|
|
pageX: e.pageX,
|
|
pageY: e.pageY
|
|
}], e.timeStamp);
|
|
// reflow since the container may have changed
|
|
_this2.reflow();
|
|
e.preventDefault();
|
|
_this2.bindEvent(document, 'mousemove', onMouseMove, willNotPreventDefault);
|
|
_this2.bindEvent(document, 'mouseup', onMouseUp, willNotPreventDefault);
|
|
}, willPreventDefault);
|
|
|
|
if (zooming) {
|
|
this.bindEvent(container, 'mousewheel', function (e) {
|
|
scroller.doMouseZoom(e.wheelDelta, e.timeStamp, e.pageX, e.pageY);
|
|
e.preventDefault();
|
|
}, willPreventDefault);
|
|
}
|
|
}
|
|
};
|
|
|
|
exports['default'] = DOMScroller;
|
|
module.exports = exports['default']; |