N°6132 - Introduce API to disable tabs dynamically (#470)

* N°6132 - disable tabs dynamically

* Apply suggestions from code review

JS cleanup after review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Disable tabs by ID instead of index
Disabled tabs are visible (with a 'not-allowed' cursor)  instead of being hidden from the extra tabs menu.

* Typo!

* Update code to match conventions

* N°6132 - Fix show/hide of disabled tabs as it collided with internal methods

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
This commit is contained in:
Denis
2023-04-06 12:12:42 +02:00
committed by GitHub
parent 2907efde4b
commit d28b099401
4 changed files with 90 additions and 13 deletions

View File

@@ -38,6 +38,10 @@ $ibo-is-code--padding: 1.25rem 1.5rem !default;
cursor: help;
}
.ibo-is-disabled {
cursor: not-allowed !important; /* Note: !important is necessary as it needs to overload any standard rules */
}
/* Class to display a hint on elements that have a tooltip for further description */
.ibo-has-description {
&::after {

View File

@@ -124,5 +124,16 @@ $.widget( "itop.regulartabs", $.ui.tabs, {
this._off( prevPanels.not( this.panels ) );
}
},
});
// JQuery UI overload
disable: function(index){
const panel = this._getPanelForTab( index );
panel.addClass('ibo-is-hidden'); // Do not use .hide() since it alters the tab state
this._super( index );
},
// JQuery UI overload
enable: function(index) {
const panel = this._getPanelForTab( index );
panel.removeClass('ibo-is-hidden'); // Do not use .show() since it alters the tab state
this._super( index );
},
});

View File

@@ -377,4 +377,16 @@ $.widget( "itop.scrollabletabs", $.ui.tabs, {
setTab : function(tab){
this.active = tab;
},
});
// JQuery UI overload
disable: function(index){
const panel = this._getPanelForTab( this.tabs[index] );
panel.addClass('ibo-is-hidden'); // Do not use .hide() since it alters the tab state
this._super( index );
},
// JQuery UI overload
enable: function(index) {
const panel = this._getPanelForTab( this.tabs[index] );
panel.removeClass('ibo-is-hidden'); // Do not use .show() since it alters the tab state
this._super( index );
},
});

View File

@@ -15,6 +15,7 @@ $(function()
css_classes:
{
is_hidden: 'ibo-is-hidden',
is_disabled: 'ibo-is-disabled',
is_transparent: 'ibo-is-transparent',
is_opaque: 'ibo-is-opaque',
is_scrollable: 'ibo-is-scrollable',
@@ -252,6 +253,11 @@ $(function()
// Prevent anchor default behaviour
oEvent.preventDefault();
if (oExtraTabTogglerElem.attr('aria-disabled') === 'true') {
// Corresponding tab is disabled, do nothing
oEvent.stopPropagation();
return;
}
// Trigger click event on real tab toggler (the hidden one)
const sTargetTabId = oExtraTabTogglerElem.attr('href').replace(/#/, '');
this.element.find(this.js_selectors.tab_header+'[data-tab-id="'+sTargetTabId+'"] '+this.js_selectors.tab_toggler).trigger('click');
@@ -297,17 +303,30 @@ $(function()
const sTabId = oTabHeaderElem.attr('data-tab-id');
const oMatchingExtraTabElem = this.element.find(this.js_selectors.extra_tab_toggler+'[href="#'+sTabId+'"]');
// Disabled tabs should be disabled in the ExtraTabs list as well
let bIsDisabled = false;
if (oTabHeaderElem.attr('aria-disabled') === 'true') {
bIsDisabled = true;
}
// Manually check if the tab header is visible if the info isn't passed
if (bIsVisible === null) {
bIsVisible = CombodoGlobalToolbox.IsElementVisibleToTheUser(oTabHeaderElem[0], true, 2);
}
bIsVisible = CombodoGlobalToolbox.IsElementVisibleToTheUser(oTabHeaderElem[0], true, 2);
}
// Hide/show the corresponding extra tab element
if (bIsVisible) {
oMatchingExtraTabElem.addClass(this.css_classes.is_hidden);
} else {
oMatchingExtraTabElem.removeClass(this.css_classes.is_hidden);
}
if (bIsVisible) {
oMatchingExtraTabElem.addClass(this.css_classes.is_hidden);
} else {
oMatchingExtraTabElem.removeClass(this.css_classes.is_hidden);
}
// Enable/disable the corresponding extra tab element
if (bIsDisabled) {
oMatchingExtraTabElem.attr('aria-disabled', 'true');
oMatchingExtraTabElem.addClass(this.css_classes.is_disabled);
} else {
oMatchingExtraTabElem.attr('aria-disabled', 'false');
oMatchingExtraTabElem.removeClass(this.css_classes.is_disabled);
}
},
// - Update extra tabs list
_updateExtraTabsList: function () {
@@ -326,7 +345,7 @@ $(function()
* @return {string} The [data-tab-id] of the iIdx-th tab (zero based). Can return undefined if it has not [data-tab-id] attribute
* @private
*/
_getTabIdFromTabIndex(iIdx) {
_getTabIdFromTabIndex: function(iIdx) {
return this.element.children(this.js_selectors.tabs_list).children(this.js_selectors.tab_header).eq(iIdx).attr('data-tab-id');
},
/**
@@ -334,10 +353,41 @@ $(function()
* @return {number} The index (zero based) of the tab. If no matching tab, 0 will be returned.
* @private
*/
_getTabIndexFromTabId(sId) {
_getTabIndexFromTabId: function(sId) {
const oTabElem = this.element.children(this.js_selectors.tabs_list).children(this.js_selectors.tab_header+'[data-tab-id="'+sId+'"]');
return oTabElem.length === 0 ? 0 : oTabElem.prevAll().length;
}
},
/**
* @param sId {string} The [data-tab-id] of the tab
* @return {Object} The jQuery object representing the tab element
*
* @private
*/
_getTabElementFromTabId: function(sId) {
return this.element.children(this.js_selectors.tabs_list).children(this.js_selectors.tab_header+'[data-tab-id="'+sId+'"]');
},
/**
* @param sId {string} The [data-tab-id] of the tab
* @return {Object} The jQuery object representing the tab element
*/
disableTab: function(sId){
const tabsWidget = this.GetTabsWidget();
const iIdx = this._getTabIndexFromTabId(sId);
tabsWidget.disable(iIdx);
const tabElement = this._getTabElementFromTabId(sId);
this._updateTabHeaderDisplay(tabElement);
},
/**
* @param sId {string} The [data-tab-id] of the tab
* @return {Object} The jQuery object representing the tab element
*/
enableTab: function(sId){
const tabsWidget = this.GetTabsWidget();
const iIdx = this._getTabIndexFromTabId(sId);
tabsWidget.enable(iIdx);
const tabElement = this._getTabElementFromTabId(sId);
this._updateTabHeaderDisplay(tabElement);
}
});
});