1// Função para atualizar os links da paginação com o hash da URL 2function UpdatePaginationWithHash() { 3 // Recupera o fragmento da URL 4 const hash = window.location.hash; 5 6 // Verifica se existe um fragmento antes de continuar 7 if (hash) { 8 // Seleciona todos os links de paginação 9 $(".pagination a").each(function () { 10 const link = $(this); 11 12 // Cria um objeto URL para manipular o href 13 // Usa a URL atual como base para preservar o caminho (pathname) quando o href for relativo (ex: "?pagina=2&") 14 const url = new URL(link.attr("href"), window.location.href); 15 16 // Adiciona o fragmento ao final da URL 17 url.hash = hash; 18 19 // Atualiza o atributo href do link 20 link.attr("href", url.toString()); 21 }); 22 } 23} 24 25function ChangeColorAccordionMonthHeader() { 26 // Evento de clique nos headers do accordion 27 $(".accordion-month").on("click", function () { 28 // Itera sobre todos os headers do accordion filho 29 $(".accordion-month").each(function () { 30 // Verifica se o accordion está expandido (não colapsado) 31 if ($(this).hasClass("collapsed")) { 32 // Remove a classe 'bg-light-primary' caso esteja colapsado 33 $(this).removeClass("bg-light-primary"); 34 } else { 35 // Adiciona a classe 'bg-light-primary' caso esteja expandido 36 $(this).addClass("bg-light-primary"); 37 } 38 }); 39 }); 40} 41 42function initializeDataTable($table, tableName) { 43 // Seleciona o elemento correspondente com base no `tableName` 44 const $tableId = $(`#table-list-${tableName}`); 45 if ($tableId.data("datatable-initialized")) { 46 return; 47 } 48 49 const $tableOrder = $tableId.attr("tableOrder") || "desc"; 50 const $tableOrderColumnRaw = $tableId.attr("tableOrderColumn"); 51 const $tableOrderColumn = Number.isFinite(Number($tableOrderColumnRaw)) 52 ? Number($tableOrderColumnRaw) 53 : 0; 54 const tableOrderingAttr = String( 55 $tableId.attr("data-datatable-ordering") || "true" 56 ).toLowerCase(); 57 const tableOrderingEnabled = !["false", "0", "no"].includes( 58 tableOrderingAttr 59 ); 60 const tablePagingAttr = String( 61 $tableId.attr("data-datatable-paging") || "false" 62 ).toLowerCase(); 63 const tablePagingEnabled = ["true", "1", "yes"].includes( 64 tablePagingAttr 65 ); 66 const tablePageLengthRaw = Number( 67 $tableId.attr("data-datatable-page-length") 68 ); 69 const tablePageLength = 70 Number.isFinite(tablePageLengthRaw) && tablePageLengthRaw > 0 71 ? tablePageLengthRaw 72 : -1; 73 74 // Verifica se a tabela existe no DOM antes de inicializar o DataTable 75 if ($tableId.length) { 76 // Inicializa o DataTable 77 const dataTableOptions = { 78 responsive: false, 79 ordering: tableOrderingEnabled, 80 pageLength: tablePageLength, 81 paging: tablePagingEnabled, 82 lengthChange: false, 83 searching: false, 84 info: tablePagingEnabled, 85 dom: tablePagingEnabled 86 ? "t<'d-flex flex-column flex-md-row justify-content-between align-items-center gap-4 mt-4'ip>" 87 : "<'table-responsive'tr>", 88 language: { 89 sEmptyTable: "Nenhum registro informado", 90 sInfo: "Mostrando de _START_ até _END_ de _TOTAL_ registros", 91 sInfoEmpty: "Mostrando 0 até 0 de 0 registros", 92 sInfoFiltered: "(Filtrados de _MAX_ registros)", 93 sInfoThousands: ".", 94 sLengthMenu: "_MENU_ por página", 95 sLoadingRecords: "Carregando...", 96 sProcessing: "Processando...", 97 sZeroRecords: "Nenhum registro informado", 98 sSearch: "Pesquisar: ", 99 oPaginate: { 100 sNext: ">>", 101 sPrevious: "<<", 102 sFirst: "Primeiro", 103 sLast: "Ãltimo", 104 }, 105 oAria: { 106 sSortAscending: ": Ordenar colunas de forma ascendente", 107 sSortDescending: ": Ordenar colunas de forma descendente", 108 }, 109 }, 110 }; 111 112 if (tableOrderingEnabled) { 113 dataTableOptions.order = [[$tableOrderColumn, $tableOrder]]; 114 dataTableOptions.columnDefs = [ 115 { 116 targets: "_all", 117 orderable: true, 118 orderSequence: ["asc", "desc"], 119 }, 120 ]; 121 } 122 123 new DataTable($tableId, dataTableOptions); 124 $tableId.data("datatable-initialized", true); 125 } else { 126 console.warn(`Tabela com ID #table-list-${tableName} não encontrada.`); 127 } 128} 129 130function loadScriptOnce(key, src) { 131 window.AG_PORTAL_VENDOR_LOADS = window.AG_PORTAL_VENDOR_LOADS || {}; 132 133 if (!window.AG_PORTAL_VENDOR_LOADS[key]) { 134 window.AG_PORTAL_VENDOR_LOADS[key] = new Promise((resolve, reject) => { 135 const existingScript = document.querySelector(`script[data-vendor="${key}"]`); 136 137 if (existingScript) { 138 existingScript.addEventListener("load", resolve, { once: true }); 139 existingScript.addEventListener("error", reject, { once: true }); 140 return; 141 } 142 143 const script = document.createElement("script"); 144 script.src = src; 145 script.async = false;
146 script.dataset.vendor = key; 147 script.onload = resolve; 148 script.onerror = reject; 149 document.body.appendChild(script); 150 }); 151 } 152 153 return window.AG_PORTAL_VENDOR_LOADS[key]; 154} 155 156function loadStyleOnce(key, href) { 157 window.AG_PORTAL_VENDOR_STYLES = window.AG_PORTAL_VENDOR_STYLES || {}; 158 159 if (window.AG_PORTAL_VENDOR_STYLES[key]) { 160 return; 161 } 162 163 const existingStyle = document.querySelector(`link[data-vendor="${key}"], link[href="${href}"]`); 164 if (existingStyle) { 165 window.AG_PORTAL_VENDOR_STYLES[key] = true; 166 return; 167 } 168 169 const link = document.createElement("link"); 170 link.href = href; 171 link.rel = "stylesheet"; 172 link.dataset.vendor = key; 173 document.head.appendChild(link); 174 window.AG_PORTAL_VENDOR_STYLES[key] = true; 175} 176 177function ensureDataTables(callback) { 178 if (typeof DataTable !== "undefined") { 179 callback(); 180 return; 181 } 182 183 const hasSortableTables = $("table[tableName], .table[tableName]").length > 0; 184 if (!hasSortableTables) { 185 return; 186 } 187 188 const dataTablesSrc = 189 (window.AG_PORTAL_ASSETS && window.AG_PORTAL_ASSETS.datatablesJs) || 190 "/assets/plugins/custom/datatables/datatables.bundle.js"; 191 const dataTablesCss = 192 (window.AG_PORTAL_ASSETS && window.AG_PORTAL_ASSETS.datatablesCss) || 193 "/assets/plugins/custom/datatables/datatables.bundle.css"; 194 195 loadStyleOnce("datatables-css", dataTablesCss); 196 loadScriptOnce("datatables", dataTablesSrc) 197 .then(callback) 198 .catch(() => { 199 console.error("Não foi possÃvel carregar o DataTables."); 200 }); 201} 202 203function SortedTable() { 204 const $tables = $("table[tableName], .table[tableName]"); 205 206 // Verifica se há tabelas no DOM 207 if ($tables.length === 0) { 208 return; 209 } 210 211 if (typeof DataTable === "undefined") { 212 ensureDataTables(SortedTable); 213 return; 214 } 215 216 // Itera sobre todas as tabelas e inicializa o DataTable 217 $tables.each(function () { 218 const tableName = $(this).attr("tableName"); 219 if (tableName) { 220 initializeDataTable($(this), tableName); 221 } else { 222 console.warn("Atributo 'tableName' não encontrado na tabela."); 223 } 224 }); 225} 226 227function validateMinLengthInputs(event) { 228 if (!event) { 229 return; 230 } 231 232 const $inputs = $(".minlength"); // Seleciona os inputs com a classe minlength 233 const minLength = 1; // Define o mÃnimo de caracteres permitidos 234 $inputs.forEach((input) => { 235 const value = input.val().trim(); // Remove espaços extras 236 237 if (value.length < minLength) { 238 event.preventDefault(); 239 alert( 240 `O campo deve conter pelo menos ${minLength} caractere${ 241 minLength > 1 ? "s" : "" 242 }.` 243 ); 244 input.focus(); // Mantém o foco no campo 245 } 246 }); 247} 248 249$("#searchForm").on("submit", validateMinLengthInputs); // Validação no submit 250
251function fontAdjustAccessibility(acao) { 252 const tamanhoMaximo = 23; 253 const tamanhoMinimo = 11; 254 let html = document.documentElement; 255 let body = document.body; 256 let tamanhoAtual = parseFloat(window.getComputedStyle(html).fontSize); 257 258 if (acao === "+" && tamanhoAtual <= tamanhoMaximo) { 259 tamanhoAtual += 2; 260 } else if (acao === "-" && tamanhoAtual >= tamanhoMinimo) { 261 tamanhoAtual -= 2; 262 } else if (acao === "default") { 263 tamanhoAtual = 13; 264 } else { 265 return; 266 } 267 268 html.style.setProperty("font-size", `${tamanhoAtual}px`, "important"); 269 body.style.setProperty("font-size", `${tamanhoAtual}px`, "important"); 270 271 localStorage.setItem("tamanhoFonte", tamanhoAtual); 272} 273 274function recoverFontSizeInLocalStorage() { 275 let tamanhoSalvo = localStorage.getItem("tamanhoFonte"); 276 if (tamanhoSalvo) { 277 document.body.style.setProperty( 278 "font-size", 279 `${tamanhoSalvo}px`, 280 "important" 281 ); 282 283 document.documentElement.style.setProperty( 284 "font-size", 285 `${tamanhoSalvo}px`, 286 "important" 287 ); 288 } 289} 290 291function handleThemeToggle() { 292 const $themeToggle = $(".themeToggle"); 293 294 $themeToggle.off("click").on("click", function (e) { 295 e.preventDefault(); 296 console.log("Theme toggle clicked"); 297 298 const currentTheme = 299 document.documentElement.getAttribute("data-bs-theme") || "light"; 300 const newTheme = currentTheme === "dark" ? "light" : "dark"; 301 302 document.documentElement.setAttribute("data-bs-theme", newTheme); 303 localStorage.setItem("data-bs-theme", newTheme); 304 305 // Atualiza classe visual 306 if (newTheme === "dark") { 307 $(this).addClass("active"); 308 } else { 309 $(this).removeClass("active"); 310 } 311 312 // Diagnóstico adicional para mobile 313 console.log("Theme set to:", newTheme); 314 }); 315 316 // Inicializa o botão com base no tema atual 317 const savedTheme = localStorage.getItem("data-bs-theme") || "light"; 318 document.documentElement.setAttribute("data-bs-theme", savedTheme); 319 320 if (savedTheme === "dark") { 321 $themeToggle.addClass("active"); 322 } else { 323 $themeToggle.removeClass("active"); 324 } 325} 326 327function validateForm(form) { 328 const $inputs = $(form).find( 329 "input[required], textarea[required], select[required]" 330 ); 331 let isValid = true; 332 333 $inputs.each(function () { 334 if (!$(this).val()) { 335 isValid = false; 336 $(this).addClass("is-invalid"); 337 } 338 }); 339 340 return isValid; 341} 342 343const submitForm = { 344 init: () => { 345 // Vincula eventos AJAX (se necessário) 346 $(document).ajaxStart(() => { 347 loading.show(); 348 }); 349 350 $(document).ajaxStop(() => { 351 loading.hide(); 352 }); 353 354 // Associa o evento de clique a cada botão com a classe "btn-buscar" 355 $(".btn-buscar").each(function () { 356 $(this).on("click", function (event) { 357 event.preventDefault(); 358 359 // Seleciona o formulário mais próximo do botão clicado 360 const $form = $(this).closest("form"); 361 362 if ($form.length === 0) { 363 console.error( 364 "Nenhum formulário encontrado para este botão." 365 ); 366 return; 367 } 368 369 const isValid = validateForm($form); 370 371 if (isValid) { 372 loading.show(); 373 $form.submit(); // Envia o formulário 374 } else { 375 alert( 376 "Por favor, preencha todos os campos obrigatórios deste formulário." 377 ); 378 loading.hide(); 379 } 380 }); 381 }); 382 }, 383}; 384 385const loading = { 386 init: () => { 387 // Cria o elemento de carregamento e adiciona ao body 388 const loadingEl = document.createElement("div"); 389 loadingEl.classList.add( 390 "page-loader", 391 "flex-column", 392 "bg-dark", 393 "bg-opacity-25", 394 "d-none" 395 ); 396 loadingEl.innerHTML = `
397 <span class="spinner-border text-primary" role="status"></span> 398 <span class="text-gray-800 fs-6 fw-semibold mt-5">Carregando...</span> 399 `; 400 document.body.prepend(loadingEl); 401 }, 402 show: () => { 403 // Mostra o loader 404 $(".page-loader").removeClass("d-none"); 405 // Usando Metronic 406 KTApp.showPageLoading(); 407 }, 408 hide: () => { 409 // Esconde o loader 410 $(".page-loader").addClass("d-none"); 411 // Usando Metronic 412 KTApp.hidePageLoading(); 413 }, 414}; 415 416// script.utils.js 417 418const toastStack = { 419 initContainer: () => { 420 // Cria container de toasts se não existir 421 if (!document.querySelector("#toast-container")) { 422 const container = document.createElement("div"); 423 container.id = "toast-container"; 424 container.className = 425 "toast-container position-fixed bottom-0 end-0 p-3"; 426 container.style.zIndex = "1055"; // acima de modal padrão 427 document.body.appendChild(container); 428 } 429 }, 430 431 show: (statusCode, message) => { 432 toastStack.initContainer(); // garante que container existe 433 434 const toastContainer = document.getElementById("toast-container"); 435 436 const toastWrapper = document.createElement("div"); 437 toastWrapper.className = "toast align-items-center border-0"; 438 toastWrapper.classList.add( 439 statusCode != 200 440 ? ("bg-danger", "text-danger") 441 : ("bg-light-success", "text-success") 442 ); 443 toastWrapper.setAttribute("role", "alert"); 444 toastWrapper.setAttribute("aria-live", "assertive"); 445 toastWrapper.setAttribute("aria-atomic", "true"); 446 447 toastWrapper.innerHTML = ` 448 <div class="toast-header"> 449 <strong class="me-auto ${ 450 statusCode == 200 ? "text-success" : "text-danger" 451 }">${ 452 statusCode == 200 ? `Sucesso ${statusCode}!` : `Erro ${statusCode}!` 453 }</strong> 454 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button> 455 </div> 456 <div class="toast-body"> 457 ${message} 458 </div> 459 </div>`; 460 461 toastContainer.appendChild(toastWrapper); 462 463 const bsToast = new bootstrap.Toast(toastWrapper); 464 bsToast.show(); 465 466 // Remove do DOM após desaparecer 467 toastWrapper.addEventListener("hidden.bs.toast", () => { 468 toastWrapper.remove(); 469 }); 470 }, 471}; 472 473// Exporta se estiver usando módulo ES 474// export default toastStack; 475window.toastStack = toastStack; // torna global caso não esteja usando módulos 476 477$(document).ready(() => { 478 // Atualiza os links da paginação com o hash da URL 479 UpdatePaginationWithHash(); 480 ChangeColorAccordionMonthHeader(); 481 SortedTable(); 482 recoverFontSizeInLocalStorage(); 483 handleThemeToggle(); 484 validateMinLengthInputs(); 485 toastStack.initContainer(); 486 487 var tooltipTriggerList = [].slice.call( 488 document.querySelectorAll('[data-bs-toggle="tooltip"]') 489 ); 490 var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { 491 return new bootstrap.Tooltip(tooltipTriggerEl); 492 }); 493 494 // Impede que o menu feche ao clicar nos links internos 495 $(".menu-redimensionamento").on("click", ".menu-link", function (e) { 496 e.stopPropagation(); 497 }); 498 499 loading.init(); 500 submitForm.init(); 501 502 // Vincula eventos AJAX 503 $(document).ajaxStart(() => { 504 loading.show(); 505 }); 506 507 $(document).ajaxStop(() => { 508 loading.hide(); 509 }); 510});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.