Rafael Lopez

arreglo descargas2

1 -<!DOCTYPE html>
2 -<html lang="es">
3 -<head>
4 - <meta charset="utf-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1">
6 - <title>Descargas presupuestarias</title>
7 - <style>
8 - :root {
9 - --text: #1f1f1f;
10 - --muted: #666;
11 - --link: #0b57d0;
12 - }
13 -
14 - * {
15 - box-sizing: border-box;
16 - }
17 -
18 - body {
19 - margin: 0;
20 - font-family: sans-serif;
21 - color: var(--text);
22 - line-height: 1.5;
23 - }
24 -
25 - main {
26 - max-width: 800px;
27 - margin: 0 auto;
28 - padding: 24px 16px 40px;
29 - }
30 -
31 - h1,
32 - h2,
33 - p {
34 - margin-top: 0;
35 - }
36 -
37 - h1 {
38 - margin-bottom: 16px;
39 - }
40 -
41 - h2 {
42 - margin-bottom: 8px;
43 - font-size: 1rem;
44 - }
45 -
46 - section {
47 - margin-bottom: 20px;
48 - }
49 -
50 - label,
51 - input,
52 - button {
53 - font: inherit;
54 - }
55 -
56 - input {
57 - width: 100%;
58 - padding: 8px 10px;
59 - border: 1px solid #ccc;
60 - background: #fff;
61 - }
62 -
63 - .field {
64 - display: grid;
65 - gap: 6px;
66 - }
67 -
68 - .radio-group {
69 - display: flex;
70 - flex-wrap: wrap;
71 - gap: 12px;
72 - }
73 -
74 - .radio-option {
75 - display: inline-flex;
76 - align-items: center;
77 - gap: 8px;
78 - }
79 -
80 - .radio-option input {
81 - width: auto;
82 - padding: 0;
83 - border: 0;
84 - }
85 -
86 - .links,
87 - .results {
88 - padding: 0;
89 - margin: 0;
90 - list-style: none;
91 - }
92 -
93 - .links {
94 - display: flex;
95 - flex-wrap: wrap;
96 - gap: 8px 12px;
97 - }
98 -
99 - .search-area {
100 - position: relative;
101 - }
102 -
103 - .results {
104 - position: absolute;
105 - top: calc(100% + 4px);
106 - left: 0;
107 - right: 0;
108 - z-index: 10;
109 - max-height: 240px;
110 - overflow-y: auto;
111 - border-top: 1px solid #ddd;
112 - border-bottom: 1px solid #ddd;
113 - background: #fff;
114 - }
115 -
116 - .results[hidden],
117 - .entity-downloads[hidden] {
118 - display: none;
119 - }
120 -
121 - .results li + li {
122 - border-top: 1px solid #ddd;
123 - }
124 -
125 - .result-button {
126 - display: block;
127 - width: 100%;
128 - padding: 10px 0;
129 - border: 0;
130 - background: transparent;
131 - text-align: left;
132 - cursor: pointer;
133 - }
134 -
135 - .result-button:hover,
136 - .result-button.active,
137 - .result-button:focus {
138 - background: #f3f3f3;
139 - }
140 -
141 - .meta,
142 - .status {
143 - color: var(--muted);
144 - }
145 -
146 - .status {
147 - min-height: 1.25rem;
148 - margin: 6px 0 0;
149 - font-size: 0.9rem;
150 - }
151 -
152 - .status.error {
153 - color: #b42318;
154 - }
155 -
156 - .entity-downloads p {
157 - margin-bottom: 8px;
158 - }
159 -
160 - a {
161 - color: var(--link);
162 - }
163 - </style>
164 -</head>
165 -<body>
166 - <main>
167 - <h1>Descargas</h1>
168 -
169 - <section>
170 - <div class="field">
171 - <span>Base</span>
172 - <div class="radio-group">
173 - <label class="radio-option">
174 - <input type="radio" name="dataset" value="gastos" checked>
175 - <span>Gastos</span>
176 - </label>
177 - <label class="radio-option">
178 - <input type="radio" name="dataset" value="ingresos">
179 - <span>Ingresos</span>
180 - </label>
181 - </div>
182 - </div>
183 - </section>
184 -
185 - <section>
186 - <h2>Completo</h2>
187 - <ul class="links" id="full-download"></ul>
188 - </section>
189 -
190 - <section>
191 - <h2>Por gestión</h2>
192 - <ul class="links" id="year-downloads"></ul>
193 - </section>
194 -
195 - <section>
196 - <h2>Por entidad</h2>
197 - <div class="field search-area">
198 - <label for="entity-search">Entidad</label>
199 - <input
200 - id="entity-search"
201 - name="entity-search"
202 - type="search"
203 - placeholder="Busca entidades"
204 - autocomplete="off"
205 - >
206 - <ul class="results" id="entity-results" hidden></ul>
207 - </div>
208 - <p class="status" id="entity-status">Cargando entidades...</p>
209 - <div class="entity-downloads" id="entity-downloads" hidden>
210 - <p id="entity-name"></p>
211 - <ul class="links" id="entity-links"></ul>
212 - </div>
213 - </section>
214 - </main>
215 -
216 - <script>
217 - const API_BASE = "http://136.112.29.74/api/";
218 - const DOWNLOAD_BASE = "https://abierto.economiayfinanzas.gob.bo/presupuesto/descargas/";
219 - const ENTITY_API = `${API_BASE}entidad/clasificador`;
220 - const YEARS = Array.from({ length: 10 }, (_, index) => 2016 + index);
221 - const MAX_ENTITY_RESULTS = 12;
222 - let entities = [];
223 - let activeResultIndex = -1;
224 -
225 - function setStatus(message, type = "info") {
226 - const status = document.getElementById("entity-status");
227 - status.textContent = message;
228 - status.classList.toggle("error", type === "error");
229 - }
230 -
231 - function currentDataset() {
232 - return document.querySelector('input[name="dataset"]:checked').value;
233 - }
234 -
235 - function buildUrl(partition, value) {
236 - return `${DOWNLOAD_BASE}${currentDataset()}/${partition}/${value}`;
237 - }
238 -
239 - function normalizeText(value) {
240 - return value
241 - .normalize("NFD")
242 - .replace(/[\u0300-\u036f]/g, "")
243 - .toLowerCase()
244 - .trim();
245 - }
246 -
247 - function createLinkItem(label, href) {
248 - const item = document.createElement("li");
249 - const link = document.createElement("a");
250 - link.href = href;
251 - link.textContent = label;
252 - item.appendChild(link);
253 - return item;
254 - }
255 -
256 - function renderFullDownload() {
257 - const container = document.getElementById("full-download");
258 - container.innerHTML = "";
259 - container.appendChild(createLinkItem("Descargar", buildUrl("completo", "ultimo")));
260 - }
261 -
262 - function renderYearDownloads() {
263 - const container = document.getElementById("year-downloads");
264 - container.innerHTML = "";
265 -
266 - YEARS.forEach((year) => {
267 - container.appendChild(createLinkItem(String(year), buildUrl("gestion", year)));
268 - });
269 - }
270 -
271 - function renderEntityDownloads(entity) {
272 - const wrapper = document.getElementById("entity-downloads");
273 - const name = document.getElementById("entity-name");
274 - const links = document.getElementById("entity-links");
275 -
276 - name.textContent = entity.desc_entidad;
277 - links.innerHTML = "";
278 - links.appendChild(createLinkItem("Descargar", buildUrl("entidad", entity.entidad)));
279 - wrapper.hidden = false;
280 - }
281 -
282 - function selectEntity(entity) {
283 - document.getElementById("entity-search").value = entity.desc_entidad;
284 - document.getElementById("entity-results").hidden = true;
285 - activeResultIndex = -1;
286 - renderEntityDownloads(entity);
287 - }
288 -
289 - function resultButtons() {
290 - return Array.from(document.querySelectorAll("#entity-results .result-button"));
291 - }
292 -
293 - function setActiveResult(index) {
294 - const buttons = resultButtons();
295 -
296 - buttons.forEach((button, buttonIndex) => {
297 - button.classList.toggle("active", buttonIndex === index);
298 - });
299 -
300 - activeResultIndex = index;
301 -
302 - if (index >= 0 && buttons[index]) {
303 - buttons[index].scrollIntoView({ block: "nearest" });
304 - }
305 - }
306 -
307 - function renderEntityResults(matches) {
308 - const results = document.getElementById("entity-results");
309 - results.innerHTML = "";
310 - activeResultIndex = -1;
311 -
312 - if (!matches.length) {
313 - results.hidden = true;
314 - return;
315 - }
316 -
317 - matches.forEach((entity) => {
318 - const item = document.createElement("li");
319 - const button = document.createElement("button");
320 - const meta = document.createElement("span");
321 -
322 - button.type = "button";
323 - button.className = "result-button";
324 - button.textContent = entity.desc_entidad;
325 - button.addEventListener("click", () => selectEntity(entity));
326 -
327 - meta.className = "meta";
328 - meta.textContent = `Código ${entity.entidad}`;
329 - button.appendChild(document.createElement("br"));
330 - button.appendChild(meta);
331 -
332 - item.appendChild(button);
333 - results.appendChild(item);
334 - });
335 -
336 - results.hidden = false;
337 - }
338 -
339 - function moveActiveResult(direction) {
340 - const buttons = resultButtons();
341 -
342 - if (!buttons.length) {
343 - return;
344 - }
345 -
346 - if (activeResultIndex === -1) {
347 - setActiveResult(direction > 0 ? 0 : buttons.length - 1);
348 - return;
349 - }
350 -
351 - const nextIndex = (activeResultIndex + direction + buttons.length) % buttons.length;
352 - setActiveResult(nextIndex);
353 - }
354 -
355 - function updateEntitySearch() {
356 - const query = normalizeText(document.getElementById("entity-search").value);
357 -
358 - document.getElementById("entity-downloads").hidden = true;
359 -
360 - if (!entities.length) {
361 - return;
362 - }
363 -
364 - if (!query) {
365 - setStatus("");
366 - document.getElementById("entity-results").hidden = true;
367 - activeResultIndex = -1;
368 - return;
369 - }
370 -
371 - const matches = entities
372 - .filter((entity) => entity.normalizedName.includes(query))
373 - .slice(0, MAX_ENTITY_RESULTS);
374 -
375 - if (!matches.length) {
376 - setStatus("Sin resultados.", "error");
377 - document.getElementById("entity-results").hidden = true;
378 - activeResultIndex = -1;
379 - return;
380 - }
381 -
382 - setStatus(`${matches.length} resultado(s).`);
383 - renderEntityResults(matches);
384 - }
385 -
386 - async function loadEntities() {
387 - try {
388 - const response = await fetch(ENTITY_API);
389 -
390 - if (!response.ok) {
391 - throw new Error(`HTTP ${response.status}`);
392 - }
393 -
394 - const data = await response.json();
395 -
396 - entities = data
397 - .filter((entity) => entity && entity.entidad && entity.desc_entidad)
398 - .map((entity) => ({
399 - entidad: entity.entidad,
400 - desc_entidad: entity.desc_entidad,
401 - normalizedName: normalizeText(entity.desc_entidad)
402 - }));
403 -
404 - setStatus("");
405 - } catch (error) {
406 - setStatus("No se pudieron cargar las entidades.", "error");
407 - }
408 - }
409 -
410 - function rerenderDownloads() {
411 - renderFullDownload();
412 - renderYearDownloads();
413 -
414 - const selectedName = document.getElementById("entity-search").value;
415 - const selectedEntity = entities.find(
416 - (entity) => entity.desc_entidad === selectedName
417 - );
418 -
419 - if (selectedEntity) {
420 - renderEntityDownloads(selectedEntity);
421 - }
422 - }
423 -
424 - document.querySelectorAll('input[name="dataset"]').forEach((input) => {
425 - input.addEventListener("change", rerenderDownloads);
426 - });
427 - document.getElementById("entity-search").addEventListener("input", updateEntitySearch);
428 - document.getElementById("entity-search").addEventListener("keydown", (event) => {
429 - const results = document.getElementById("entity-results");
430 -
431 - if (event.key === "ArrowDown") {
432 - event.preventDefault();
433 - if (!results.hidden) {
434 - moveActiveResult(1);
435 - }
436 - }
437 -
438 - if (event.key === "ArrowUp") {
439 - event.preventDefault();
440 - if (!results.hidden) {
441 - moveActiveResult(-1);
442 - }
443 - }
444 -
445 - if (event.key === "Enter") {
446 - const buttons = resultButtons();
447 - if (!results.hidden && activeResultIndex >= 0 && buttons[activeResultIndex]) {
448 - event.preventDefault();
449 - buttons[activeResultIndex].click();
450 - }
451 - }
452 -
453 - if (event.key === "Escape") {
454 - results.hidden = true;
455 - activeResultIndex = -1;
456 - }
457 - });
458 -
459 - renderFullDownload();
460 - renderYearDownloads();
461 - loadEntities();
462 - </script>
463 -</body>
464 -</html>
1 -<!DOCTYPE html>
2 -<html lang="es">
3 -<head>
4 - <meta charset="utf-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1">
6 - <title>Descargas presupuestarias</title>
7 - <style>
8 - :root {
9 - --text: #1f1f1f;
10 - --muted: #666;
11 - --link: #0b57d0;
12 - }
13 -
14 - * {
15 - box-sizing: border-box;
16 - }
17 -
18 - body {
19 - margin: 0;
20 - font-family: sans-serif;
21 - color: var(--text);
22 - line-height: 1.5;
23 - }
24 -
25 - main {
26 - max-width: 800px;
27 - margin: 0 auto;
28 - padding: 24px 16px 40px;
29 - }
30 -
31 - h1,
32 - h2,
33 - p {
34 - margin-top: 0;
35 - }
36 -
37 - h1 {
38 - margin-bottom: 16px;
39 - }
40 -
41 - h2 {
42 - margin-bottom: 8px;
43 - font-size: 1rem;
44 - }
45 -
46 - section {
47 - margin-bottom: 20px;
48 - }
49 -
50 - label,
51 - input,
52 - button {
53 - font: inherit;
54 - }
55 -
56 - input {
57 - width: 100%;
58 - padding: 8px 10px;
59 - border: 1px solid #ccc;
60 - background: #fff;
61 - }
62 -
63 - .field {
64 - display: grid;
65 - gap: 6px;
66 - }
67 -
68 - .radio-group {
69 - display: flex;
70 - flex-wrap: wrap;
71 - gap: 12px;
72 - }
73 -
74 - .radio-option {
75 - display: inline-flex;
76 - align-items: center;
77 - gap: 8px;
78 - }
79 -
80 - .radio-option input {
81 - width: auto;
82 - padding: 0;
83 - border: 0;
84 - }
85 -
86 - .links,
87 - .results {
88 - padding: 0;
89 - margin: 0;
90 - list-style: none;
91 - }
92 -
93 - .links {
94 - display: flex;
95 - flex-wrap: wrap;
96 - gap: 8px 12px;
97 - }
98 -
99 - .search-area {
100 - position: relative;
101 - }
102 -
103 - .results {
104 - position: absolute;
105 - top: calc(100% + 4px);
106 - left: 0;
107 - right: 0;
108 - z-index: 10;
109 - max-height: 240px;
110 - overflow-y: auto;
111 - border-top: 1px solid #ddd;
112 - border-bottom: 1px solid #ddd;
113 - background: #fff;
114 - }
115 -
116 - .results[hidden],
117 - .entity-downloads[hidden] {
118 - display: none;
119 - }
120 -
121 - .results li + li {
122 - border-top: 1px solid #ddd;
123 - }
124 -
125 - .result-button {
126 - display: block;
127 - width: 100%;
128 - padding: 10px 0;
129 - border: 0;
130 - background: transparent;
131 - text-align: left;
132 - cursor: pointer;
133 - }
134 -
135 - .result-button:hover,
136 - .result-button.active,
137 - .result-button:focus {
138 - background: #f3f3f3;
139 - }
140 -
141 - .meta,
142 - .status {
143 - color: var(--muted);
144 - }
145 -
146 - .status {
147 - min-height: 1.25rem;
148 - margin: 6px 0 0;
149 - font-size: 0.9rem;
150 - }
151 -
152 - .status.error {
153 - color: #b42318;
154 - }
155 -
156 - .entity-downloads p {
157 - margin-bottom: 8px;
158 - }
159 -
160 - a {
161 - color: var(--link);
162 - }
163 - </style>
164 -</head>
165 -<body>
166 - <main>
167 - <h1>Descargas</h1>
168 -
169 - <section>
170 - <div class="field">
171 - <span>Base</span>
172 - <div class="radio-group">
173 - <label class="radio-option">
174 - <input type="radio" name="dataset" value="gastos" checked>
175 - <span>Gastos</span>
176 - </label>
177 - <label class="radio-option">
178 - <input type="radio" name="dataset" value="ingresos">
179 - <span>Ingresos</span>
180 - </label>
181 - </div>
182 - </div>
183 - </section>
184 -
185 - <section>
186 - <h2>Completo</h2>
187 - <ul class="links" id="full-download"></ul>
188 - </section>
189 -
190 - <section>
191 - <h2>Por gestión</h2>
192 - <ul class="links" id="year-downloads"></ul>
193 - </section>
194 -
195 - <section>
196 - <h2>Por entidad</h2>
197 - <div class="field search-area">
198 - <label for="entity-search">Entidad</label>
199 - <input
200 - id="entity-search"
201 - name="entity-search"
202 - type="search"
203 - placeholder="Busca entidades"
204 - autocomplete="off"
205 - >
206 - <ul class="results" id="entity-results" hidden></ul>
207 - </div>
208 - <p class="status" id="entity-status">Cargando entidades...</p>
209 - <div class="entity-downloads" id="entity-downloads" hidden>
210 - <p id="entity-name"></p>
211 - <ul class="links" id="entity-links"></ul>
212 - </div>
213 - </section>
214 - </main>
215 -
216 - <script>
217 - const API_BASE = "http://136.112.29.74/api/";
218 - const DOWNLOAD_BASE = "https://abierto.economiayfinanzas.gob.bo/presupuesto/descargas/";
219 - const ENTITY_API = `${API_BASE}entidad/clasificador`;
220 - const YEARS = Array.from({ length: 10 }, (_, index) => 2016 + index);
221 - const MAX_ENTITY_RESULTS = 12;
222 - let entities = [];
223 - let activeResultIndex = -1;
224 -
225 - function setStatus(message, type = "info") {
226 - const status = document.getElementById("entity-status");
227 - status.textContent = message;
228 - status.classList.toggle("error", type === "error");
229 - }
230 -
231 - function currentDataset() {
232 - return document.querySelector('input[name="dataset"]:checked').value;
233 - }
234 -
235 - function buildUrl(partition, value) {
236 - return `${DOWNLOAD_BASE}${currentDataset()}/${partition}/${value}`;
237 - }
238 -
239 - function normalizeText(value) {
240 - return value
241 - .normalize("NFD")
242 - .replace(/[\u0300-\u036f]/g, "")
243 - .toLowerCase()
244 - .trim();
245 - }
246 -
247 - function createLinkItem(label, href) {
248 - const item = document.createElement("li");
249 - const link = document.createElement("a");
250 - link.href = href;
251 - link.textContent = label;
252 - item.appendChild(link);
253 - return item;
254 - }
255 -
256 - function renderFullDownload() {
257 - const container = document.getElementById("full-download");
258 - container.innerHTML = "";
259 - container.appendChild(createLinkItem("Descargar", buildUrl("completo", "ultimo")));
260 - }
261 -
262 - function renderYearDownloads() {
263 - const container = document.getElementById("year-downloads");
264 - container.innerHTML = "";
265 -
266 - YEARS.forEach((year) => {
267 - container.appendChild(createLinkItem(String(year), buildUrl("gestion", year)));
268 - });
269 - }
270 -
271 - function renderEntityDownloads(entity) {
272 - const wrapper = document.getElementById("entity-downloads");
273 - const name = document.getElementById("entity-name");
274 - const links = document.getElementById("entity-links");
275 -
276 - name.textContent = entity.desc_entidad;
277 - links.innerHTML = "";
278 - links.appendChild(createLinkItem("Descargar", buildUrl("entidad", entity.entidad)));
279 - wrapper.hidden = false;
280 - }
281 -
282 - function selectEntity(entity) {
283 - document.getElementById("entity-search").value = entity.desc_entidad;
284 - document.getElementById("entity-results").hidden = true;
285 - activeResultIndex = -1;
286 - renderEntityDownloads(entity);
287 - }
288 -
289 - function resultButtons() {
290 - return Array.from(document.querySelectorAll("#entity-results .result-button"));
291 - }
292 -
293 - function setActiveResult(index) {
294 - const buttons = resultButtons();
295 -
296 - buttons.forEach((button, buttonIndex) => {
297 - button.classList.toggle("active", buttonIndex === index);
298 - });
299 -
300 - activeResultIndex = index;
301 -
302 - if (index >= 0 && buttons[index]) {
303 - buttons[index].scrollIntoView({ block: "nearest" });
304 - }
305 - }
306 -
307 - function renderEntityResults(matches) {
308 - const results = document.getElementById("entity-results");
309 - results.innerHTML = "";
310 - activeResultIndex = -1;
311 -
312 - if (!matches.length) {
313 - results.hidden = true;
314 - return;
315 - }
316 -
317 - matches.forEach((entity) => {
318 - const item = document.createElement("li");
319 - const button = document.createElement("button");
320 - const meta = document.createElement("span");
321 -
322 - button.type = "button";
323 - button.className = "result-button";
324 - button.textContent = entity.desc_entidad;
325 - button.addEventListener("click", () => selectEntity(entity));
326 -
327 - meta.className = "meta";
328 - meta.textContent = `Código ${entity.entidad}`;
329 - button.appendChild(document.createElement("br"));
330 - button.appendChild(meta);
331 -
332 - item.appendChild(button);
333 - results.appendChild(item);
334 - });
335 -
336 - results.hidden = false;
337 - }
338 -
339 - function moveActiveResult(direction) {
340 - const buttons = resultButtons();
341 -
342 - if (!buttons.length) {
343 - return;
344 - }
345 -
346 - if (activeResultIndex === -1) {
347 - setActiveResult(direction > 0 ? 0 : buttons.length - 1);
348 - return;
349 - }
350 -
351 - const nextIndex = (activeResultIndex + direction + buttons.length) % buttons.length;
352 - setActiveResult(nextIndex);
353 - }
354 -
355 - function updateEntitySearch() {
356 - const query = normalizeText(document.getElementById("entity-search").value);
357 -
358 - document.getElementById("entity-downloads").hidden = true;
359 -
360 - if (!entities.length) {
361 - return;
362 - }
363 -
364 - if (!query) {
365 - setStatus("");
366 - document.getElementById("entity-results").hidden = true;
367 - activeResultIndex = -1;
368 - return;
369 - }
370 -
371 - const matches = entities
372 - .filter((entity) => entity.normalizedName.includes(query))
373 - .slice(0, MAX_ENTITY_RESULTS);
374 -
375 - if (!matches.length) {
376 - setStatus("Sin resultados.", "error");
377 - document.getElementById("entity-results").hidden = true;
378 - activeResultIndex = -1;
379 - return;
380 - }
381 -
382 - setStatus(`${matches.length} resultado(s).`);
383 - renderEntityResults(matches);
384 - }
385 -
386 - async function loadEntities() {
387 - try {
388 - const response = await fetch(ENTITY_API);
389 -
390 - if (!response.ok) {
391 - throw new Error(`HTTP ${response.status}`);
392 - }
393 -
394 - const data = await response.json();
395 -
396 - entities = data
397 - .filter((entity) => entity && entity.entidad && entity.desc_entidad)
398 - .map((entity) => ({
399 - entidad: entity.entidad,
400 - desc_entidad: entity.desc_entidad,
401 - normalizedName: normalizeText(entity.desc_entidad)
402 - }));
403 -
404 - setStatus("");
405 - } catch (error) {
406 - setStatus("No se pudieron cargar las entidades.", "error");
407 - }
408 - }
409 -
410 - function rerenderDownloads() {
411 - renderFullDownload();
412 - renderYearDownloads();
413 -
414 - const selectedName = document.getElementById("entity-search").value;
415 - const selectedEntity = entities.find(
416 - (entity) => entity.desc_entidad === selectedName
417 - );
418 -
419 - if (selectedEntity) {
420 - renderEntityDownloads(selectedEntity);
421 - }
422 - }
423 -
424 - document.querySelectorAll('input[name="dataset"]').forEach((input) => {
425 - input.addEventListener("change", rerenderDownloads);
426 - });
427 - document.getElementById("entity-search").addEventListener("input", updateEntitySearch);
428 - document.getElementById("entity-search").addEventListener("keydown", (event) => {
429 - const results = document.getElementById("entity-results");
430 -
431 - if (event.key === "ArrowDown") {
432 - event.preventDefault();
433 - if (!results.hidden) {
434 - moveActiveResult(1);
435 - }
436 - }
437 -
438 - if (event.key === "ArrowUp") {
439 - event.preventDefault();
440 - if (!results.hidden) {
441 - moveActiveResult(-1);
442 - }
443 - }
444 -
445 - if (event.key === "Enter") {
446 - const buttons = resultButtons();
447 - if (!results.hidden && activeResultIndex >= 0 && buttons[activeResultIndex]) {
448 - event.preventDefault();
449 - buttons[activeResultIndex].click();
450 - }
451 - }
452 -
453 - if (event.key === "Escape") {
454 - results.hidden = true;
455 - activeResultIndex = -1;
456 - }
457 - });
458 -
459 - renderFullDownload();
460 - renderYearDownloads();
461 - loadEntities();
462 - </script>
463 -</body>
464 -</html>