feat: Improve dropdown menu handling and visibility for OTS-specific menus
This commit is contained in:
1
_xibo-cms-clone
Submodule
1
_xibo-cms-clone
Submodule
Submodule _xibo-cms-clone added at 56c98da0b5
@@ -80,14 +80,25 @@ body {
|
|||||||
transform: none !important;
|
transform: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure menus that are intentionally floated into `body` are visible
|
||||||
|
(this targets only menus moved by our JS: `.ots-floating-menu` or
|
||||||
|
`.dropdown-menu` marked with `data-ots-floating="1`). This avoids
|
||||||
|
forcing visibility for all dropdowns. */
|
||||||
|
.ots-floating-menu,
|
||||||
|
.dropdown-menu[data-ots-floating="1"] {
|
||||||
|
display: block !important;
|
||||||
|
visibility: visible !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Elevated z-index for menus so they render above other panels */
|
/* Elevated z-index for menus so they render above other panels */
|
||||||
.ots-floating-menu, .dropdown-menu {
|
.ots-floating-menu, .dropdown-menu {
|
||||||
z-index: 99999 !important;
|
z-index: 99999 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force ALL dropdown/context menu classes to render on top of everything.
|
/* Limit aggressive floating/menu overrides to explicit floating menus only.
|
||||||
This is maximally aggressive to defeat any stacking context or overflow clipping. */
|
Avoid forcing `.dropdown-menu` to be `display:block`/`visibility:visible` so
|
||||||
.dropdown-menu,
|
native dropdown behaviour (open/close) is preserved. */
|
||||||
.ots-notif-menu,
|
.ots-notif-menu,
|
||||||
.ots-user-menu,
|
.ots-user-menu,
|
||||||
.context-menu,
|
.context-menu,
|
||||||
@@ -101,24 +112,29 @@ body {
|
|||||||
transform: none !important;
|
transform: none !important;
|
||||||
will-change: auto !important;
|
will-change: auto !important;
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
visibility: visible !important;
|
|
||||||
display: block !important;
|
|
||||||
opacity: 1 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure dropdown list items and children aren't clipped */
|
/* Hide the rowMenu column header completely */
|
||||||
.dropdown-menu li,
|
th.rowMenu,
|
||||||
.dropdown-menu > li > a,
|
td.rowMenu {
|
||||||
.dropdown-menu > li > span,
|
display: none !important;
|
||||||
.dropdown-menu ul,
|
visibility: hidden !important;
|
||||||
.dropdown-menu div {
|
width: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure floating menu children aren't clipped (scoped to floated menus only) */
|
||||||
|
.ots-floating-menu li,
|
||||||
|
.ots-floating-menu > li > a,
|
||||||
|
.ots-floating-menu > li > span,
|
||||||
|
.ots-floating-menu ul,
|
||||||
|
.ots-floating-menu div {
|
||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
position: relative !important;
|
|
||||||
z-index: 2147483647 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove any transform or overflow from menu ancestors that could create stacking context */
|
/* Remove transforms inside floating menus that could create stacking context */
|
||||||
.dropdown-menu *,
|
|
||||||
.ots-floating-menu * {
|
.ots-floating-menu * {
|
||||||
transform: none !important;
|
transform: none !important;
|
||||||
}
|
}
|
||||||
@@ -1994,6 +2010,12 @@ body.ots-sidebar-open .ots-topbar {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataTables_buttons,
|
||||||
|
.dataTables_buttons * {
|
||||||
|
background: transparent !important;
|
||||||
|
color: var(--color-text-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.dt-button-collection {
|
.dt-button-collection {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
@@ -2081,6 +2103,19 @@ body.ots-sidebar-open .ots-topbar {
|
|||||||
color: var(--color-primary) !important;
|
color: var(--color-primary) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DataTables ColVis button styling */
|
||||||
|
.ColVis_MasterButton,
|
||||||
|
.dt-button {
|
||||||
|
background-color: var(--color-surface-elevated) !important;
|
||||||
|
color: var(--color-text-primary) !important;
|
||||||
|
border: 1px solid var(--color-border) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ColVis_MasterButton:hover,
|
||||||
|
.dt-button:hover {
|
||||||
|
background-color: var(--color-surface) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown.active .dropdown-menu,
|
.dropdown.active .dropdown-menu,
|
||||||
.dropdown:focus-within .dropdown-menu {
|
.dropdown:focus-within .dropdown-menu {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -3147,6 +3182,35 @@ body.ots-sidebar-open .ots-topbar {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure the folder-tree "All Folders" checkbox follows light/dark variables
|
||||||
|
(the checkbox lives in `.ots-folder-tree` / `#grid-folder-filter`). */
|
||||||
|
.ots-folder-tree input[type="checkbox"],
|
||||||
|
.ots-folder-tree .form-check-input,
|
||||||
|
#grid-folder-filter input[type="checkbox"],
|
||||||
|
#grid-folder-filter .form-check-input {
|
||||||
|
-webkit-appearance: none !important;
|
||||||
|
appearance: none !important;
|
||||||
|
width: 18px !important;
|
||||||
|
height: 18px !important;
|
||||||
|
display: inline-block !important;
|
||||||
|
vertical-align: middle !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
background-color: var(--color-surface) !important;
|
||||||
|
background-image: none !important;
|
||||||
|
border: 1px solid var(--color-border) !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ots-folder-tree input[type="checkbox"]:checked,
|
||||||
|
.ots-folder-tree .form-check-input:checked,
|
||||||
|
#grid-folder-filter input[type="checkbox"]:checked,
|
||||||
|
#grid-folder-filter .form-check-input:checked {
|
||||||
|
background-color: var(--color-primary) !important;
|
||||||
|
border-color: var(--color-primary) !important;
|
||||||
|
background-image: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ots-grid-with-folders {
|
.ots-grid-with-folders {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 260px 1fr;
|
grid-template-columns: 260px 1fr;
|
||||||
@@ -3255,6 +3319,12 @@ body.ots-sidebar-open .ots-topbar {
|
|||||||
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make table fill full width */
|
||||||
|
.ots-table-card .table {
|
||||||
|
width: 100% !important;
|
||||||
|
table-layout: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ots-table-card .table thead th,
|
.ots-table-card .table thead th,
|
||||||
.ots-table-card .table tbody td,
|
.ots-table-card .table tbody td,
|
||||||
.ots-table-card .table tbody th,
|
.ots-table-card .table tbody th,
|
||||||
@@ -4262,7 +4332,9 @@ textarea {
|
|||||||
.panel,
|
.panel,
|
||||||
.panel-body,
|
.panel-body,
|
||||||
.table-wrapper,
|
.table-wrapper,
|
||||||
.dataTables_wrapper .dataTables_scrollBody {
|
.dataTables_wrapper .dataTables_scrollBody,
|
||||||
|
.dataTables_wrapper .dataTables_scrollHead,
|
||||||
|
.dataTables_wrapper .dataTables_scrollHead table {
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
@@ -5118,33 +5190,32 @@ body.ots-light-mode .dataTables_wrapper .dataTables_paginate .paginate_button.cu
|
|||||||
color: white !important;
|
color: white !important;
|
||||||
border-color: var(--color-primary) !important;
|
border-color: var(--color-primary) !important;
|
||||||
}
|
}
|
||||||
/* Aggressive unconditional overrides to ensure table text is readable
|
/* Light-mode unconditional overrides to ensure table text is readable */
|
||||||
These apply regardless of light/dark mode */
|
body.ots-light-mode .table td,
|
||||||
.table td,
|
body.ots-light-mode .table th,
|
||||||
.table th,
|
body.ots-light-mode .dataTable td,
|
||||||
.dataTable td,
|
body.ots-light-mode .dataTable th,
|
||||||
.dataTable th,
|
body.ots-light-mode .dataTables_wrapper td,
|
||||||
.dataTables_wrapper td,
|
body.ots-light-mode .dataTables_wrapper th,
|
||||||
.dataTables_wrapper th,
|
body.ots-light-mode .modern-table td,
|
||||||
.modern-table td,
|
body.ots-light-mode .modern-table th {
|
||||||
.modern-table th {
|
|
||||||
color: #0f172a !important;
|
color: #0f172a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dataTables_wrapper .dataTables_info,
|
body.ots-light-mode .dataTables_wrapper .dataTables_info,
|
||||||
.dataTables_wrapper .dataTables_filter,
|
body.ots-light-mode .dataTables_wrapper .dataTables_filter,
|
||||||
.dataTables_wrapper .dataTables_length {
|
body.ots-light-mode .dataTables_wrapper .dataTables_length {
|
||||||
color: #0f172a !important;
|
color: #0f172a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table thead,
|
body.ots-light-mode .table thead,
|
||||||
.dataTable thead,
|
body.ots-light-mode .dataTable thead,
|
||||||
.modern-table thead {
|
body.ots-light-mode .modern-table thead {
|
||||||
background-color: #f1f5f9 !important;
|
background-color: #f1f5f9 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dataTables_wrapper .dataTables_filter input,
|
body.ots-light-mode .dataTables_wrapper .dataTables_filter input,
|
||||||
.dataTables_wrapper .dataTables_length select {
|
body.ots-light-mode .dataTables_wrapper .dataTables_length select {
|
||||||
color: #0f172a !important;
|
color: #0f172a !important;
|
||||||
background-color: #ffffff !important;
|
background-color: #ffffff !important;
|
||||||
border-color: #e2e8f0 !important;
|
border-color: #e2e8f0 !important;
|
||||||
|
|||||||
@@ -306,10 +306,13 @@
|
|||||||
* Initialize dropdown menus
|
* Initialize dropdown menus
|
||||||
*/
|
*/
|
||||||
function initDropdowns() {
|
function initDropdowns() {
|
||||||
const dropdowns = document.querySelectorAll('.dropdown');
|
// Only handle OTS-specific dropdowns (user menu, notifications).
|
||||||
|
// Let Bootstrap handle topbar nav dropdowns (Schedule, Design, etc.) natively
|
||||||
|
// so that links like Dayparting can navigate normally.
|
||||||
|
const otsDropdowns = document.querySelectorAll('.ots-topbar-action .dropdown, .ots-page-actions .dropdown');
|
||||||
|
|
||||||
dropdowns.forEach(dropdown => {
|
otsDropdowns.forEach(dropdown => {
|
||||||
const toggle = dropdown.querySelector('.dropdown-toggle, [data-toggle="dropdown"], .dt-button');
|
const toggle = dropdown.querySelector('.dropdown-toggle, [data-toggle="dropdown"]');
|
||||||
const menu = dropdown.querySelector('.dropdown-menu');
|
const menu = dropdown.querySelector('.dropdown-menu');
|
||||||
|
|
||||||
if (!toggle || !menu) return;
|
if (!toggle || !menu) return;
|
||||||
@@ -318,7 +321,12 @@
|
|||||||
toggle.addEventListener('click', function(e) {
|
toggle.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
dropdown.classList.toggle('active');
|
const isNowActive = dropdown.classList.toggle('active');
|
||||||
|
|
||||||
|
// Close other OTS dropdowns
|
||||||
|
otsDropdowns.forEach(other => {
|
||||||
|
if (other !== dropdown) other.classList.remove('active');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close menu when clicking outside
|
// Close menu when clicking outside
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
<p class="text-muted">{% trans "Manage time-based scheduling rules." %}</p>
|
<p class="text-muted">{% trans "Manage time-based scheduling rules." %}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% embed 'custom/otssignange/views/partials/_dashboard-card.twig' with {'classes':'ots-displays-card'} %}
|
<div class="widget dashboard-card ots-displays-card">
|
||||||
{% block body %}
|
<div class="widget-body ots-displays-body">
|
||||||
<div class="XiboGrid" id="{{ random() }}">
|
<div class="XiboGrid" id="{{ random() }}">
|
||||||
<div class="XiboFilter card mb-3 bg-light dashboard-card ots-filter-card">
|
<div class="XiboFilter card mb-3 bg-light dashboard-card ots-filter-card">
|
||||||
<div class="ots-filter-header">
|
<div class="ots-filter-header">
|
||||||
@@ -46,43 +46,44 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ots-filter-content collapsed" id="ots-filter-content">
|
<div class="ots-filter-content collapsed" id="ots-filter-content">
|
||||||
<div class="FilterDiv card-body" id="Filter">
|
<div class="FilterDiv card-body" id="Filter">
|
||||||
<form class="form-inline">
|
<form class="form-inline">
|
||||||
{% set title %}{% trans "Name" %}{% endset %}
|
{% set title %}{% trans "Name" %}{% endset %}
|
||||||
{{ inline.inputNameGrid('name', title) }}
|
{{ inline.inputNameGrid('name', title) }}
|
||||||
|
|
||||||
{% set title %}{% trans "Retired" %}{% endset %}
|
{% set title %}{% trans "Retired" %}{% endset %}
|
||||||
{% set option1 = "Yes"|trans %}
|
{% set option1 = "Yes"|trans %}
|
||||||
{% set option2 = "No"|trans %}
|
{% set option2 = "No"|trans %}
|
||||||
{% set values = [{id: 1, value: option1}, {id: 0, value: option2}] %}
|
{% set values = [{id: 1, value: option1}, {id: 0, value: option2}] %}
|
||||||
{{ inline.dropdown("isRetired", "single", title, 0, values, "id", "value") }}
|
{{ inline.dropdown("isRetired", "single", title, 0, values, "id", "value") }}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="XiboData card pt-3 dashboard-card ots-table-card">
|
<div class="XiboData card pt-3 dashboard-card ots-table-card">
|
||||||
<div class="ots-table-toolbar">
|
<div class="ots-table-toolbar">
|
||||||
{% if currentUser.featureEnabled("daypart.add") %}
|
{% if currentUser.featureEnabled("daypart.add") %}
|
||||||
<button class="btn btn-sm btn-success XiboFormButton" title="{% trans "Add a new Daypart" %}" href="{{ url_for("daypart.add.form") }}"><i class="fa fa-plus-circle" aria-hidden="true"></i> {% trans "Add Daypart" %}</button>
|
<button class="btn btn-sm btn-success XiboFormButton" title="{% trans "Add a new Daypart" %}" href="{{ url_for("daypart.add.form") }}"><i class="fa fa-plus-circle" aria-hidden="true"></i> {% trans "Add Daypart" %}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="btn btn-sm btn-primary" id="refreshGrid" title="{% trans "Refresh the Table" %}" href="#"><i class="fa fa-refresh" aria-hidden="true"></i></button>
|
<button class="btn btn-sm btn-primary" id="refreshGrid" title="{% trans "Refresh the Table" %}" href="#"><i class="fa fa-refresh" aria-hidden="true"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<table id="dayparts" class="table table-striped" data-state-preference-name="daypartGrid">
|
<table id="dayparts" class="table table-striped" data-state-preference-name="daypartGrid">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans "Name" %}</th>
|
<th>{% trans "Name" %}</th>
|
||||||
<th>{% trans "Description" %}</th>
|
<th>{% trans "Description" %}</th>
|
||||||
<th>{% trans "Start Time" %}</th>
|
<th>{% trans "Start Time" %}</th>
|
||||||
<th>{% trans "End Time" %}</th>
|
<th>{% trans "End Time" %}</th>
|
||||||
<th class="rowMenu"></th>
|
<th class="rowMenu"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
</div>
|
||||||
{% endembed %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -315,79 +315,63 @@
|
|||||||
group.classList.toggle('is-open', !isOpen);
|
group.classList.toggle('is-open', !isOpen);
|
||||||
target.setAttribute('aria-expanded', (!isOpen).toString());
|
target.setAttribute('aria-expanded', (!isOpen).toString());
|
||||||
submenu.style.display = isOpen ? 'none' : 'block';
|
submenu.style.display = isOpen ? 'none' : 'block';
|
||||||
}, true);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize dropdown menus
|
* Initialize dropdown menus
|
||||||
*/
|
*/
|
||||||
function initDropdowns() {
|
function initDropdowns() {
|
||||||
const dropdowns = document.querySelectorAll('.dropdown');
|
// Only handle the user-menu dropdown.
|
||||||
|
// Let Bootstrap handle topbar nav dropdowns (Schedule, Design, etc.) natively
|
||||||
dropdowns.forEach(dropdown => {
|
// so that links like Dayparting navigate normally.
|
||||||
const button = dropdown.querySelector('.dropdown-menu');
|
const userDropdown = document.querySelector('#navbarUserMenu') && document.querySelector('#navbarUserMenu').closest('.dropdown');
|
||||||
|
if (!userDropdown) return;
|
||||||
if (!button) return;
|
|
||||||
|
|
||||||
const menu = dropdown.querySelector('.dropdown-menu');
|
|
||||||
|
|
||||||
// Toggle menu on button click
|
|
||||||
dropdown.addEventListener('click', function(e) {
|
|
||||||
if (e.target.closest('.user-btn') || e.target.closest('[aria-label="User menu"]') || e.target.closest('#navbarUserMenu')) {
|
|
||||||
e.preventDefault();
|
|
||||||
const nowActive = !dropdown.classList.contains('active');
|
|
||||||
dropdown.classList.toggle('active');
|
|
||||||
|
|
||||||
// If the dropdown has a menu, float it out of any overflowed container
|
const userMenu = userDropdown.querySelector('.dropdown-menu');
|
||||||
try {
|
if (!userMenu) return;
|
||||||
const ddMenu = dropdown.querySelector('.dropdown-menu');
|
|
||||||
if (ddMenu) {
|
|
||||||
if (nowActive) {
|
|
||||||
floatMenu(ddMenu, dropdown);
|
|
||||||
} else {
|
|
||||||
unfloatMenu(ddMenu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) { /* ignore */ }
|
|
||||||
|
|
||||||
// If this dropdown contains the user menu, compute placement to avoid going off-screen
|
userDropdown.addEventListener('click', function(e) {
|
||||||
const menu = dropdown.querySelector('.dropdown-menu.ots-user-menu');
|
if (e.target.closest('.user-btn') || e.target.closest('[aria-label="User menu"]') || e.target.closest('#navbarUserMenu')) {
|
||||||
const trigger = dropdown.querySelector('#navbarUserMenu');
|
e.preventDefault();
|
||||||
if (menu && trigger) {
|
const nowActive = !userDropdown.classList.contains('active');
|
||||||
// Reset any previous placement classes
|
userDropdown.classList.toggle('active');
|
||||||
menu.classList.remove('dropdown-menu-left');
|
|
||||||
menu.classList.remove('dropdown-menu-right');
|
|
||||||
|
|
||||||
// Use getBoundingClientRect for accurate placement
|
// Float / unfloat the user menu
|
||||||
const trigRect = trigger.getBoundingClientRect();
|
try {
|
||||||
// Ensure menu is in DOM and has an offsetWidth
|
if (nowActive) {
|
||||||
const menuWidth = menu.offsetWidth || 220; // fallback estimate
|
floatMenu(userMenu, userDropdown);
|
||||||
|
} else {
|
||||||
|
unfloatMenu(userMenu);
|
||||||
|
}
|
||||||
|
} catch (err) { /* ignore */ }
|
||||||
|
|
||||||
const spaceRight = window.innerWidth - trigRect.right;
|
// Compute placement to avoid going off-screen
|
||||||
const spaceLeft = trigRect.left;
|
const trigger = userDropdown.querySelector('#navbarUserMenu');
|
||||||
|
if (trigger) {
|
||||||
// Prefer opening to the right where possible, otherwise open to the left
|
userMenu.classList.remove('dropdown-menu-left', 'dropdown-menu-right');
|
||||||
if (spaceRight < menuWidth && spaceLeft > menuWidth) {
|
const trigRect = trigger.getBoundingClientRect();
|
||||||
// not enough space on the right, open to left
|
const menuWidth = userMenu.offsetWidth || 220;
|
||||||
menu.classList.add('dropdown-menu-left');
|
const spaceRight = window.innerWidth - trigRect.right;
|
||||||
} else {
|
const spaceLeft = trigRect.left;
|
||||||
// default to right-aligned
|
if (spaceRight < menuWidth && spaceLeft > menuWidth) {
|
||||||
menu.classList.add('dropdown-menu-right');
|
userMenu.classList.add('dropdown-menu-left');
|
||||||
}
|
} else {
|
||||||
|
userMenu.classList.add('dropdown-menu-right');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
// Close menu when clicking outside
|
|
||||||
document.addEventListener('click', function(e) {
|
// Close user menu when clicking outside
|
||||||
if (!dropdown.contains(e.target)) {
|
document.addEventListener('click', function(e) {
|
||||||
const hasActive = dropdown.classList.contains('active');
|
if (!userDropdown.contains(e.target) && !userMenu.contains(e.target)) {
|
||||||
dropdown.classList.remove('active');
|
const hadActive = userDropdown.classList.contains('active');
|
||||||
if (hasActive) {
|
userDropdown.classList.remove('active');
|
||||||
try { const ddMenu = dropdown.querySelector('.dropdown-menu'); if (ddMenu) unfloatMenu(ddMenu); } catch (err) {}
|
if (hadActive) {
|
||||||
}
|
try { unfloatMenu(userMenu); } catch (err) {}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user