devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
257 lines (254 loc) • 10.1 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/m_defer_rendering.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 _transition_executor = require("../../common/core/animation/transition_executor/transition_executor");
var _events_engine = _interopRequireDefault(require("../../common/core/events/core/events_engine"));
var _visibility_change = require("../../common/core/events/visibility_change");
var _component_registrator = _interopRequireDefault(require("../../core/component_registrator"));
var _dom_adapter = _interopRequireDefault(require("../../core/dom_adapter"));
var _renderer = _interopRequireDefault(require("../../core/renderer"));
var _common = require("../../core/utils/common");
var _deferred = require("../../core/utils/deferred");
var _iterator = require("../../core/utils/iterator");
var _position = require("../../core/utils/position");
var _type = require("../../core/utils/type");
var _window = require("../../core/utils/window");
var _load_indicator = _interopRequireDefault(require("../../ui/load_indicator"));
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 window = (0, _window.getWindow)();
const WIDGET_CLASS = "dx-widget";
const DEFER_RENDERING_CLASS = "dx-deferrendering";
const PENDING_RENDERING_CLASS = "dx-pending-rendering";
const PENDING_RENDERING_MANUAL_CLASS = "dx-pending-rendering-manual";
const PENDING_RENDERING_ACTIVE_CLASS = "dx-pending-rendering-active";
const VISIBLE_WHILE_PENDING_RENDERING_CLASS = "dx-visible-while-pending-rendering";
const INVISIBLE_WHILE_PENDING_RENDERING_CLASS = "dx-invisible-while-pending-rendering";
const LOADINDICATOR_CONTAINER_CLASS = "dx-loadindicator-container";
const DEFER_RENDERING_LOADINDICATOR_CONTAINER_CLASS = "dx-deferrendering-loadindicator-container";
const DEFER_DEFER_RENDERING_LOAD_INDICATOR = "dx-deferrendering-load-indicator";
const ANONYMOUS_TEMPLATE_NAME = "content";
const ACTIONS = ["onRendered", "onShown"];
class DeferRendering extends _widget.default {
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
showLoadIndicator: false,
onRendered: null,
onShown: null
})
}
_getAnonymousTemplateName() {
return "content"
}
_init() {
this.transitionExecutor = new _transition_executor.TransitionExecutor;
this._initElement();
this._initRender();
this._$initialContent = this.$element().clone().contents();
this._initActions();
super._init()
}
_initElement() {
this.$element().addClass("dx-deferrendering")
}
_initRender() {
const that = this;
const $element = this.$element();
const renderWhen = this.option("renderWhen");
const doRender = () => that._renderDeferredContent();
if ((0, _type.isPromise)(renderWhen)) {
(0, _deferred.fromPromise)(renderWhen).done(doRender)
} else {
$element.data("dx-render-delegate", doRender);
if (void 0 === renderWhen) {
$element.addClass("dx-pending-rendering-manual")
}
}
}
_initActions() {
this._actions = {};
(0, _iterator.each)(ACTIONS, ((_, action) => {
this._actions[action] = this._createActionByOption(action) || _common.noop
}))
}
_initMarkup() {
super._initMarkup();
if (!this._initContent) {
this._initContent = this._renderContent;
this._renderContent = () => {}
}
this._initContent()
}
_renderContentImpl() {
this.$element().removeClass("dx-widget");
this.$element().append(this._$initialContent);
this._setLoadingState()
}
_renderDeferredContent() {
const that = this;
const $element = this.$element();
const result = (0, _deferred.Deferred)();
$element.removeClass("dx-pending-rendering-manual");
$element.addClass("dx-pending-rendering-active");
this._abortRenderTask();
this._renderTask = (0, _common.executeAsync)((() => {
that._renderImpl().done((() => {
const shownArgs = {
element: $element
};
that._actions.onShown([shownArgs]);
result.resolve(shownArgs)
})).fail((function() {
result.rejectWith(result, arguments)
}))
}));
return result.promise()
}
_isElementInViewport(element) {
const rect = (0, _position.getBoundingRect)(element);
return rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || _dom_adapter.default.getDocumentElement().clientHeight) && rect.left <= (window.innerWidth || _dom_adapter.default.getDocumentElement().clientWidth)
}
_animate() {
const that = this;
const $element = this.$element();
const animation = (0, _window.hasWindow)() && this.option("animation");
const staggerItemSelector = this.option("staggerItemSelector");
let animatePromise;
that.transitionExecutor.stop();
if (animation) {
if (staggerItemSelector) {
$element.find(staggerItemSelector).each((function() {
if (that._isElementInViewport(this)) {
that.transitionExecutor.enter((0, _renderer.default)(this), animation)
}
}))
} else {
that.transitionExecutor.enter($element, animation)
}
animatePromise = that.transitionExecutor.start()
} else {
animatePromise = (0, _deferred.Deferred)().resolve().promise()
}
return animatePromise
}
_renderImpl() {
const $element = this.$element();
const renderedArgs = {
element: $element
};
const contentTemplate = this._getTemplate(this._templateManager.anonymousTemplateName);
if (contentTemplate) {
contentTemplate.render({
container: $element.empty(),
noModel: true
})
}
this._setRenderedState();
_events_engine.default.trigger($element, "dxcontentrendered");
this._actions.onRendered([renderedArgs]);
this._isRendered = true;
return this._animate()
}
_setLoadingState() {
const $element = this.$element();
const hasCustomLoadIndicator = !!$element.find(".dx-visible-while-pending-rendering").length;
$element.addClass("dx-pending-rendering");
if (!hasCustomLoadIndicator) {
$element.children().addClass("dx-invisible-while-pending-rendering")
}
if (this.option("showLoadIndicator")) {
this._showLoadIndicator($element)
}
}
_showLoadIndicator($container) {
this._$loadIndicator = new _load_indicator.default((0, _renderer.default)("<div>"), {
visible: true
}).$element().addClass("dx-deferrendering-load-indicator");
(0, _renderer.default)("<div>").addClass("dx-loadindicator-container").addClass("dx-deferrendering-loadindicator-container").append(this._$loadIndicator).appendTo($container)
}
_setRenderedState() {
const $element = this.$element();
if (this._$loadIndicator) {
this._$loadIndicator.remove()
}
$element.removeClass("dx-pending-rendering");
$element.removeClass("dx-pending-rendering-active");
(0, _visibility_change.triggerShownEvent)($element.children())
}
_optionChanged(args) {
const {
value: value
} = args;
const {
previousValue: previousValue
} = args;
switch (args.name) {
case "renderWhen":
if (false === previousValue && true === value) {
this._renderOrAnimate()
} else if (true === previousValue && false === value) {
this.transitionExecutor.stop();
this._setLoadingState()
}
break;
case "showLoadIndicator":
case "onRendered":
case "onShown":
break;
default:
super._optionChanged(args)
}
}
_renderOrAnimate() {
let result;
if (this._isRendered) {
this._setRenderedState();
result = this._animate()
} else {
result = this._renderDeferredContent()
}
return result
}
renderContent() {
return this._renderOrAnimate()
}
_abortRenderTask() {
if (this._renderTask) {
this._renderTask.abort();
this._renderTask = void 0
}
}
_dispose() {
this.transitionExecutor.stop(true);
this._abortRenderTask();
this._actions = void 0;
this._$initialContent = void 0;
super._dispose()
}
}(0, _component_registrator.default)("dxDeferRendering", DeferRendering);
var _default = exports.default = DeferRendering;