devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
264 lines (261 loc) • 9.7 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/scroll_view/m_scrollbar.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _translator = require("../../../common/core/animation/translator");
var _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine"));
var _pointer = _interopRequireDefault(require("../../../common/core/events/pointer"));
var _index = require("../../../common/core/events/utils/index");
var _dom_adapter = _interopRequireDefault(require("../../../core/dom_adapter"));
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _common = require("../../../core/utils/common");
var _ready_callbacks = _interopRequireDefault(require("../../../core/utils/ready_callbacks"));
var _type = require("../../../core/utils/type");
var _widget = _interopRequireDefault(require("../../core/widget/widget"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
function _extends() {
return _extends = Object.assign ? Object.assign.bind() : function(n) {
for (var e = 1; e < arguments.length; e++) {
var t = arguments[e];
for (var r in t) {
({}).hasOwnProperty.call(t, r) && (n[r] = t[r])
}
}
return n
}, _extends.apply(null, arguments)
}
const SCROLLBAR = "dxScrollbar";
const SCROLLABLE_SCROLLBAR_CLASS = "dx-scrollable-scrollbar";
const SCROLLABLE_SCROLLBAR_ACTIVE_CLASS = "dx-scrollable-scrollbar-active";
const SCROLLABLE_SCROLL_CLASS = "dx-scrollable-scroll";
const SCROLLABLE_SCROLL_CONTENT_CLASS = "dx-scrollable-scroll-content";
const HOVER_ENABLED_STATE = "dx-scrollbar-hoverable";
const HORIZONTAL = "horizontal";
const THUMB_MIN_SIZE = 15;
const SCROLLBAR_VISIBLE = {
onScroll: "onScroll",
onHover: "onHover",
always: "always",
never: "never"
};
let activeScrollbar = null;
class Scrollbar extends _widget.default {
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
direction: null,
visible: false,
activeStateEnabled: false,
visibilityMode: SCROLLBAR_VISIBLE.onScroll,
containerSize: 0,
contentSize: 0,
expandable: true,
scaleRatio: 1
})
}
_init() {
super._init();
this._isHovered = false
}
_initMarkup() {
this._renderThumb();
super._initMarkup()
}
_render() {
super._render();
this._renderDirection();
this._update();
this._attachPointerDownHandler();
this.option("hoverStateEnabled", this._isHoverMode());
const {
hoverStateEnabled: hoverStateEnabled
} = this.option();
this.$element().toggleClass(HOVER_ENABLED_STATE, hoverStateEnabled)
}
_renderThumb() {
this._$thumb = (0, _renderer.default)("<div>").addClass("dx-scrollable-scroll");
(0, _renderer.default)("<div>").addClass("dx-scrollable-scroll-content").appendTo(this._$thumb);
this.$element().addClass("dx-scrollable-scrollbar").append(this._$thumb)
}
isThumb($element) {
return !!this.$element().find($element).length
}
_isHoverMode() {
const {
visibilityMode: visibilityMode,
expandable: expandable
} = this.option();
return (visibilityMode === SCROLLBAR_VISIBLE.onHover || visibilityMode === SCROLLBAR_VISIBLE.always) && expandable
}
_renderDirection() {
const {
direction: direction
} = this.option();
this.$element().addClass(`dx-scrollbar-${direction}`);
this._dimension = direction === HORIZONTAL ? "width" : "height";
this._prop = direction === HORIZONTAL ? "left" : "top"
}
_attachPointerDownHandler() {
_events_engine.default.on(this._$thumb, (0, _index.addNamespace)(_pointer.default.down, SCROLLBAR), this.feedbackOn.bind(this))
}
feedbackOn(e) {
null === e || void 0 === e || e.preventDefault();
this.$element().addClass("dx-scrollable-scrollbar-active");
activeScrollbar = this
}
feedbackOff() {
this.$element().removeClass("dx-scrollable-scrollbar-active");
activeScrollbar = null
}
cursorEnter() {
this._isHovered = true;
if (this._needScrollbar()) {
this.option("visible", true)
}
}
cursorLeave() {
this._isHovered = false;
this.option("visible", false)
}
_renderDimensions() {
this._$thumb.css({
width: this.option("width"),
height: this.option("height")
})
}
_toggleVisibility(visible) {
const {
visibilityMode: visibilityMode
} = this.option();
if (visibilityMode === SCROLLBAR_VISIBLE.onScroll) {
this._$thumb.css("opacity")
}
visible = this._adjustVisibility(visible);
this.option().visible = visible;
this._$thumb.toggleClass("dx-state-invisible", !visible)
}
_adjustVisibility(visible) {
if (this._baseContainerToContentRatio && !this._needScrollbar()) {
return false
}
const {
visibilityMode: visibilityMode
} = this.option();
switch (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(location) {
if (this._isHidden()) {
return
}
if ((0, _type.isPlainObject)(location)) {
location = location[this._prop] || 0
}
const scrollBarLocation = {};
scrollBarLocation[this._prop] = this._calculateScrollBarPosition(location);
(0, _translator.move)(this._$thumb, scrollBarLocation)
}
_calculateScrollBarPosition(location) {
return -location * this._thumbRatio
}
_update() {
const containerSize = Math.round(this.option("containerSize"));
const contentSize = Math.round(this.option("contentSize"));
let baseContainerSize = Math.round(this.option("baseContainerSize"));
let baseContentSize = Math.round(this.option("baseContentSize"));
if (isNaN(baseContainerSize)) {
baseContainerSize = containerSize;
baseContentSize = contentSize
}
const {
scaleRatio: scaleRatio
} = this.option();
this._baseContainerToContentRatio = baseContentSize ? baseContainerSize / baseContentSize : baseContainerSize;
this._realContainerToContentRatio = contentSize ? containerSize / contentSize : containerSize;
const thumbSize = Math.round(Math.max(Math.round(containerSize * this._realContainerToContentRatio), 15));
this._thumbRatio = (containerSize - thumbSize) / (scaleRatio * (contentSize - containerSize));
this.option(this._dimension, thumbSize / scaleRatio);
this.$element().css("display", this._needScrollbar() ? "" : "none")
}
_isHidden() {
const {
visibilityMode: visibilityMode
} = this.option();
return visibilityMode === SCROLLBAR_VISIBLE.never
}
_needScrollbar() {
return !this._isHidden() && this._baseContainerToContentRatio < 1
}
containerToContentRatio() {
return this._realContainerToContentRatio
}
_normalizeSize(size) {
return (0, _type.isPlainObject)(size) ? size[this._dimension] || 0 : size
}
_clean() {
super._clean();
if (this === activeScrollbar) {
activeScrollbar = null
}
_events_engine.default.off(this._$thumb, `.${SCROLLBAR}`)
}
_optionChanged(args) {
if (this._isHidden()) {
return
}
switch (args.name) {
case "containerSize":
case "contentSize":
this.option()[args.name] = this._normalizeSize(args.value);
this._update();
break;
case "baseContentSize":
case "baseContainerSize":
case "scaleRatio":
this._update();
break;
case "visibilityMode":
case "direction":
this._invalidate();
break;
default:
super._optionChanged.apply(this, arguments)
}
}
update() {
(0, _common.deferRenderer)((() => {
this._adjustVisibility() && this.option("visible", true)
}))()
}
}
_ready_callbacks.default.add((() => {
_events_engine.default.subscribeGlobal(_dom_adapter.default.getDocument(), (0, _index.addNamespace)(_pointer.default.up, SCROLLBAR), (() => {
if (activeScrollbar) {
activeScrollbar.feedbackOff()
}
}))
}));
var _default = exports.default = Scrollbar;