PageSourceSearch

https://lafolkargentina.com.ar/assets/astra/astra.js?v=80.12

js lafolkargentina.com.ar collected 2026-10-04 13:26:33 UTC 10,779 bytes, 185 lines download raw bytes

1/* Magazine Astra: independent of jQuery/Bootstrap for navigation and loading. */
2(() => {
3  'use strict';
4  const ready = fn => document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', fn, {once:true}) : fn();
5  ready(() => {
6    if (!document.body.classList.contains('theme-astra')) return;
7    document.querySelectorAll('[data-astra-toggle="collapse"]').forEach(button => {
8      const target = document.querySelector(button.getAttribute('data-target'));
9      if (!target) return;
10      button.addEventListener('click', () => {
11        const open = !target.classList.contains('show');
12        target.classList.toggle('show', open); button.setAttribute('aria-expanded', String(open));
13      });
14      target.addEventListener('keydown', event => {
15        if (event.key === 'Escape') { target.classList.remove('show'); button.setAttribute('aria-expanded','false'); button.focus(); }
16      });
17    });
18    document.querySelectorAll('[data-astra-toggle="dropdown"]').forEach(toggle => {
19      toggle.setAttribute('aria-expanded','false');
20      toggle.addEventListener('click', event => {
21        event.preventDefault();
22        const menu = toggle.parentElement.querySelector('.dropdown-menu');
23        if (menu) { const open = !menu.classList.contains('show'); menu.classList.toggle('show',open); toggle.setAttribute('aria-expanded',String(open)); }
24      });
25    });
26    document.addEventListener('keydown', event => {
27      if(event.key !== 'Escape') return;
28      document.querySelectorAll('[data-astra-toggle="dropdown"][aria-expanded="true"]').forEach(toggle=>{toggle.parentElement.querySelector('.dropdown-menu')?.classList.remove('show');toggle.setAttribute('aria-expanded','false');toggle.focus();});
29    });
30    // La columna más corta acompaña el scroll, limitada por el final de la fila.
31    const columns = document.getElementById('main-content');
32    const content = columns?.querySelector(':scope > #content');
33    const sidebar = columns?.querySelector(':scope > #sidebar');
34    const sidebarInner = sidebar?.querySelector('.sidebar__inner');
35    if (content && sidebar && sidebarInner) {
36      const contentInner = document.createElement('div');
37      contentInner.className = 'astra-content-inner';
38      while (content.firstChild) contentInner.append(content.firstChild);
39      content.append(contentInner);
40      columns.classList.add('astra-balanced-columns');
41      let pending = false;
42      const measureColumns = () => {
43        pending = false;
44        const mobile = window.innerWidth < 768;
45        const leftHeight = contentInner.getBoundingClientRect().height;
46        const rightHeight = sidebarInner.getBoundingClientRect().height;
47        const leftShorter = leftHeight + 1 < rightHeight;
48        content.classList.toggle('astra-column-follow', !mobile && leftShorter);
49        sidebar.classList.toggle('astra-column-follow', !mobile && !leftShorter);
50        const menuHeight = document.getElementById('navigato2')?.offsetHeight || 0;
51        [[content, leftHeight], [sidebar, rightHeight]].forEach(([column, height]) => {
52          const top = Math.min(menuHeight + 16, window.innerHeight - height - 16);
53          column.style.setProperty('--astra-column-top', `${top}px`);
54        });
55      };
56      const scheduleColumns = () => {
57        if (!pending) { pending = true; requestAnimationFrame(measureColumns); }
58      };
59      window.addEventListener('resize', scheduleColumns, {passive:true});
60      window.addEventListener('load', scheduleColumns, {once:true});
61      if (window.ResizeObserver) {
62        const observer = new ResizeObserver(scheduleColumns);
63        observer.observe(contentInner);
64        observer.observe(sidebarInner);
65        const menu = document.getElementById('navigato2');
66        if (menu) observer.observe(menu);
67      }
68      measureColumns();
69    }
70    // Isotope masonry: cada noticia conserva su altura, incluida su publicidad.
71    const masonryGrids = [];
72    document.querySelectorAll('.astra-list, .astra-category-band__grid, .astra-legacy-grid').forEach((grid, gridIndex) => {
73      if (!window.Isotope) return; // El CSS original sigue siendo legible si falla la librería.
74      const legacy = grid.classList.contains('astra-legacy-grid');
75      const itemAttribute = `astra-masonry-${gridIndex}`;
76      let instance = null, pending = false, lastWidth = -1;
77      const seen = new WeakSet();
78      const sizes = new WeakMap();
79      const schedule = () => {
80        if (!pending) { pending = true; requestAnimationFrame(layout); }
81      };
82      const itemObserver = window.ResizeObserver ? new ResizeObserver(entries => {
83        let changed = false;
84        entries.forEach(entry => {
85          const next = `${entry.contentRect.width}:${entry.contentRect.height}`;
86          if (sizes.get(entry.target) !== next) { sizes.set(entry.target, next); changed = true; }
87        });
88        if (changed) schedule();
89      }) : null;
90      function layout() {
91        pending = false;
92        const items = Array.from(grid.children).filter(el => !['SCRIPT','STYLE','TEMPLATE'].includes(el.tagName));
93        if (!items.length || grid.clientWidth < 2) return;
94        grid.classList.add('astra-isotope');
95        items.forEach(item => {
96          item.setAttribute('data-astra-masonry-item', itemAttribute);
97          if (!seen.has(item)) { seen.add(item); itemObserver?.observe(item); }
98        });
99        const width = Math.min(...items.map(item => item.getBoundingClientRect().width).filter(w => w > 0));
100        if (!Number.isFinite(width)) return;
101        const options = {
102          itemSelector: `[data-astra-masonry-item="${itemAttribute}"]`,
103          layoutMode: 'masonry', percentPosition: true, transitionDuration: 0,
104          masonry: {columnWidth: width, gutter: legacy ? 0 : 24, horizontalOrder: false}
105        };
106        if (!instance) instance = new window.Isotope(grid, options);
107        else { instance.option(options); instance.reloadItems(); instance.arrange(); }
108      }
109      grid.addEventListener('load', schedule, true);
110      grid.addEventListener('error', schedule, true);
111      grid.addEventListener('loadedmetadata', schedule, true);
112      new MutationObserver(schedule).observe(grid, {childList:true, subtree:true});
113      if (window.ResizeObserver) new ResizeObserver(entries => {
114        const width = entries[0].contentRect.width;
115        if (width !== lastWidth) { lastWidth = width; schedule(); }
116      }).observe(grid);
117      window.addEventListener('resize', schedule, {passive:true});
118      window.addEventListener('load', schedule, {once:true});
119      document.fonts?.ready.then(schedule);
120      masonryGrids.push({grid, schedule});
121      layout();
122    });
123    const externalScripts = new Set(Array.from(document.scripts).filter(s=>s.src).map(s=>s.src));
124    // Only server-rendered cards (escaped) and existing trusted administrator ads enter this fragment.
125    const activateAds = async nodes => {
126      for (const node of nodes) {
127        for (const inert of node.querySelectorAll('script')) {
128          if (inert.type && !['text/javascript','application/javascript','module'].includes(inert.type)) continue;
129          const script = document.createElement('script');
130          for (const attr of inert.attributes) script.setAttribute(attr.name,attr.value);
131          script.textContent = inert.textContent;
132          if (script.src && externalScripts.has(script.src)) { inert.remove(); continue; }
133          if (script.src) {
134            externalScripts.add(script.src);
135            if (!script.async) await new Promise(resolve => { script.onload=resolve; script.onerror=resolve; inert.replaceWith(script); });
136            else inert.replaceWith(script);
137          } else inert.replaceWith(script);
138        }
139      }
140    };
141    document.querySelectorAll('[data-astra-feed]').forEach(feed => {
142      const button = feed.querySelector('[data-astra-more]');
143      if (!button || !window.fetch || !window.AbortController) return;
144      const items = feed.querySelector('[data-astra-items]');
145      const status = feed.querySelector('[role="status"]');
146      const fallback = feed.querySelector('[data-astra-fallback]');
147      const context = JSON.parse(feed.dataset.context);
148      let loading = false;
149      button.hidden=false; if(fallback)fallback.hidden=true;
150      button.addEventListener('click', async () => {
151        if(loading) return;
152        loading=true; button.disabled=true; button.textContent='Cargando…'; feed.setAttribute('aria-busy','true'); status.textContent='';
153        const controller=new AbortController(); const timeout=setTimeout(()=>controller.abort(),20000);
154        try {
155          const url=new URL(feed.dataset.endpoint,document.baseURI);
156          Object.entries(context).forEach(([key,value])=>url.searchParams.set(key,value));
157          url.searchParams.set('cursor',button.dataset.cursor);
158          const response=await fetch(url,{signal:controller.signal,headers:{Accept:'application/json'},credentials:'same-origin'});
159          if(!response.ok) throw new Error('HTTP '+response.status);
160          const data=await response.json();
161          if(!data.success || typeof data.html!=='string' || typeof data.has_more!=='boolean' || (data.has_more && typeof data.cursor!=='string')) throw new Error('Respuesta inválida');
162          const template=document.createElement('template'); template.innerHTML=data.html;
163          const known=new Set(Array.from(items.querySelectorAll('[data-news-id]'),el=>el.dataset.newsId));
164          template.content.querySelectorAll('[data-news-id]').forEach(el=>{if(known.has(el.dataset.newsId))el.remove();});
165          const nodes=Array.from(template.content.children); const first=template.content.querySelector('.astra-card__title a');
166          items.append(template.content);
167          masonryGrids.forEach(entry => { if (entry.grid === items) entry.schedule(); });
168          button.dataset.cursor=data.cursor;
169          if(fallback && typeof data.fallback==='string') fallback.href=data.fallback;
170          button.hidden=!data.has_more;
171          status.textContent=data.count ? `${data.count} noticias cargadas.${data.has_more?'':' No hay más noticias.'}` : 'No hay más noticias.';
172          if(first) first.focus({preventScroll:true});
173          if(fallback) fallback.hidden=true;
174          activateAds(nodes).catch(()=>{});
175        } catch(error) {
176          status.textContent='No se pudieron cargar más noticias. Intentar nuevamente.';
177          // Original link remains a usable fallback for the next SSR page.
178          if(fallback) fallback.hidden=false;
179        } finally {
180          clearTimeout(timeout); loading=false; button.disabled=false; button.textContent='VER MÁS'; feed.removeAttribute('aria-busy');
181        }
182      });
183    });
184  });
185})();

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.