UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

292 lines (239 loc) • 9.95 kB
"use strict"; var $ = require("../../core/renderer"), eventsEngine = require("../../events/core/events_engine"), noop = require("../../core/utils/common").noop, each = require("../../core/utils/iterator").each, devices = require("../../core/devices"), Class = require("../../core/class"), Scrollbar = require("./ui.scrollbar"); var SCROLLABLE_NATIVE = "dxNativeScrollable", SCROLLABLE_NATIVE_CLASS = "dx-scrollable-native", SCROLLABLE_SCROLLBAR_SIMULATED = "dx-scrollable-scrollbar-simulated", SCROLLABLE_SCROLLBARS_HIDDEN = "dx-scrollable-scrollbars-hidden", VERTICAL = "vertical", HORIZONTAL = "horizontal", HIDE_SCROLLBAR_TIMEOUT = 500; var NativeStrategy = Class.inherit({ ctor: function ctor(scrollable) { this._init(scrollable); }, _init: function _init(scrollable) { this._component = scrollable; this._$element = scrollable.$element(); this._$container = scrollable._$container; this._$content = scrollable._$content; this._direction = scrollable.option("direction"); this._useSimulatedScrollbar = scrollable.option("useSimulatedScrollbar"); this._showScrollbar = scrollable.option("showScrollbar"); this.option = scrollable.option.bind(scrollable); this._createActionByOption = scrollable._createActionByOption.bind(scrollable); this._isLocked = scrollable._isLocked.bind(scrollable); this._isDirection = scrollable._isDirection.bind(scrollable); this._allowedDirection = scrollable._allowedDirection.bind(scrollable); }, render: function render() { this._renderPushBackOffset(); var device = devices.real(), deviceType = device.platform; this._$element.addClass(SCROLLABLE_NATIVE_CLASS).addClass(SCROLLABLE_NATIVE_CLASS + "-" + deviceType).toggleClass(SCROLLABLE_SCROLLBARS_HIDDEN, !this._showScrollbar); if (this._showScrollbar && this._useSimulatedScrollbar) { this._renderScrollbars(); } }, updateBounds: noop, _renderPushBackOffset: function _renderPushBackOffset() { var pushBackValue = this.option("pushBackValue"); if (!pushBackValue && !this._component._lastPushBackValue) { return; } this._$content.css({ paddingTop: pushBackValue, paddingBottom: pushBackValue }); this._component._lastPushBackValue = pushBackValue; }, _renderScrollbars: function _renderScrollbars() { this._scrollbars = {}; this._hideScrollbarTimeout = 0; this._$element.addClass(SCROLLABLE_SCROLLBAR_SIMULATED); this._renderScrollbar(VERTICAL); this._renderScrollbar(HORIZONTAL); }, _renderScrollbar: function _renderScrollbar(direction) { if (!this._isDirection(direction)) { return; } this._scrollbars[direction] = new Scrollbar($("<div>").appendTo(this._$element), { direction: direction, expandable: this._component.option("scrollByThumb") }); }, handleInit: noop, handleStart: function handleStart() { this._disablePushBack = true; }, handleMove: function handleMove(e) { if (this._isLocked()) { e.cancel = true; return; } if (this._allowedDirection()) { e.originalEvent.isScrollingEvent = true; } }, handleEnd: function handleEnd() { this._disablePushBack = false; }, handleCancel: noop, handleStop: noop, _eachScrollbar: function _eachScrollbar(callback) { callback = callback.bind(this); each(this._scrollbars || {}, function (direction, scrollbar) { callback(scrollbar, direction); }); }, createActions: function createActions() { this._scrollAction = this._createActionByOption("onScroll"); this._updateAction = this._createActionByOption("onUpdated"); }, _createActionArgs: function _createActionArgs() { var location = this.location(); return { event: this._eventForUserAction, scrollOffset: { top: -location.top, left: -location.left }, reachedLeft: this._isDirection(HORIZONTAL) ? location.left >= 0 : undefined, reachedRight: this._isDirection(HORIZONTAL) ? location.left <= this._containerSize.width - this._componentContentSize.width : undefined, reachedTop: this._isDirection(VERTICAL) ? location.top >= 0 : undefined, reachedBottom: this._isDirection(VERTICAL) ? location.top <= this._containerSize.height - this._componentContentSize.height : undefined }; }, handleScroll: function handleScroll(e) { // NOTE: ignoring scroll events when scroll location was not changed (for Android browser - B250122) if (!this._isScrollLocationChanged()) { e.stopImmediatePropagation(); return; } this._eventForUserAction = e; this._moveScrollbars(); this._scrollAction(this._createActionArgs()); this._lastLocation = this.location(); this._pushBackFromBoundary(); }, _pushBackFromBoundary: function _pushBackFromBoundary() { var pushBackValue = this.option("pushBackValue"); if (!pushBackValue || this._disablePushBack) { return; } var scrollOffset = this._containerSize.height - this._contentSize.height, scrollTopPos = this._$container.scrollTop(), scrollBottomPos = scrollOffset + scrollTopPos - pushBackValue * 2; if (!scrollTopPos) { this._$container.scrollTop(pushBackValue); } else if (!scrollBottomPos) { this._$container.scrollTop(pushBackValue - scrollOffset); } }, _isScrollLocationChanged: function _isScrollLocationChanged() { var currentLocation = this.location(), lastLocation = this._lastLocation || {}, isTopChanged = lastLocation.top !== currentLocation.top, isLeftChanged = lastLocation.left !== currentLocation.left; return isTopChanged || isLeftChanged; }, _moveScrollbars: function _moveScrollbars() { this._eachScrollbar(function (scrollbar) { scrollbar.moveTo(this.location()); scrollbar.option("visible", true); }); this._hideScrollbars(); }, _hideScrollbars: function _hideScrollbars() { clearTimeout(this._hideScrollbarTimeout); this._hideScrollbarTimeout = setTimeout(function () { this._eachScrollbar(function (scrollbar) { scrollbar.option("visible", false); }); }.bind(this), HIDE_SCROLLBAR_TIMEOUT); }, location: function location() { return { left: -this._$container.scrollLeft(), top: this.option("pushBackValue") - this._$container.scrollTop() }; }, disabledChanged: noop, update: function update() { this._update(); this._updateAction(this._createActionArgs()); }, _update: function _update() { this._updateDimensions(); this._updateScrollbars(); }, _updateDimensions: function _updateDimensions() { this._containerSize = { height: this._$container.height(), width: this._$container.width() }; this._componentContentSize = { height: this._component.$content().height(), width: this._component.$content().width() }; this._contentSize = { height: this._$content.height(), width: this._$content.width() }; this._pushBackFromBoundary(); }, _updateScrollbars: function _updateScrollbars() { this._eachScrollbar(function (scrollbar, direction) { var dimension = direction === VERTICAL ? "height" : "width"; scrollbar.option({ containerSize: this._containerSize[dimension], contentSize: this._componentContentSize[dimension] }); scrollbar.update(); }); }, _allowedDirections: function _allowedDirections() { return { vertical: this._isDirection(VERTICAL) && this._contentSize.height > this._containerSize.height, horizontal: this._isDirection(HORIZONTAL) && this._contentSize.width > this._containerSize.width }; }, dispose: function dispose() { var className = this._$element.get(0).className; var scrollableNativeRegexp = new RegExp(SCROLLABLE_NATIVE_CLASS + "\\S*", "g"); if (scrollableNativeRegexp.test(className)) { this._$element.removeClass(className.match(scrollableNativeRegexp).join(" ")); } eventsEngine.off(this._$element, "." + SCROLLABLE_NATIVE); eventsEngine.off(this._$container, "." + SCROLLABLE_NATIVE); this._removeScrollbars(); clearTimeout(this._gestureEndTimer); clearTimeout(this._hideScrollbarTimeout); }, _removeScrollbars: function _removeScrollbars() { this._eachScrollbar(function (scrollbar) { scrollbar.$element().remove(); }); }, scrollBy: function scrollBy(distance) { var location = this.location(); this._$container.scrollTop(-location.top - distance.top + this.option("pushBackValue")); this._$container.scrollLeft(-location.left - distance.left); }, validate: function validate() { return !this.option("disabled") && this._allowedDirection(); }, getDirection: function getDirection() { return this._allowedDirection(); }, verticalOffset: function verticalOffset() { return this.option("pushBackValue"); } }); module.exports = NativeStrategy;