// ==UserScript== // @name BOLC / newmips.cloud // @namespace BOLC Newmips Patch // @match https://lacollecte.newmips.cloud/* // @match https://app-emmaus-cloud.newmips.run/* // @homepageURL https://github.com/emmausconnect/BOLC_Userscript // @downloadURL https://raw.githubusercontent.com/emmausconnect/BOLC_Userscript/refs/heads/main/BOLC_Userscript.user.js // @updateURL https://raw.githubusercontent.com/emmausconnect/BOLC_Userscript/refs/heads/main/BOLC_Userscript.user.js // @grant none // @version 1.4.0 // @author Joffrey SCHROEDER / @Write on Github // @inject-into content // ==/UserScript== (function () { 'use strict'; /* ---------------- * CONFIGURATION * ---------------- * */ const CONFIG = { DEBUG: false, ANIMATION_SPEED: 0, MIN_COL_WIDTH: 70, TABLE_DISPLAY_OPTIONS: [1000, 2000, 3000, 5000, 10000], PATHS_WITH_TABLEAU: [ "/materiel_disponible/list", "/materiel_pa/list", "/contact/list", "/don/list", "/donateur/list", "/relais/list", "/reconditionnement/list", //"/personne_morale/list", "/besoin_relais/list", "/ticket_sav/list" //"/log_import/list" ], PATHS_WITH_TABLEAU_PAGINATION_ONLY: [ "/log_import/list" ] }; /* ---------------- * HELPERS * ---------------- * */ const logger = { log: (str) => { if (CONFIG.DEBUG) { const scriptVersion = GM_info.script.version; const style = 'background: #0066ff; color: white; padding: 2px 5px; border-radius: 3px;'; console.log(`📜 %c[BOLCScript]%c (${scriptVersion}) : ${str}`, style, ''); } }, error: (str) => { const scriptVersion = GM_info.script.version; const style = 'background: #ff0000; color: white; padding: 2px 5px; border-radius: 3px;'; console.error(`📜 %c[BOLCScript]%c (${scriptVersion}) ERROR: ${str}`, style, ''); } }; const utils = { isDark: window.matchMedia?.("(prefers-color-scheme: dark)").matches, platform: window.navigator.platform, currentPagepath: window.location.pathname, currentUrl: window.location.href, theme: window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light", match: (str, rule) => { const escapeRegex = (s) => s.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str); }, addScript: (text) => { const newScript = document.createElement('script'); newScript.type = "application/javascript"; newScript.textContent = text; document.head.appendChild(newScript); }, paste: (str) => { const node = document.createElement('style'); node.type = 'text/css'; node.appendChild(document.createTextNode(str.replace(/;/g, ' !important;'))); (document.head || document.documentElement).appendChild(node); }, checkElement: async (selector) => { while (document.querySelector(selector) === null) { await new Promise(resolve => requestAnimationFrame(resolve)); } return document.querySelector(selector); }, removeGarbage: (arr) => { arr.forEach(e => { utils.checkElement(e).then((selector) => { logger.log(`Deleting element -- ${e}`); selector.remove(); }); }); }, clearEventListener: (element) => { const clonedElement = element.cloneNode(true); element.replaceWith(clonedElement); return clonedElement; } }; /* ---------------- * MAIN SCRIPT * ---------------- * */ const init = () => { // Écouter les événements de log depuis le contexte principal document.addEventListener('BOLCScript_log', function (e) { logger.log(e.detail); }); document.addEventListener('BOLCScript_error', function (e) { logger.error(e.detail); }); // Log load context if (window.top === window.self) { logger.log(`(main) Loaded on: ${utils.currentUrl}`); } else { logger.log(`(iframe) Loaded on: ${utils.currentUrl}`); } // Append la version du script à côté de la version du BOLC const scriptVersion = GM_info.script.version; const targetElement = document.querySelector('li[style*="padding: 20px 18px 0 18px !important;"] > div'); if (targetElement) { // Ajouter la version après le texte existant targetElement.innerHTML += ` - BOLCScript v${scriptVersion}`; } // Inject le code directement dans le contexte principale. // Obligatoire car nous utilisons @inject-into content // Pour la compatibilité avec Safari. (function () { const script = document.createElement('script'); script.textContent = ` (function() { const animationSpeed = ${CONFIG.ANIMATION_SPEED}; const interval = setInterval(() => { if (window.jQuery && window.jQuery.AdminLTE) { clearInterval(interval); $.AdminLTE.options.animationSpeed = animationSpeed; $.AdminLTE.boxWidget.animationSpeed = 0; $.AdminLTE.tree('.sidebar'); $('.box').each(function () { $.AdminLTE.boxWidget.activate(this); }); $.AdminLTE.boxWidget.activate(); } }, 50); // Check every 50ms if jQuery is loaded })(); `; document.documentElement.appendChild(script); script.remove(); })(); // Extend table display options utils.checkElement('select[name*=_length').then((selector) => { CONFIG.TABLE_DISPLAY_OPTIONS.forEach(value => { const option = document.createElement('option'); option.value = value; option.textContent = value; selector.appendChild(option); }); }); applyGlobalStyle(); // Apply styles for specific paths if (CONFIG.PATHS_WITH_TABLEAU.some(path => utils.currentPagepath.startsWith(path))) { applyTableauStyles(); setupTableInteractions(); setupTablePaginationMemory(); } else { applyStyleIfNoTable(); } if (CONFIG.PATHS_WITH_TABLEAU_PAGINATION_ONLY.some(path => utils.currentPagepath.startsWith(path))) { applyTableauStyles(); setupDataTableOverflow(); setupTablePaginationMemory(); } initializeColumnSelectorOnUrlChange(); }; const setupTableInteractions = () => { const initialize = () => { disableScrollEvents(); disableFixedHeader(); setupTableResizing(); setupDataTableOverflow(); fixTableColumns(); setupResetButtonHandler(); setupResetColumnsButtonHandler(); duplicateUIBottomBtn(); }; if (document.readyState === "loading") { // Le document n'est pas encore prêt, on attend l'événement DOMContentLoaded document.addEventListener('DOMContentLoaded', initialize); } else { // Le document est déjà prêt, on initialise directement initialize(); } }; const setupTablePaginationMemory = () => { const script = document.createElement('script'); script.textContent = ` (function() { const logger = { log: (message) => { document.dispatchEvent(new CustomEvent('BOLCScript_log', { detail: message })); }, error: (message) => { document.dispatchEvent(new CustomEvent('BOLCScript_error', { detail: message })); } }; logger.log('Script injected into main context'); const waitForDataTable = setInterval(() => { if (typeof jQuery === 'undefined' || typeof jQuery.fn.DataTable === 'undefined') { logger.log('Waiting for jQuery and DataTable...'); return; } const table = jQuery('.dataTable'); if (table.length === 0) { logger.log('Waiting for DataTable to be present in DOM...'); return; } try { const dataTable = table.DataTable(); if (dataTable) { logger.log('DataTable found and initialized'); clearInterval(waitForDataTable); const restorePage = () => { logger.log('Attempting to restore page from URL'); const urlParams = new URLSearchParams(window.location.hash.slice(1)); const pageFromUrl = urlParams.get('page'); if (pageFromUrl !== null) { logger.log('Found page in URL: ' + pageFromUrl); try { const pageNumber = parseInt(pageFromUrl) - 1; // Convert to 0-based index const pageInfo = dataTable.page.info(); logger.log('Current page info: ' + JSON.stringify(pageInfo)); if (pageNumber >= 0 && pageNumber < pageInfo.pages) { logger.log('Setting page to: ' + (pageNumber + 1)); dataTable.page(pageNumber).draw('page'); } else { logger.error('Page number out of bounds: ' + pageNumber + ' (total pages: ' + pageInfo.pages + ')'); } } catch (error) { logger.error('Error restoring page: ' + error.message); } } else { logger.log('No page found in URL'); } }; // Handle page changes dataTable.on('page.dt', function() { const currentPage = dataTable.page() + 1; // Index starts at 1 logger.log('Page changed to: ' + currentPage); const url = new URL(window.location); url.hash = 'page=' + currentPage; window.history.replaceState({}, '', url); logger.log('URL updated: ' + url.toString()); }); // Check if data is loaded by checking if we have valid page info const waitForData = setInterval(() => { const pageInfo = dataTable.page.info(); if (pageInfo && pageInfo.pages > 0) { logger.log('Data loaded, pages available: ' + pageInfo.pages); clearInterval(waitForData); restorePage(); } else { logger.log('Waiting for data to load...'); } }, 100); window.addEventListener('hashchange', function() { logger.log('URL hash changed'); const urlParams = new URLSearchParams(window.location.hash.slice(1)); const pageFromUrl = urlParams.get('page'); if (pageFromUrl !== null) { logger.log('Changing page from hash change: ' + pageFromUrl); try { const pageNumber = parseInt(pageFromUrl) - 1; // Convert to 0-based index dataTable.page(pageNumber).draw('page'); } catch (error) { logger.error('Error changing page from hash: ' + error.message); } } }); logger.log('Page persistence initialization complete'); } } catch (error) { logger.error('Error accessing DataTable: ' + error.message); } }, 100); })(); `; document.head.appendChild(script); }; const fixTableColumns = () => { utils.checkElement('.dataTable').then((dataTable) => { logger.log('Fixing table column widths'); const lastThreeHeaders = dataTable.querySelectorAll('th:nth-last-child(-n+3)'); lastThreeHeaders.forEach(th => { th.style.width = '90px'; }); }); }; const disableScrollEvents = () => { document.addEventListener('scroll', (event) => { event.preventDefault(); event.stopPropagation(); }); }; const disableFixedHeader = () => { const table = document.querySelector('#table_id'); if (table) { table.addEventListener('page.dt', () => { document.querySelectorAll('.fixedHeader-floating').forEach(el => el.remove()); }); table.addEventListener('draw.dt', () => { document.querySelectorAll('.fixedHeader-floating').forEach(el => el.remove()); }); } }; const initializeColumnSelectorOnUrlChange = () => { // 1. Listen for popstate events (back/forward navigation) window.addEventListener('popstate', () => { console.log("URL changed (popstate event)"); setTimeout(initializeColumnSelector(), 500); }); // 2. Listen for hashchange events (fragment/hash changes) window.addEventListener('hashchange', () => { console.log("URL fragment changed (hashchange event)"); setTimeout(initializeColumnSelector(), 500); }); initializeColumnSelector(); }; const initializeColumnSelector = () => { console.log("Initializing column selector..."); // Clear any existing polling to avoid duplicates if (window.columnSelectorPoller) { clearInterval(window.columnSelectorPoller); } // Variables to control polling const maxAttempts = 50; // Maximum 50 attempts const pollingInterval = 50; // Poll every 50ms let attempts = 0; // Start polling for the button window.columnSelectorPoller = setInterval(() => { const targetButton = Array.from(document.querySelectorAll('.dt-button')).find( btn => btn.textContent.trim() === 'Choix Colonnes' ); attempts++; if (targetButton) { console.log("Column selector button found after", attempts, "attempts"); clearInterval(window.columnSelectorPoller); handleColumnSelector(); } else if (attempts >= maxAttempts) { console.log("Column selector button not found after maximum attempts"); clearInterval(window.columnSelectorPoller); } }, pollingInterval); }; const handleColumnSelector = () => { logger.log("init handleColumnSelector"); const handleResetColumns = () => { const tableId = document.querySelector('.dt-button.buttons-print').getAttribute('aria-controls'); const storageKey = 'newmips_shown_columns_save_' + tableId; localStorage.removeItem(storageKey); console.log('Reset filters for table:', storageKey); window.location.reload(); }; const handleClickOutside = (event) => { const columnSelector = document.querySelector('#columnSelector'); if (columnSelector && !columnSelector.contains(event.target)) { // Make sure we're not clicking any of the toggle buttons const targetButtons = Array.from(document.querySelectorAll('.dt-button')).filter( btn => btn.textContent.trim() === 'Choix Colonnes' ); const clickedOnButton = targetButtons.some(btn => btn.contains(event.target)); if (!clickedOnButton) { columnSelector.style.display = 'none'; document.body.setAttribute('data-table-shown', 'false'); // Remove the event listener when we close the selector document.removeEventListener('mousedown', handleClickOutside); } } }; // Add a small delay to ensure DOM is fully loaded and ready setTimeout(() => { // Find all buttons with text "Choix Colonnes" const targetButtons = Array.from(document.querySelectorAll('.dt-button')).filter( btn => btn.textContent.trim() === 'Choix Colonnes' ); if (targetButtons.length > 0) { logger.log(`Found ${targetButtons.length} "Choix Colonnes" buttons`); // Attach the event to each button targetButtons.forEach((button, index) => { logger.log(`Attaching event to button ${index + 1}:`); console.log(button); button.addEventListener('click', () => { let columnSelector = document.querySelector('#columnSelector'); let body = document.querySelector('body'); if (columnSelector) { if (body.getAttribute('data-table-shown') == 'true') { columnSelector.style.display = 'none'; body.setAttribute('data-table-shown', 'false'); // Remove the event listener when we close the selector document.removeEventListener('mousedown', handleClickOutside); } else { body.setAttribute('data-table-shown', 'true'); columnSelector = document.querySelector('#columnSelector'); var columnSelectorTitle = document.querySelector('#columnSelector h4'); columnSelectorTitle.innerText = ""; var columnSelectorApply = document.querySelector('#columnSelector button').parentElement; var columnSelectorReset = document.querySelector('#columnSelector button').parentElement.cloneNode(true); document.querySelector('#columnSelector').prepend(columnSelectorApply); columnSelectorApply.parentElement.prepend(columnSelectorReset); columnSelectorReset.firstChild.innerText = 'Remettre à zéro'; columnSelectorReset.style.marginLeft = '30%'; columnSelectorReset.firstChild.style.marginTop = '10px'; columnSelectorReset.firstChild.classList.add('resetcolumns'); columnSelectorReset.style.display = 'inline'; columnSelectorApply.style.display = 'inline'; columnSelectorApply.style.marginLeft = '10px'; columnSelectorApply.firstChild.style.marginTop = '10px'; columnSelectorReset.addEventListener('click', () => { handleResetColumns(); }); if (columnSelector) { document.body.appendChild(columnSelector); columnSelector.style.position = 'fixed'; columnSelector.style.top = '50%'; columnSelector.style.left = '50%'; columnSelector.style.transform = 'translate(-50%, -50%)'; columnSelector.style.zIndex = '9999'; // Add the click outside listener after the selector is shown document.addEventListener('mousedown', handleClickOutside); } } } }); }); } else { logger.log("(handleColumnSelector) no targetButtons found."); } }, 200); // Initial delay to ensure DOM is ready }; /* TODO */ const setupResetColumnsButtonHandler = () => { const script = document.createElement('script'); script.textContent = ` const handleResetColumns= () => { // Clear the corresponding localStorage entry const storageKey = 'newmips_shown_columns_save_' + tableId; localStorage.removeItem(storageKey); console.log('Reset filters for table:', tableId); }; const resetcolumnsBtn = document.querySelector('.resetcolumns'); resetcolumnsBtn.addEventListener('click', () => { handleResetColumns(); }); `; // Inject the script into the page document.documentElement.appendChild(script); }; const setupResetButtonHandler = () => { const script = document.createElement('script'); script.textContent = ` const clearAllFilters = () => { document.querySelectorAll('thead.filters tr.fields input.filter-input, thead.filters tr.fields select').forEach(element => { if (element.tagName.toLowerCase() === 'select') { element.selectedIndex = 0; } else { element.value = ''; } element.dispatchEvent(new Event('keyup', { bubbles: true })); }); }; const handleReset = (button) => { // Get the table ID from aria-controls const tableId = button.getAttribute('aria-controls'); // Clear the corresponding localStorage entry const storageKey = 'newmips_filter_save_' + tableId; localStorage.removeItem(storageKey); // Clear all filter inputs clearAllFilters(); }; // Setup event delegation for the reset button document.addEventListener('click', (event) => { // Find closest .dt-button ancestor of the clicked element const button = event.target.closest('.dt-button[title^="Réinitialiser"]'); if (button) { // Prevent default behavior and stop propagation event.preventDefault(); event.stopPropagation(); // Handle the reset handleReset(button); } }, true); // Use capture phase to ensure we catch the event first `; // Inject the script into the page document.documentElement.appendChild(script); }; const duplicateUIBottomBtn = () => { const backButton = document.querySelector('a[href="javascript:history.back();"]'); const createButtonElement = document.querySelector('a[href="/donateur/create_form"] button'); const createButtonElement2 = document.querySelector('a[href="/don/create_form_don_pa"] button'); const createButton = createButtonElement ? createButtonElement.parentElement : null; const createButton2 = createButtonElement2 ? createButtonElement2.parentElement : null; const targetElement = document.querySelector('.connectedSortable'); /* Fix si elem déjà présent en double */ const elements_back_double = document.querySelectorAll('.connectedSortable .btn[href^=javascript]'); if (elements_back_double.length >= 2) { const firstElement = elements_back_double[0]; let currentNode = firstElement; // Supprime les deux BR suivants let brCount = 0; while (currentNode.nextElementSibling && brCount < 2) { let nextNode = currentNode.nextElementSibling; if (nextNode.nodeName === 'BR') { nextNode.remove(); brCount++; } currentNode = nextNode; } // Supprime le premier élément firstElement.remove(); } const elements_create_double = document.querySelectorAll('.connectedSortable a[href^=\\/don\\/create_form_don_pa]'); if (elements_create_double.length >= 2) { elements_create_double[0].remove(); } /* Applique la copie des boutons en bas de page, en haut */ if (targetElement) { // Crée un conteneur pour les boutons const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'flex-start'; buttonContainer.style.gap = '10px'; buttonContainer.style.marginBottom = '10px'; // Clone et ajoute le bouton "back" au conteneur if (backButton) { const clone = backButton.cloneNode(true); buttonContainer.appendChild(clone); } // Clone et ajoute le bouton "create" au conteneur if (createButton) { const createClone = createButton.cloneNode(true); buttonContainer.appendChild(createClone); } if (createButton2) { const createClone2 = createButton2.cloneNode(true); buttonContainer.appendChild(createClone2); } // Insère le conteneur avant la cible targetElement.parentNode.insertBefore(buttonContainer, targetElement); } }; const setupTableResizing = () => { document.addEventListener('mousedown', function (e) { logger.log("mousedown listenerd") // Vérifier si on clique sur une poignée de redimensionnement if ( e.target.classList.contains('DTCR_tableHeader') || e.target.classList.contains('DTCR_tableHeaderHover') ) { // Pendant le drag uniquement const mouseMoveHandler = function (e) { const columns = document.querySelectorAll('th'); logger.log("dragging") columns.forEach(col => { if (col.offsetWidth < CONFIG.MIN_COL_WIDTH) { col.style.width = `${CONFIG.MIN_COL_WIDTH}px`; } }); }; // Nettoyer quand on relâche const mouseUpHandler = function () { // Vérifier une dernière fois après un court délai setTimeout(() => { const columns = document.querySelectorAll('th'); columns.forEach(col => { if (col.offsetWidth < CONFIG.MIN_COL_WIDTH) { col.style.width = `${CONFIG.MIN_COL_WIDTH}px`; } }); }, 50); // petit délai pour laisser DataTables finir son traitement document.removeEventListener('mousemove', mouseMoveHandler); document.removeEventListener('mouseup', mouseUpHandler); }; document.addEventListener('mousemove', mouseMoveHandler); document.addEventListener('mouseup', mouseUpHandler); } }); } const setupDataTableOverflow = () => { (function () { const script = document.createElement('script'); script.textContent = ` const logger2 = { log: (message) => { document.dispatchEvent(new CustomEvent('BOLCScript_log', { detail: message })); }, error: (message) => { document.dispatchEvent(new CustomEvent('BOLCScript_error', { detail: message })); } }; const expandHiddenText = () => { const hiddenElements = document.querySelectorAll('.np_text_modal span'); hiddenElements.forEach(innerSpan => { const parentSpan = innerSpan.closest('.np_text_modal'); if (parentSpan) { // On garde le span intérieur intact mais on met son texte comme contenu direct du parent const spanText = innerSpan.textContent.trim(); // On préserve le span intérieur en le retirant temporairement const hiddenSpan = innerSpan.cloneNode(true); parentSpan.textContent = spanText; // Ceci efface tout le contenu parentSpan.appendChild(hiddenSpan); // On remet le span caché } }); }; const createMovablePaginationButton = (paginateContainer) => { if (paginateContainer.querySelector('.move_button')) return; const moveButton = document.createElement('li'); moveButton.classList.add('paginate_button', 'move_button'); moveButton.innerHTML = '🖐'; paginateContainer.querySelector('ul').prepend(moveButton); let isMoving = false; let startX = 0; let startRight = parseInt(window.getComputedStyle(paginateContainer).right, 10) || 0; moveButton.querySelector('a').addEventListener('click', (e) => { e.preventDefault(); }); moveButton.addEventListener('mousedown', (e) => { isMoving = true; startX = e.pageX; startRight = parseInt(window.getComputedStyle(paginateContainer).right, 10) || 0; e.preventDefault(); moveButton.querySelector('a').style.cursor = 'grabbing'; }); document.addEventListener('mousemove', (e) => { if (!isMoving) return; const moveX = e.pageX - startX; const minRight = 0; const maxRight = window.innerWidth - paginateContainer.offsetWidth; const newRight = startRight - moveX; paginateContainer.style.setProperty('right', \`\${Math.min(Math.max(newRight, minRight), maxRight)}px\`, 'important'); }); document.addEventListener('mouseup', () => { isMoving = false; moveButton.querySelector('a').style.cursor = 'grab'; }); moveButton.addEventListener('dragstart', (e) => e.preventDefault()); }; // Handle pagination clicks to scroll to top const setupPaginationScrollToTop = (dtable) => { const scrollToTop = () => { window.scrollTo({ top: 0, behavior: 'instant' }); }; // Also handle length change dropdown if it exists $(document).on('change', '.dataTables_length select', function(e) { if (window.scrollY > 0) { scrollToTop(); } }); }; // Safe DataTable handling with retry logic const initializeDataTableOverflow = () => { const MAX_RETRIES = 10; // Maximum number of retries const RETRY_DELAY = 500; // Delay between retries in milliseconds let retryCount = 0; const tryInitialize = () => { logger2.log('Attempting to initialize DataTableOverflow (Retry)'); const $dataTable = $('.dataTable'); // Ensure we have a table to work with if (!$dataTable.length) { logger2.error('No .dataTable element found'); return; } let dtable; try { // Check if DataTable is initialized if ($.fn.DataTable.isDataTable($dataTable)) { dtable = $dataTable.DataTable(); } else { retryCount++; if (retryCount <= MAX_RETRIES) { logger2.log('DataTable not initialized yet. Retrying in ms...'); setTimeout(tryInitialize, RETRY_DELAY); } else { logger2.error('DataTable initialization failed after maximum retries.'); } return; // Exit this attempt } // Setup pagination scroll to top setupPaginationScrollToTop(dtable); // Apply styles and listeners $dataTable.css('table-layout', 'fixed'); dtable.columns().every(function () { const $header = $(this.header()); if ($header.length) { $header.css({ 'min-width': '${CONFIG.MIN_COL_WIDTH}px', 'overflow': 'hidden', 'text-overflow': 'ellipsis' }); } }); dtable.on('draw', () => { logger2.log('Table draw event'); /****************************** * * Corrige le bug newmips de page suivante / précedente * ne fonctionnant parfois pas. * On clone puis ré-attache un event custom a chaque draw. * **/ var prev = document.querySelector('.paginate_button.previous'); var next = document.querySelector('.paginate_button.next'); // Clone and replace buttons to remove all attached events if (prev) prev.replaceWith(prev.cloneNode(true)); if (next) next.replaceWith(next.cloneNode(true)); // Get new references after replacement prev = document.querySelector('.paginate_button.previous'); next = document.querySelector('.paginate_button.next'); // Handle next button if (next) { next.addEventListener('click', function(e) { e.preventDefault(); var table = $('.dataTable').DataTable(); var info = table.page.info(); // Only move forward if not on last page if (info.page < info.pages - 1) { table.page(info.page + 1).draw(false); } }); } // Handle previous button if (prev) { prev.addEventListener('click', function(e) { e.preventDefault(); var table = $('.dataTable').DataTable(); var info = table.page.info(); if (info.page > 0) { table.page(info.page - 1).draw(false); } }); } /******************************/ setTimeout(() => { expandHiddenText(); const columns = document.querySelectorAll('th'); columns.forEach(col => { if (col.offsetWidth < '${CONFIG.MIN_COL_WIDTH}') { col.style.width = '${CONFIG.MIN_COL_WIDTH}px'; } }); }, 50); const paginateContainer = document.querySelector('.dataTables_paginate'); if (paginateContainer) { createMovablePaginationButton(paginateContainer); } }); dtable.columns.adjust(); logger2.log('DataTableOverflow initialized successfully.'); } catch (error) { logger2.error('Error in DataTable handling:', error); } }; tryInitialize(); }; // Wait for document ready if (document.readyState === 'loading') { logger2.log('Document not ready, attaching DOMContentLoaded listener.'); document.addEventListener('DOMContentLoaded', initializeDataTableOverflow); } else { logger2.log('Document already ready. Calling initializeDataTableOverflow directly.'); initializeDataTableOverflow(); } `; document.documentElement.appendChild(script); })(); }; /* ---------------- * Style CSS * Appliqué uniquement * Là où il n'y a pas de tableaux * !config.PATHS_WITH_TABLEAU * ---------------- * */ const applyStyleIfNoTable = () => { const ifNoTableStyle = ` .nav-tabs-custom > .nav-tabs > li.active > a, .nav-tabs-custom > .nav-tabs > li.active:hover > a { background-color: #00c1b4; color: #fff; border-radius: 6px 6px 0px 0px; } .nav-tabs-custom > .nav-tabs > li { border-top: 0px solid transparent; margin-bottom: 0px; margin-right: 0px; } .box { padding: 0.25rem; } .nav-tabs-custom > .tab-content { padding: 0px; } .content-wrapper { background-color: #f2f7f8 !important; border-left: 0px; padding: 0px 10px; } .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { padding: 0px; padding-left: 5px; } ` utils.paste(ifNoTableStyle); } /* ---------------- * Style CSS * Appliqué uniquement * Là où il ya des tableaux * Voir config.PATHS_WITH_TABLEAU * ---------------- * */ const applyTableauStyles = () => { const tableauStyle = ` .hover:hover { color: unset; background-color: unset; } body .table-responsive { } tr td a:hover { color: #fafafa; } .paging_simple_numbers .pagination .paginate_button:hover a { background: #095f68; } tr td a:hover { color: #fafafa; } .paging_simple_numbers .pagination .paginate_button.active a { background: #09acbe; } .paging_simple_numbers .pagination .paginate_button.disabled:hover a { background: #eee; } .dataTables_wrapper .dataTables_paginate .paginate_button:hover { color: white; border: 1px solid transparent; } .dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active { background: white; } .pagination > .disabled > a, .pagination > .disabled > a:hover { background: white; } .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { color: #c6c6c6; cursor: not-allowed; background-color: #f2f2f2; text-shadow: 0px 1px 0px #fff; } .pagination > li > a, .pagination > li > span { margin-left: unset; } #table_e_materiel_pa_info, .btn.btn-default { margin-left: 20px; } .dataTables_paginate { position: fixed; bottom: 5px; right: 5px; z-index: 9999; background: #aaa5a5b2; padding: 3px; margin: 0px; border-radius: 6px; line-height: 0; } .paginate_button { border-radius: 4px; } .pagination { line-height: 0; } .dataTables_wrapper .dataTables_paginate .paginate_button:first-child { margin-left: 0px; } div.dataTables_paginate ul.pagination { margin: 0; padding: 0; } .table-responsive { margin-bottom: 0px; } .box { margin-bottom: 0px; } table.dataTable { clear: both; margin-top: 0px; margin-bottom: 0px; table-layout: fixed; } section.content-header, section.content, div.content-wrapper { background: white; } .box-body { padding: 0; } .box { padding: 0; } .content-wrapper { padding: 0; } .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { padding: 0; } .fixedHeader-floating { display: none; } td a button { margin-top: 0px; } td span.badge { margin: 0px; padding: 2px 0px; } td span.badge { padding-left: 5px; padding-right: 5px; margin-top: 2px; } `; utils.paste(tableauStyle); } /* ---------------- * Style CSS * Appliqué partout * ---------------- * */ const applyGlobalStyle = () => { const globalStyle = ` .hover:hover { color: unset; background-color: unset; } #columnSelector div { border-bottom: 1px solid #cccccc63; padding-top: 1px; padding-bottom: 1px; } #columnSelector label { padding-left: 10px; padding-right: 10px; } #columnSelector label:hover { font-weight: bold; cursor: pointer; } #columnSelector div:hover .icheck-item { filter: hue-rotate(100deg); } .script-link { color: #fff; text-decoration: underline; } .script-link:hover { color: black; text-decoration: none; } .form-group { margin-bottom: 5px; } #columnSelector { height: unset; width: 35%; height: 100vh; overflow: auto; position: absolute; background: #ffffffed; border: 1px solid grey; border-radius: 0px; padding: 0px; } #columnSelector label { display: inline-block; margin-bottom: 0px; font-weight: normal; } .dt-buttons .dt-button { background: #04b8c4; } .btn-primary, .btn-primary.disabled, .btn-info, .btn-info.disabled { background: #04b8c4; border: 1px solid #009efb; } h3, .h3 { font-size: 20px; } .select2-results__option { padding: 0px 10px; } .badge[style*="background: #fff700"] { background: #b3ae00; } .badge[style*="background: #8cff00"] { background: #79b72d; } .badge[style*="background: #f6f5f4"] { background: #535353; } .badge[style*="background: #4dff00"] { background: #329d04; } .badge[style*="background: #ff0000"] { background: #ea0909; } .badge[style*="background: #babdb6"] { background: #757574; } .badge[style*="background: #a6a6a6"] { background: #757574; } .badge[style*="background: #edd400"] { background: #bfac0b; } .badge[style*="background: #eeff00"] { background: #b5c206; } .badge[style*="background: #ffdd00"], .badge[style*="background: #c4a000"] { background: #ffdd01; color: #ae0000; } .btn { border-color: #7b7b7b75; } .badge { padding: 4px 7px; } .sidebar-menu > li > a { padding: 5px 5px 5px 5px; } .sidebar-mini.sidebar-collapse .sidebar-menu > li > a { padding: 10px 5px 10px 11px; } .sidebar-menu .treeview.active .fa.fa-angle-left.pull-right { position: absolute; top: 50%; right: 10px; margin-top: -8px; } .sidebar-menu .treeview.active .fa.fa-angle-left.pull-right { right: 2px; margin-top: -12px; } .sidebar-menu > li > a > .fa, .sidebar-menu > li > a > .glyphicon, .sidebar-menu > li > a > .ion { width: 18px; } .sidebar-menu li > a > .fa-angle-left { right: -5px; } .sidebar-menu li > a > .fa-angle-left, .sidebar-menu li > a > .pull-right-container > .fa-angle-left { margin-right: 0px; } #tmp_text_modal { background: #cccccc4f; } tbody tr td .btn.btn-default, tbody tr td .btn.btn-success, tbody tr td .btn.btn-error, tbody tr td .btn.btn-primary, tbody tr td .btn.btn-warning, tbody tr td .btn.btn-danger { padding: 0px; padding-left: 6px; padding-right: 6px; } .btn.btn-default, .btn.btn-success, .btn.btn-error, .btn.btn-primary, .btn.btn-warning, .btn.btn-info, .btn.btn-danger { padding: 4px; } .dt-button[title^="Réinitialiser"]:after { content: ' RàZ Recherche'; } .fade { transition: opacity 0s linear; opacity: 1; -webkit-transition: opacity 0s linear; transition: opacity 0s linear; background: transparent; } a[style^="color: rgb(60, 141, 188)"] { color: white; background: #09acbe; } .sidebar-collapse .sidebar-menu li.active > a { background: #0ca4ba; color: white; } th:last-child { padding-right: 300; border-right: 5px solid transparent; } a.dt-button.btnSTL { top: unset; } .fields th { overflow: hidden; } .fields { white-space: nowrap; overflow: hidden; } tr td { overflow: hidden; white-space: nowrap; } .sidebar-menu .treeview-menu > li:hover > a { color: #fff; } .sidebar-menu .treeview-menu > li:hover > a { background: #777777;; } .sidebar-collapse li.treeview span { box-shadow: 3px -2px 3px #ccc; } .sidebar-collapse li ul.treeview-menu { box-shadow: 3px 3px 3px #ccc; } .sidebar-collapse ul.treeview-menu li:hover { background: #ccc; } .sidebar-menu .treeview-menu { padding-left: 0px; } .sidebar-menu .treeview-menu > li > a { padding: 3px 0px 3px 10px; display: block; font-size: 13px; } .btn { padding: 0px 4px; font-size: 13px; } .content-header > h1 { display: none; } .main-header .sidebar-toggle { padding: 4px 10px; } .navbar-nav > li, sidebar-toggle { padding-top: 0px; } .main-header .navbar { min-height: 0; padding: 0px 15px 0 0; height: 32px; margin-left: 170px; } .sidebar-mini.sidebar-collapse .main-header .navbar { margin-left: 44px; } .form-control { height: 25px; padding: 0px 0px 0px 5px; font-size: 13px; min-height: 28px; } tr:hover td a { color: white; } .content-wrapper, .right-side, .main-footer { margin-left: 170px; } .navbar-nav > li, sidebar-toggle { min-height: 0; } .sidebar-toggle { min-height: 0; } .dataTables_length { float: left; padding-left: 15px; } .nav > li:nth-child(1) > div:nth-child(1) { margin-top: -16px; padding: 2px 10px 0px 10px; } .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { padding: 0px; padding-left: 5px; } .main-sidebar, .left-side { padding-top: 0px; } body { font-size: small; } .info-box-icon, .info-box, i { -webkit-transition: all 0s linear; -o-transition: all 0s linear; transition: all 0s linear; } .sidebar-menu > li { -webkit-transition: border-left-color 0s ease; -o-transition: border-left-color 0s ease; transition: border-left-color 0s ease; } .main-header .navbar { -webkit-transition: margin-left 0s ease-in-out; -o-transition: margin-left 0s ease-in-out; transition: margin-left 0s ease-in-out; } .main-sidebar, .left-side { -webkit-transition: -webkit-transform 0s ease-in-out, width 0s ease-in-out; -moz-transition: -moz-transform 0s ease-in-out, width 0s ease-in-out; -o-transition: -o-transform 0s ease-in-out, width 0s ease-in-out; transition: transform 0s ease-in-out, width 0s ease-in-out; } .content-wrapper, .right-side, .main-footer { -webkit-transition: -webkit-transform 0s ease-in-out, margin 0s ease-in-out; -moz-transition: -moz-transform 0s ease-in-out, margin 0s ease-in-out; -o-transition: -o-transform 0s ease-in-out, margin 0s ease-in-out; transition: transform 0s ease-in-out, margin 0s ease-in-out; } .logo { display: none; } aside.main-sidebar, .left-side { background-color: #fff; width: 170px; box-shadow: unset; border-right: 1px solid #ccc; } .content-header > .breadcrumb { padding: 0px 5px; position: absolute; top: 10px; left: 10px; } .content { padding: 5px 0px 0px 0px; } .box-header { padding: 10px 0px 10px 5px; } .animated { -webkit-animation-duration: 0s; animation-duration: 0; scale: both; animation-fill-mode: unset; } .tab-content .btn.btn-success, form .btn, form .btn.btn-primary, .quicklinks .btn, .box-footer .btn { padding: 10px; } @media (min-width: 768px) { .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > a > span { top: 0; margin-left: -3px; padding: 12px 5px 11px 20px; background-color: #0ca4ba; color: white; } .sidebar-mini.sidebar-collapse .sidebar-menu > li > .treeview-menu { padding-top: 0px; padding-bottom: 0px; border-bottom-right-radius: 0px; } .sidebar-mini.sidebar-collapse .sidebar-menu > li > .treeview-menu { padding-bottom: 0px; } .hover:hover, .inline-help:hover, input[type="color"]:hover, .insert:hover, table > tbody > tr:hover { color: white; background-color: #27a6c7; } .table-striped > tbody > tr:hover:nth-child(2n+1) > td { background-color: #1f5d6c; } body.sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-mini.sidebar-collapse .right-side, .sidebar-mini.sidebar-collapse .main-footer { margin-left: 45px; } .sidebar-mini.sidebar-collapse .main-header .navbar { margin-left: 0px; } .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > a > span:not(.pull-right), .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > .treeview-menu { left: 44px; border-left: 1px solid #ccc; cursor: auto; } body.sidebar-mini.sidebar-collapse .main-sidebar { width: 45px; } .navbar-nav > li > a { padding-top: 5px; padding-bottom: 0px; } } `; utils.paste(globalStyle); } init(); })();