@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
161 lines (141 loc) • 5.94 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2023 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides mixin sap.ui.core.EnabledPropagator
sap.ui.define([
"sap/ui/dom/jquery/Selectors"// jQuery custom selectors ":focusable"
], function() {
"use strict";
/**
* Mixin for enhancement of a control prototype with propagation of the <code>enabled</code> property.
*
* Controls that apply this mixin calculate their effective <code>enabled</code> state on read access
* as the logical OR of their own <code>enabled</code> property and the <code>enabled</code> state
* of the nearest ancestor control which has either an <code>enabled</code> property or a
* <code>getEnabled</code> method.
*
* Applying this mixin adds the <code>enabled</code> property, if it not already exists, to the control
* metadata.
*
* Also adds the <code>useEnabledPropagator(boolean)</code> helper method to the prototype of the given control.
* <code>myControlInstance.useEnabledPropagator(false)</code> can be used to prevent a single instance from using
* <code>EnabledPropagator</code>. In this case, the effective <code>enabled</code> state does not take any
* ancestors <code>enabled</code> state into account, only the control's own <code>enabled</code> property.
*
* @example <caption>Usage Example:</caption>
* sap.ui.define(["sap/ui/core/Control", "sap/ui/core/EnabledPropagator"], function(Control, EnabledPropagator) {
* "use strict";
* var MyControl = Control.extend("my.MyControl", {
* metadata : {
* //...
* }
* //...
* });
*
* EnabledPropagator.apply(MyControl.prototype);
*
* return MyControl;
* });
*
* @param {boolean} [bDefault=true] Value that should be used as default value for the enhancement of the control.
* @param {boolean} [bLegacy=false] Whether the introduced property should use the old name <code>Enabled</code>.
* @version 1.111.5
* @public
* @class
* @alias sap.ui.core.EnabledPropagator
*/
var EnabledPropagator = function(bDefault, bLegacy) {
// Ensure only Controls are enhanced
if (!this.isA || !this.isA("sap.ui.core.Control")) {
throw new Error("EnabledPropagator only supports subclasses of Control");
}
// Marker for the EnabledPropagator
this._bUseEnabledPropagator = true;
// Ensure not to overwrite existing implementations.
var fnOrigGet = this.getEnabled;
if (fnOrigGet === undefined) {
// set some default
this.getEnabled = function() {
return (this._bUseEnabledPropagator && hasDisabledAncestor(this)) ? false : this.getProperty("enabled");
};
// Default for the bDefault
bDefault = (bDefault === undefined) ? true : Boolean(bDefault);
if ( bLegacy ) {
// add Enabled with old spelling for compatibility reasons. Shares the getter and setter with new spelling.
this.getMetadata().addProperty("Enabled", {type : "boolean", group : "Behavior", defaultValue : bDefault});
}
this.getMetadata().addProperty("enabled", {type : "boolean", group : "Behavior", defaultValue : bDefault});
this.getMetadata().addPublicMethods("getEnabled");
} else {
this.getEnabled = function() {
return (this._bUseEnabledPropagator && hasDisabledAncestor(this)) ? false : fnOrigGet.apply(this, arguments);
};
}
if (this.setEnabled === undefined) {
this.setEnabled = function(bEnabled) {
checkAndMoveFocus(this, bEnabled);
return this.setProperty("enabled", bEnabled);
};
this.getMetadata().addPublicMethods("setEnabled");
} else {
var fnOrigSet = this.setEnabled;
this.setEnabled = function(bEnabled) {
checkAndMoveFocus(this, bEnabled);
return fnOrigSet.apply(this, arguments);
};
}
// enhance with the helper method to exclude a single instance from being use of EnabledPropagator
this.useEnabledPropagator = function(bUseEnabledPropagator) {
this._bUseEnabledPropagator = bUseEnabledPropagator;
};
this.getMetadata().addPublicMethods("useEnabledPropagator");
};
/**
* Invalidates the descendants of the provided root element that are implementing the EnabledPropagator mixin
*
* @param {sap.ui.core.Element} oRootElement The root element instance
* @private
* @ui5-restricted sap.ui.core
*/
EnabledPropagator.updateDescendants = function(oRootElement) {
oRootElement.isActive() && oRootElement.findElements(true, function(oElement) {
if (oElement._bUseEnabledPropagator && oElement.bOutput == true) {
oElement.invalidate();
}
});
};
/**
* Determines whether an ancestor of the provided control implements getEnabled method and that returns false
*
* @param {sap.ui.core.Control} oControl A control instance
* @returns {boolean} Whether any control implements getEnabled method and that returns false
* @private
*/
function hasDisabledAncestor(oControl) {
for (var oParent = oControl.getParent(); oParent && !oParent.getEnabled && oParent.getParent; oParent = oParent.getParent()) {/* empty */}
return oParent && oParent.getEnabled && !oParent.getEnabled();
}
/**
* Moves the focus to the nearest ancestor that is focusable when the control that is going to be disabled
* (bEnabled === false) currently has the focus. This is done to prevent the focus from being set to the body
* tag
*
* @param {sap.ui.core.Control} oControl the control that is going to be enabled/disalbed
* @param {boolean} bEnabled whether the control is going to be enabled
* @private
*/
function checkAndMoveFocus(oControl, bEnabled) {
var oDomRef = oControl.getDomRef();
if (!bEnabled && oDomRef && oDomRef.contains(document.activeElement)) {
var oFocusableAncestor = oControl.$().parent().closest(":focusable")[0];
if (oFocusableAncestor) {
oFocusableAncestor.focus({
preventScroll: true
});
}
}
}
return EnabledPropagator;
}, /* bExport= */ true);