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

'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'];