Adds inline numbers, fills fields, auto-associates, indicates pressed number, and manages enabled state.
// ==UserScript==
// @name Mapear Esteio - BCI Inline Numbers
// @namespace http://tampermonkey.net/
// @version 1.2 // Enable/disable inline numbers based on edit state
// @description Adds inline numbers, fills fields, auto-associates, indicates pressed number, and manages enabled state.
// @author Seu Nome ou Gemini
// @match http://mapear.esteio.com.br/teresina/selecao/painel/index.php?pagina=boletim*
// @grant GM_addStyle
// @grant GM_log
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
const NUM_EDIF_INPUT_ID = 'associ_numero_da_edificacao';
const RELACAO_BASE_DROPDOWN_ID = 'selecao_tb_pessoa';
const ASSOCIAR_BUTTON_ID = 'btnAssociarPessoa';
const DADOS_PESSOA_FIELDSET_SELECTOR = '#dados_pessoa fieldset.border.p-4';
const INLINE_NUMBERS_ROW_CLASS = 'gm-inline-numbers-row';
const INLINE_NUM_BUTTON_CLASS = 'gm-inline-num-button';
const PRESSED_BUTTON_CLASS = 'gm-inline-num-button-pressed';
const SALVAR_CADASTRO_BUTTON_ID = 'btnSalvarCadastro';
const EDITAR_BOLETIM_SELECTOR = 'a[onclick^="editarBoletim("][title="Editar Boletim"]'; // Seletor do botão "Editar" na lista
const EDIFICACOES_LIST_CONTAINER_ID = 'listar_edif'; // Container da lista de edificações
GM_addStyle(`
.${INLINE_NUMBERS_ROW_CLASS} {
margin-top: 10px;
margin-bottom: 15px;
padding-top: 5px;
border-top: 1px solid #e0e0e0;
text-align: center;
}
.${INLINE_NUM_BUTTON_CLASS} {
padding: 6px 12px;
margin: 2px 3px;
border: 1px solid #007bff;
background-color: #f8f9fa;
color: #007bff;
cursor: pointer;
min-width: 35px;
text-align: center;
border-radius: 0.25rem;
font-size: 0.9em;
font-weight: bold;
transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, opacity 0.15s ease-in-out;
display: inline-block;
}
.${INLINE_NUM_BUTTON_CLASS}:hover:not(:disabled) { /* Hover effect only when not disabled */
background-color: #007bff;
color: white;
}
.${INLINE_NUM_BUTTON_CLASS}.${PRESSED_BUTTON_CLASS} {
background-color: #0056b3;
color: white;
border-color: #004085;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
}
.${INLINE_NUM_BUTTON_CLASS}:disabled {
background-color: #e9ecef;
color: #6c757d;
border-color: #ced4da;
cursor: not-allowed;
opacity: 0.65; /* Visual indication of disabled */
box-shadow: none;
}
`);
function setInlineNumberButtonsEnabled(enable) {
const allNumButtons = document.querySelectorAll(`.${INLINE_NUM_BUTTON_CLASS}`);
allNumButtons.forEach(btn => {
btn.disabled = !enable;
});
GM_log(`Botões numéricos inline ${enable ? 'HABILITADOS' : 'DESABILITADOS'}.`);
}
function clearNumberButtonSelection() {
const allNumButtons = document.querySelectorAll(`.${INLINE_NUM_BUTTON_CLASS}`);
allNumButtons.forEach(btn => {
btn.classList.remove(PRESSED_BUTTON_CLASS);
});
GM_log("Seleção de botão numérico (estado 'pressionado') foi limpa.");
}
function handleNumberButtonClick(selectedNumber, clickedButtonElement) {
if (clickedButtonElement.disabled) return; // Não faz nada se o botão estiver desabilitado
GM_log(`Botão numérico inline '${selectedNumber}' clicado.`);
clearNumberButtonSelection();
clickedButtonElement.classList.add(PRESSED_BUTTON_CLASS);
GM_log(`Botão '${selectedNumber}' marcado como pressionado.`);
const numEdifInput = document.getElementById(NUM_EDIF_INPUT_ID);
if (numEdifInput) {
numEdifInput.value = selectedNumber;
numEdifInput.dispatchEvent(new Event('input', { bubbles: true }));
numEdifInput.dispatchEvent(new Event('change', { bubbles: true }));
} else {
GM_log(`ERRO: Campo '${NUM_EDIF_INPUT_ID}' não encontrado.`);
return;
}
const relacaoBaseDropdown = document.getElementById(RELACAO_BASE_DROPDOWN_ID);
if (relacaoBaseDropdown) {
if (relacaoBaseDropdown.options.length > 1 && relacaoBaseDropdown.options[0].value === "" && relacaoBaseDropdown.options[1]) {
relacaoBaseDropdown.selectedIndex = 1;
relacaoBaseDropdown.dispatchEvent(new Event('change', { bubbles: true }));
} else if (relacaoBaseDropdown.options.length > 0 && relacaoBaseDropdown.options[0].value !== "") {
relacaoBaseDropdown.selectedIndex = 0;
relacaoBaseDropdown.dispatchEvent(new Event('change', { bubbles: true }));
}
}
const associarButton = document.getElementById(ASSOCIAR_BUTTON_ID);
if (associarButton) {
associarButton.disabled = false;
setTimeout(() => {
associarButton.click();
}, 150);
}
}
let inlineButtonsCreated = false;
function initInlineNumberButtons() {
if (inlineButtonsCreated) return true;
const dadosPessoaFieldset = document.querySelector(DADOS_PESSOA_FIELDSET_SELECTOR);
if (!dadosPessoaFieldset) return false;
if (dadosPessoaFieldset.querySelector(`.${INLINE_NUMBERS_ROW_CLASS}`)) {
inlineButtonsCreated = true;
setInlineNumberButtonsEnabled(false); // Garante que estejam desabilitados ao recarregar a página se já existirem
return true;
}
const numbersRow = document.createElement('div');
numbersRow.className = `${INLINE_NUMBERS_ROW_CLASS} form-row`;
for (let i = 1; i <= 9; i++) {
const button = document.createElement('button');
button.textContent = i;
button.type = 'button';
button.className = INLINE_NUM_BUTTON_CLASS;
button.disabled = true; // Começam desabilitados
button.addEventListener('click', function() {
handleNumberButtonClick(this.textContent, this);
});
numbersRow.appendChild(button);
}
dadosPessoaFieldset.appendChild(numbersRow);
GM_log('Botões numéricos inline CRIADOS (desabilitados) na seção "Dados Pessoa".');
inlineButtonsCreated = true;
return true;
}
let saveButtonListenerAttached = false;
function attachListenerToSaveButton() {
if (saveButtonListenerAttached) return true;
const salvarCadastroButton = document.getElementById(SALVAR_CADASTRO_BUTTON_ID);
if (salvarCadastroButton) {
salvarCadastroButton.addEventListener('click', function() {
GM_log(`Botão '${SALVAR_CADASTRO_BUTTON_ID}' clicado. Limpando e desabilitando botões numéricos.`);
clearNumberButtonSelection();
setInlineNumberButtonsEnabled(false); // Desabilita os botões
});
saveButtonListenerAttached = true;
GM_log(`Listener adicionado ao botão '${SALVAR_CADASTRO_BUTTON_ID}'.`);
return true;
}
return false;
}
let editarBoletimListenerAttached = false;
function attachListenerToEditarBoletim() {
if (editarBoletimListenerAttached) return true;
const container = document.getElementById(EDIFICACOES_LIST_CONTAINER_ID);
if (container) {
container.addEventListener('click', function(event) {
let currentElement = event.target;
while (currentElement && currentElement !== this && currentElement !== document.body) {
if (currentElement.matches(EDITAR_BOLETIM_SELECTOR)) {
GM_log('Tampermonkey: Botão "Editar Boletim" clicado. Habilitando botões numéricos inline.');
setInlineNumberButtonsEnabled(true); // Habilita os botões
clearNumberButtonSelection(); // Limpa seleção anterior
return;
}
currentElement = currentElement.parentElement;
}
});
editarBoletimListenerAttached = true;
GM_log(`Listener para "${EDITAR_BOLETIM_SELECTOR}" adicionado ao container '${EDIFICACOES_LIST_CONTAINER_ID}'.`);
return true;
}
return false;
}
// Função principal de configuração
function setupAllFunctionality() {
let allSetup = true;
if (!inlineButtonsCreated) {
inlineButtonsCreated = initInlineNumberButtons();
}
if (!saveButtonListenerAttached) {
saveButtonListenerAttached = attachListenerToSaveButton();
}
if (!editarBoletimListenerAttached) {
editarBoletimListenerAttached = attachListenerToEditarBoletim();
}
// Se tudo foi configurado, podemos parar de observar
if (inlineButtonsCreated && saveButtonListenerAttached && editarBoletimListenerAttached) {
if (observer) {
observer.disconnect();
GM_log('Tampermonkey: Observer desconectado após todas as funcionalidades (v1.2) serem configuradas.');
}
timeoutIds.forEach(clearTimeout);
timeoutIds = [];
}
}
let observer = null;
let timeoutIds = [];
if (document.readyState === 'interactive' || document.readyState === 'complete') {
setupAllFunctionality();
} else {
document.addEventListener('DOMContentLoaded', () => {
GM_log('Evento DOMContentLoaded (v1.2).');
setupAllFunctionality();
});
}
window.addEventListener('load', () => {
GM_log('Evento window.load (v1.2).');
setupAllFunctionality();
});
observer = new MutationObserver((mutationsList, obs) => {
setupAllFunctionality();
});
function startObserverWhenReady() {
if (document.body) {
observer.observe(document.body, { childList: true, subtree: true });
GM_log('MutationObserver (v1.2) iniciado no document.body.');
} else {
setTimeout(startObserverWhenReady, 50);
}
}
startObserverWhenReady();
[500, 1500, 3000, 5000].forEach(delay => {
timeoutIds.push(setTimeout(setupAllFunctionality, delay));
});
})();