UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

205 lines (204 loc) • 7.78 kB
/** * DevExtreme (ui/scroll_view/ui.scrollbar.js) * Version: 18.1.3 * Build date: Tue May 15 2018 * * Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var $ = require("../../core/renderer"), domAdapter = require("../../core/dom_adapter"), eventsEngine = require("../../events/core/events_engine"), ready = require("../../core/utils/ready_callbacks").add, translator = require("../../animation/translator"), Widget = require("../widget/ui.widget"), eventUtils = require("../../events/utils"), commonUtils = require("../../core/utils/common"), isPlainObject = require("../../core/utils/type").isPlainObject, extend = require("../../core/utils/extend").extend, pointerEvents = require("../../events/pointer"); var SCROLLBAR = "dxScrollbar", SCROLLABLE_SCROLLBAR_CLASS = "dx-scrollable-scrollbar", SCROLLABLE_SCROLLBAR_ACTIVE_CLASS = SCROLLABLE_SCROLLBAR_CLASS + "-active", SCROLLABLE_SCROLL_CLASS = "dx-scrollable-scroll", SCROLLABLE_SCROLL_CONTENT_CLASS = "dx-scrollable-scroll-content", HOVER_ENABLED_STATE = "dx-scrollbar-hoverable", HORIZONTAL = "horizontal", THUMB_MIN_SIZE = 15; var SCROLLBAR_VISIBLE = { onScroll: "onScroll", onHover: "onHover", always: "always", never: "never" }; var Scrollbar = Widget.inherit({ _getDefaultOptions: function() { return extend(this.callBase(), { direction: null, visible: false, activeStateEnabled: false, visibilityMode: SCROLLBAR_VISIBLE.onScroll, containerSize: 0, contentSize: 0, expandable: true }) }, _init: function() { this.callBase(); this._isHovered = false }, _initMarkup: function() { this._renderThumb(); this.callBase() }, _render: function() { this.callBase(); this._renderDirection(); this._update(); this._attachPointerDownHandler(); this.option("hoverStateEnabled", this._isHoverMode()); this.$element().toggleClass(HOVER_ENABLED_STATE, this.option("hoverStateEnabled")) }, _renderThumb: function() { this._$thumb = $("<div>").addClass(SCROLLABLE_SCROLL_CLASS); $("<div>").addClass(SCROLLABLE_SCROLL_CONTENT_CLASS).appendTo(this._$thumb); this.$element().addClass(SCROLLABLE_SCROLLBAR_CLASS).append(this._$thumb) }, isThumb: function($element) { return !!this.$element().find($element).length }, _isHoverMode: function() { var visibilityMode = this.option("visibilityMode"); return (visibilityMode === SCROLLBAR_VISIBLE.onHover || visibilityMode === SCROLLBAR_VISIBLE.always) && this.option("expandable") }, _renderDirection: function() { var direction = this.option("direction"); this.$element().addClass("dx-scrollbar-" + direction); this._dimension = direction === HORIZONTAL ? "width" : "height"; this._prop = direction === HORIZONTAL ? "left" : "top" }, _attachPointerDownHandler: function() { eventsEngine.on(this._$thumb, eventUtils.addNamespace(pointerEvents.down, SCROLLBAR), this.feedbackOn.bind(this)) }, feedbackOn: function() { this.$element().addClass(SCROLLABLE_SCROLLBAR_ACTIVE_CLASS); activeScrollbar = this }, feedbackOff: function() { this.$element().removeClass(SCROLLABLE_SCROLLBAR_ACTIVE_CLASS); activeScrollbar = null }, cursorEnter: function() { this._isHovered = true; this.option("visible", true) }, cursorLeave: function() { this._isHovered = false; this.option("visible", false) }, _renderDimensions: function() { this._$thumb.css({ width: this.option("width"), height: this.option("height") }) }, _toggleVisibility: function(visible) { if (this.option("visibilityMode") === SCROLLBAR_VISIBLE.onScroll) { this._$thumb.css("opacity") } visible = this._adjustVisibility(visible); this.option().visible = visible; this._$thumb.toggleClass("dx-state-invisible", !visible) }, _adjustVisibility: function(visible) { if (this.containerToContentRatio() && !this._needScrollbar()) { return false } switch (this.option("visibilityMode")) { case SCROLLBAR_VISIBLE.onScroll: break; case SCROLLBAR_VISIBLE.onHover: visible = visible || !!this._isHovered; break; case SCROLLBAR_VISIBLE.never: visible = false; break; case SCROLLBAR_VISIBLE.always: visible = true } return visible }, moveTo: function(location) { if (this._isHidden()) { return } if (isPlainObject(location)) { location = location[this._prop] || 0 } var scrollBarLocation = {}; scrollBarLocation[this._prop] = this._calculateScrollBarPosition(location); translator.move(this._$thumb, scrollBarLocation) }, _calculateScrollBarPosition: function(location) { return -location * this._thumbRatio }, _update: function() { var containerSize = Math.round(this.option("containerSize")), contentSize = Math.round(this.option("contentSize")); this._containerToContentRatio = contentSize ? containerSize / contentSize : containerSize; var thumbSize = Math.round(Math.max(Math.round(containerSize * this._containerToContentRatio), THUMB_MIN_SIZE)); this._thumbRatio = (containerSize - thumbSize) / (contentSize - containerSize); this.option(this._dimension, thumbSize); this.$element().css("display", this._needScrollbar() ? "" : "none") }, _isHidden: function() { return this.option("visibilityMode") === SCROLLBAR_VISIBLE.never }, _needScrollbar: function() { return !this._isHidden() && this._containerToContentRatio < 1 }, containerToContentRatio: function() { return this._containerToContentRatio }, _normalizeSize: function(size) { return isPlainObject(size) ? size[this._dimension] || 0 : size }, _clean: function() { this.callBase(); if (this === activeScrollbar) { activeScrollbar = null } eventsEngine.off(this._$thumb, "." + SCROLLBAR) }, _optionChanged: function(args) { if (this._isHidden()) { return } switch (args.name) { case "containerSize": case "contentSize": this.option()[args.name] = this._normalizeSize(args.value); this._update(); break; case "visibilityMode": case "direction": this._invalidate(); break; default: this.callBase.apply(this, arguments) } }, update: commonUtils.deferRenderer(function() { this._adjustVisibility() && this.option("visible", true) }) }); var activeScrollbar = null; ready(function() { eventsEngine.subscribeGlobal(domAdapter.getDocument(), eventUtils.addNamespace(pointerEvents.up, SCROLLBAR), function() { if (activeScrollbar) { activeScrollbar.feedbackOff() } }) }); module.exports = Scrollbar;