|
97 | 97 | padding: 0.4rem 0.75rem !important; |
98 | 98 | } |
99 | 99 |
|
| 100 | + /* Navbar dropdown menu styling */ |
| 101 | + .navbar .dropdown-menu { |
| 102 | + max-height: 400px; |
| 103 | + overflow-y: auto; |
| 104 | + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); |
| 105 | + } |
| 106 | + |
| 107 | + .navbar .dropdown-item { |
| 108 | + padding: 0.4rem 1rem; |
| 109 | + font-size: 0.875rem; |
| 110 | + transition: background-color 0.15s ease-in-out; |
| 111 | + } |
| 112 | + |
| 113 | + .navbar .dropdown-item:hover { |
| 114 | + background-color: rgba(0, 123, 255, 0.1); |
| 115 | + } |
| 116 | + |
| 117 | + .navbar .dropdown-item.functoid-btn { |
| 118 | + cursor: move; |
| 119 | + } |
| 120 | + |
| 121 | + .navbar .dropdown-item.functoid-btn:active { |
| 122 | + cursor: grabbing; |
| 123 | + } |
| 124 | + |
| 125 | + .navbar .dropdown-header { |
| 126 | + font-size: 0.75rem; |
| 127 | + font-weight: 600; |
| 128 | + color: #6c757d; |
| 129 | + padding: 0.5rem 1rem 0.25rem; |
| 130 | + } |
| 131 | + |
| 132 | + .navbar .dropdown-divider { |
| 133 | + margin: 0.25rem 0; |
| 134 | + } |
| 135 | + |
100 | 136 | /* When sidebar is collapsed, adjust header margin */ |
101 | 137 | body.sidebar-collapse .app-header { |
102 | 138 | margin-left: calc(4.6rem + 1px) !important; |
|
489 | 525 | <i class="bi bi-list"></i> |
490 | 526 | </a> |
491 | 527 | </li> |
| 528 | + <li class="nav-item dropdown"> |
| 529 | + <a class="nav-link" data-bs-toggle="dropdown" href="#" role="button"> |
| 530 | + <i class="bi bi-box me-1"></i> Functoids |
| 531 | + </a> |
| 532 | + <div class="dropdown-menu dropdown-menu-lg"> |
| 533 | + <span class="dropdown-item dropdown-header">String Functions</span> |
| 534 | + <div class="dropdown-divider"></div> |
| 535 | + <a href="#" class="dropdown-item functoid-btn" data-type="string" draggable="true"> |
| 536 | + <i class="bi bi-fonts me-2"></i> String |
| 537 | + </a> |
| 538 | + <a href="#" class="dropdown-item functoid-btn" data-type="concat" draggable="true"> |
| 539 | + <i class="bi bi-plus-circle me-2"></i> Concatenate |
| 540 | + </a> |
| 541 | + <a href="#" class="dropdown-item functoid-btn" data-type="substring" draggable="true"> |
| 542 | + <i class="bi bi-scissors me-2"></i> Substring |
| 543 | + </a> |
| 544 | + <div class="dropdown-divider"></div> |
| 545 | + <span class="dropdown-item dropdown-header">Math Functions</span> |
| 546 | + <div class="dropdown-divider"></div> |
| 547 | + <a href="#" class="dropdown-item functoid-btn" data-type="math" draggable="true"> |
| 548 | + <i class="bi bi-calculator me-2"></i> Math |
| 549 | + </a> |
| 550 | + <a href="#" class="dropdown-item functoid-btn" data-type="add" draggable="true"> |
| 551 | + <i class="bi bi-plus-lg me-2"></i> Add |
| 552 | + </a> |
| 553 | + <a href="#" class="dropdown-item functoid-btn" data-type="multiply" draggable="true"> |
| 554 | + <i class="bi bi-x-lg me-2"></i> Multiply |
| 555 | + </a> |
| 556 | + <div class="dropdown-divider"></div> |
| 557 | + <span class="dropdown-item dropdown-header">Logical Functions</span> |
| 558 | + <div class="dropdown-divider"></div> |
| 559 | + <a href="#" class="dropdown-item functoid-btn" data-type="logical" draggable="true"> |
| 560 | + <i class="bi bi-check-square me-2"></i> Logical |
| 561 | + </a> |
| 562 | + <a href="#" class="dropdown-item functoid-btn" data-type="conditional" draggable="true"> |
| 563 | + <i class="bi bi-question-circle me-2"></i> Conditional |
| 564 | + </a> |
| 565 | + <div class="dropdown-divider"></div> |
| 566 | + <span class="dropdown-item dropdown-header">Date Functions</span> |
| 567 | + <div class="dropdown-divider"></div> |
| 568 | + <a href="#" class="dropdown-item functoid-btn" data-type="date" draggable="true"> |
| 569 | + <i class="bi bi-calendar-event me-2"></i> Date |
| 570 | + </a> |
| 571 | + <a href="#" class="dropdown-item functoid-btn" data-type="dateformat" draggable="true"> |
| 572 | + <i class="bi bi-calendar3 me-2"></i> Format Date |
| 573 | + </a> |
| 574 | + </div> |
| 575 | + </li> |
492 | 576 | </ul> |
493 | 577 | <!--end::Start Navbar Links--> |
494 | 578 |
|
|
909 | 993 | new lte.Treeview(treeviewEl); |
910 | 994 | } |
911 | 995 |
|
912 | | - // Listen to AdminLTE's built-in sidebar toggle event |
| 996 | + // Function to redraw connectors |
| 997 | + function redrawConnectors() { |
| 998 | + if (window.mappingToolInstance && window.mappingToolInstance.updateAllMappingLines) { |
| 999 | + window.mappingToolInstance.updateAllMappingLines(); |
| 1000 | + } |
| 1001 | + } |
| 1002 | + |
| 1003 | + // Listen to AdminLTE 4's built-in sidebar toggle events |
913 | 1004 | document.addEventListener('lte.pushmenu.collapsed', () => { |
914 | | - // Redraw mapping lines after sidebar animation |
915 | | - setTimeout(() => { |
916 | | - if (window.mappingToolInstance && window.mappingToolInstance.updateAllMappingLines) { |
917 | | - window.mappingToolInstance.updateAllMappingLines(); |
918 | | - } |
919 | | - }, 300); |
| 1005 | + setTimeout(redrawConnectors, 300); |
920 | 1006 | }); |
921 | 1007 |
|
922 | 1008 | document.addEventListener('lte.pushmenu.expanded', () => { |
923 | | - // Redraw mapping lines after sidebar animation |
924 | | - setTimeout(() => { |
925 | | - if (window.mappingToolInstance && window.mappingToolInstance.updateAllMappingLines) { |
926 | | - window.mappingToolInstance.updateAllMappingLines(); |
| 1009 | + setTimeout(redrawConnectors, 300); |
| 1010 | + }); |
| 1011 | + |
| 1012 | + // Also listen to older AdminLTE 3 events for compatibility |
| 1013 | + document.addEventListener('collapsed.lte.pushmenu', () => { |
| 1014 | + setTimeout(redrawConnectors, 300); |
| 1015 | + }); |
| 1016 | + |
| 1017 | + document.addEventListener('shown.lte.pushmenu', () => { |
| 1018 | + setTimeout(redrawConnectors, 300); |
| 1019 | + }); |
| 1020 | + |
| 1021 | + // Listen to sidebar element transition end for more accurate timing |
| 1022 | + const sidebar = document.querySelector('.app-sidebar'); |
| 1023 | + if (sidebar) { |
| 1024 | + sidebar.addEventListener('transitionend', (e) => { |
| 1025 | + // Only redraw on width/margin transitions (not all transitions) |
| 1026 | + if (e.propertyName === 'margin-left' || e.propertyName === 'width') { |
| 1027 | + redrawConnectors(); |
927 | 1028 | } |
928 | | - }, 300); |
| 1029 | + }); |
| 1030 | + } |
| 1031 | + |
| 1032 | + // Direct listener on the hamburger button as fallback |
| 1033 | + const sidebarToggle = document.querySelector('[data-lte-toggle="sidebar"]'); |
| 1034 | + if (sidebarToggle) { |
| 1035 | + sidebarToggle.addEventListener('click', () => { |
| 1036 | + // Wait for animation to complete |
| 1037 | + setTimeout(redrawConnectors, 350); |
| 1038 | + }); |
| 1039 | + } |
| 1040 | + |
| 1041 | + // Listen to window resize events to redraw connectors |
| 1042 | + let resizeTimeout; |
| 1043 | + window.addEventListener('resize', () => { |
| 1044 | + clearTimeout(resizeTimeout); |
| 1045 | + resizeTimeout = setTimeout(redrawConnectors, 150); |
929 | 1046 | }); |
930 | 1047 | }); |
931 | 1048 | </script> |
|
1015 | 1132 | }); |
1016 | 1133 |
|
1017 | 1134 | // Functoid sidebar links - handle both class and data-functoid for backwards compatibility |
1018 | | - document.querySelectorAll('.functoid-btn, [data-functoid]').forEach(link => { |
1019 | | - link.addEventListener('click', (e) => { |
1020 | | - e.preventDefault(); |
1021 | | - const type = link.getAttribute('data-type') || link.getAttribute('data-functoid'); |
1022 | | - // Access the global MappingTool instance |
1023 | | - if (window.mappingToolInstance && type) { |
1024 | | - window.mappingToolInstance.addFunctoid(type); |
1025 | | - } |
1026 | | - }); |
1027 | | - }); |
| 1135 | + // Use event delegation to avoid multiple handlers on the same element |
| 1136 | + const handleFunctoidClick = (e) => { |
| 1137 | + const target = e.target.closest('.functoid-btn, [data-functoid]'); |
| 1138 | + if (!target) return; |
| 1139 | + |
| 1140 | + e.preventDefault(); |
| 1141 | + e.stopPropagation(); |
| 1142 | + e.stopImmediatePropagation(); // Prevent other handlers from firing |
| 1143 | + |
| 1144 | + const type = target.getAttribute('data-type') || target.getAttribute('data-functoid'); |
| 1145 | + // Access the global MappingTool instance |
| 1146 | + if (window.mappingToolInstance && type) { |
| 1147 | + window.mappingToolInstance.addFunctoid(type); |
| 1148 | + } |
| 1149 | + }; |
| 1150 | + |
| 1151 | + // Add event listener to document for event delegation |
| 1152 | + document.addEventListener('click', handleFunctoidClick, true); // Use capture phase |
1028 | 1153 |
|
1029 | 1154 | // Update mapping count |
1030 | 1155 | function updateMappingCount() { |
|
0 commit comments