Skip to content

Instantly share code, notes, and snippets.

@redraw
Last active August 23, 2025 15:36
Show Gist options
  • Save redraw/760037f18eb047d1ac611f9793a6f812 to your computer and use it in GitHub Desktop.
Save redraw/760037f18eb047d1ac611f9793a6f812 to your computer and use it in GitHub Desktop.
(() => {
const ID = "datos-generales-sunburst-id";
const VALUE_INDEXES = [1, 3, 5]; // hijos con los importes: inicial, vigente, ejecutado
const LOCALE = "es-AR";
const parseEU = (s) => {
// Extrae primer número con formato "94.573.214,04"
const m = (s || "").match(/[\d.,]+/);
if (!m) return NaN;
const num = m[0].replace(/\./g, "").replace(",", ".");
return Number(num);
};
const fmtPct = (n) =>
isFinite(n)
? n.toLocaleString(LOCALE, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + "%"
: "—";
const getContainer = () => document.getElementById(ID);
if (!getContainer()) return;
// 1) Leer totales al primer load (índices 1,3,5)
const container = getContainer();
const kids = container.children;
const totals = VALUE_INDEXES.map((i) => parseEU(kids[i]?.innerText));
// Guardar en dataset por si otro script necesita leerlos
container.dataset.totalInicial = String(totals[0] ?? "");
container.dataset.totalVigente = String(totals[1] ?? "");
container.dataset.totalEjecutado = String(totals[2] ?? "");
// Utilidad: actualizar un nodo con su % respecto del total
const ensurePercentSpan = (node, total) => {
if (!node) return;
// Eliminar spans previos
node.querySelectorAll(".pct-of-total").forEach((el) => el.remove());
const current = parseEU(node.textContent);
if (!isFinite(current) || !isFinite(total) || total === 0) return;
const pct = (current / total) * 100;
const span = document.createElement("span");
span.className = "pct-of-total";
span.style.marginLeft = "0.35em";
span.style.fontWeight = "600";
span.style.whiteSpace = "nowrap";
span.textContent = `(${fmtPct(pct)})`;
node.appendChild(span);
};
let busy = false;
const updatePercents = () => {
if (busy) return;
busy = true;
try {
// Re-resolver hijos por si el DOM fue reemplazado
const c = getContainer();
if (!c) return;
const ch = c.children;
ensurePercentSpan(ch[VALUE_INDEXES[0]], totals[0]); // Presupuesto Inicial
ensurePercentSpan(ch[VALUE_INDEXES[1]], totals[1]); // Presupuesto Vigente
ensurePercentSpan(ch[VALUE_INDEXES[2]], totals[2]); // Ejecutado
} finally {
// Micro-debounce para evitar bucles del observer
setTimeout(() => (busy = false), 0);
}
};
// Render inicial
updatePercents();
// 2) Observar cambios en #datos-generales-sunburst-id
const observer = new MutationObserver(() => updatePercents());
observer.observe(container, {
childList: true,
characterData: true,
subtree: true,
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment