{{-- Main Orchestrator — abre o modal, gerencia eventos e filtros --}} /** * Abre o modal do gallery picker com instância nova a cada chamada, * eliminando qualquer instância anterior e backdrops órfãos. */ const openGalleryModal = function(pickerId) { var modalEl = document.getElementById('gallery-picker-modal-' + pickerId); if (!modalEl) return null; // Instância anterior: se o modal já está aberto, mantém a instância atual — // recriar nesse caso dispara um "blink" (esconde e reabre na mesma chamada). var oldInst = bootstrap.Modal.getInstance(modalEl); if (oldInst) { if (modalEl.classList.contains('show')) { return oldInst; } // Instância residual (modal já fechado): só dispose(), NUNCA hide()+ // dispose() em sequência — o hide() agenda _hideModal assíncronamente // (_queueCallback/setTimeout) e o dispose() já anulou this._element // quando o callback roda, gerando "TypeError: can't access property // 'style', this._element is null". oldInst.dispose(); // Limpa o estado visual residual que o dispose() não remove (se o // modal estivesse em transição) antes de reabrir com instância nova. modalEl.classList.remove('show'); modalEl.style.display = ''; modalEl.removeAttribute('aria-modal'); modalEl.setAttribute('aria-hidden', 'true'); } // Remove backdrops órfãos — só quando nenhum outro modal estiver aberto if (document.querySelectorAll('.modal.show').length === 0) { document.querySelectorAll('.modal-backdrop').forEach(function (el) { el.remove(); }); document.body.classList.remove('modal-open'); document.body.style.removeProperty('padding-right'); document.body.style.removeProperty('overflow'); } // Cria instância nova e exibe var modal = new bootstrap.Modal(modalEl, { backdrop: false, keyboard: false }); modal.show(); // Garante limpeza ao fechar $(modalEl).off('hidden.bs.modal.gallery').on('hidden.bs.modal.gallery', function () { if (document.querySelectorAll('.modal.show').length === 0) { document.querySelectorAll('.modal-backdrop').forEach(function (el) { el.remove(); }); document.body.classList.remove('modal-open'); document.body.style.removeProperty('padding-right'); document.body.style.removeProperty('overflow'); } }); return modal; }; window.addEventListener('lotep:open-gallery-picker-' + pickerId, function(e) { if (e.detail && typeof e.detail.callback === 'function') { activeCallback = e.detail.callback; // Dynamic overrides from event detail (when called from media-input) if (e.detail.ownerModule) { ownerModule = e.detail.ownerModule; } if (e.detail.allowedMimeTypes) { filterMimeTypes = e.detail.allowedMimeTypes; } destroyCropper(); $('#gallery-detail-segment-' + pickerId).hide(); loadGallery(); openGalleryModal(pickerId); if (e.detail.droppedFile) { handleDirectDroppedFile(e.detail.droppedFile); } } }); /* Alternar visualização entre galeria ativa e arquivados */ $('#btn-toggle-archived-' + pickerId).on('click', function() { var active = $(this).attr('data-view-archived') == '1'; if (active) { $(this).attr('data-view-archived', '0').html(' Ver Arquivados').removeClass('btn-warning').addClass('btn-outline-secondary'); $('#gallery-list-title-' + pickerId).html(' 4. Galeria de Arquivos Existentes'); viewArchived = 0; } else { $(this).attr('data-view-archived', '1').html(' Ver Galeria Ativa').removeClass('btn-outline-secondary').addClass('btn-warning'); $('#gallery-list-title-' + pickerId).html(' 4. Galeria de Arquivos Arquivados'); viewArchived = 1; } $('#gallery-detail-segment-' + pickerId).hide(); loadGallery(); }); $('#gallery-search-' + pickerId).on('keyup', function() { loadGallery(); }); $('#gallery-filter-type-' + pickerId).on('change', function() { loadGallery(); });