PageSourceSearch

https://arenab3.com.br/v2-page-hero.js

js arenab3.com.br collected 2026-10-05 21:43:14 UTC 7,169 bytes, 246 lines download raw bytes

1/**
2 * Arena B3 v2 — Faixa azul + colchete pontilhado no topo das paginas internas.
3 * Substitui o titulo-texto solto por page hero full-bleed (pedido cliente 05/08).
4 */
5(function () {
6  'use strict';
7
8  var HERO_ID = 'ab3-v2-page-hero';
9  var BODY_CLASS = 'ab3-v2-has-page-hero';
10
11  var TITLES = {
12    'quemSomos': {
13      pt: 'Quem Somos',
14      en: 'About Us',
15      es: 'Quiénes Somos',
16    },
17    programacao: {
18      pt: 'Programação',
19      en: 'Program',
20      es: 'Programación',
21    },
22    galeria: {
23      pt: 'Galeria de Fotos',
24      en: 'Photo Gallery',
25      es: 'Galería de Fotos',
26    },
27    imprensa: {
28      pt: 'Imprensa',
29      en: 'Press',
30      es: 'Prensa',
31    },
32    comoChegar: {
33      pt: 'Como Chegar',
34      en: 'Getting Here',
35      es: 'Cómo Llegar',
36    },
37    faq: {
38      pt: 'FAQ',
39      en: 'FAQ',
40      es: 'FAQ',
41    },
42  };
43
44  var renderedKey = '';
45  var lastScrollHash = '';
46
47  /* Arte cliente: colchetes [ ] solidos (nao pontilhados). Branco via CSS color. */
48  var BRACKET_SVG =
49    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150" fill="currentColor" aria-hidden="true">' +
50    '<path d="M0 0 H34 V11 H11 V139 H34 V150 H0 Z"/>' +
51    '<path d="M116 0 H150 V150 H116 V139 H139 V11 H116 Z"/>' +
52    '</svg>';
53
54  function parseHash() {
55    var hash = location.hash || '';
56    var route = location.pathname.replace(/\/$/, '') || '/';
57    var fragment = '';
58    if (hash.charAt(0) === '#') {
59      var raw = hash.slice(1);
60      var qIndex = raw.indexOf('?');
61      if (qIndex >= 0) raw = raw.slice(0, qIndex);
62      var fragIndex = raw.indexOf('#');
63      if (fragIndex >= 0) {
64        fragment = raw.slice(fragIndex + 1);
65        raw = raw.slice(0, fragIndex);
66      }
67      if (raw && raw.charAt(0) === '/') {
68        route = raw.replace(/\/$/, '') || '/';
69      }
70    }
71    return { route: route, fragment: fragment };
72  }
73
74  function getLang() {
75    var lang = '';
76    try {
77      lang = localStorage.getItem('currentLanguage') || '';
78    } catch (e) { /* storage indisponivel */ }
79    return ['pt', 'en', 'es'].indexOf(lang) >= 0 ? lang : 'pt';
80  }
81
82  function resolveHeroKey(parsed) {
83    if (parsed.route === '/programacao') return 'programacao';
84    if (parsed.route === '/a-arena') {
85      if (parsed.fragment === 'galeria') return 'galeria';
86      if (!parsed.fragment || parsed.fragment === 'institucional') return 'quemSomos';
87      return null;
88    }
89    if (parsed.route === '/contato') {
90      if (parsed.fragment === 'imprensa') return 'imprensa';
91      if (parsed.fragment === 'como-chegar') return 'comoChegar';
92      if (parsed.fragment === 'faq') return 'faq';
93      return null;
94    }
95    return null;
96  }
97
98  function ensureHeroElement() {
99    var existing = document.getElementById(HERO_ID);
100    if (existing) return existing;
101
102    var navbar = document.querySelector('app-navbar');
103    if (!navbar || !navbar.parentNode) return null;
104
105    var hero = document.createElement('header');
106    hero.id = HERO_ID;
107    hero.className = 'ab3-v2-page-hero';
108    hero.hidden = true;
109
110    var inner = document.createElement('div');
111    inner.className = 'ab3-v2-page-hero__inner';
112
113    var heading = document.createElement('div');
114    heading.className = 'ab3-v2-page-hero__heading';
115
116    var title = document.createElement('h1');
117    title.className = 'ab3-v2-page-hero__title';
118
119    var bracket = document.createElement('span');
120    bracket.className = 'ab3-v2-page-hero__bracket';
121    bracket.setAttribute('aria-hidden', 'true');
122    bracket.innerHTML = BRACKET_SVG;
123
124    heading.appendChild(title);
125    heading.appendChild(bracket);
126    inner.appendChild(heading);
127    hero.appendChild(inner);
128
129    navbar.parentNode.insertBefore(hero, navbar.nextSibling);
130    return hero;
131  }
132
133  /**
134   * Cliente 06/08: ao mudar de pagina o browser/Angular ancora no fragment
135   * (#institucional, #galeria, #faq…) e o banner azul fica fora da viewport
136   * ("entra no meio da pagina"). Corrige rolando o page-hero para logo
137   * abaixo do navbar sticky — com retries pq o Angular ainda re-rola.
138   */
139  function scrollBannerIntoView() {
140    var hero = document.getElementById(HERO_ID);
141    if (!hero || hero.hidden) return;
142
143    var tries = 0;
144    function go() {
145      hero = document.getElementById(HERO_ID);
146      if (!hero || hero.hidden) return;
147
148      var navbar = document.querySelector('app-navbar');
149      var navH = navbar ? navbar.getBoundingClientRect().height : 0;
150      var heroTop = hero.getBoundingClientRect().top;
151      // Ideal: topo do banner colado sob o navbar (±28px).
152      if (Math.abs(heroTop - navH) > 28) {
153        var absoluteTop = hero.getBoundingClientRect().top + window.pageYOffset - navH;
154        window.scrollTo({
155          top: Math.max(0, Math.round(absoluteTop)),
156          behavior: tries === 0 ? 'smooth' : 'auto',
157        });
158      }
159
160      tries += 1;
161      if (tries < 7) {
162        setTimeout(go, tries === 1 ? 180 : 420);
163      }
164    }
165    setTimeout(go, 60);
166  }
167
168  function updateHero() {
169    if ((location.hash || '').indexOf('/admin') === 1) return;
170
171    var parsed = parseHash();
172    var lang = getLang();
173    var heroKey = resolveHeroKey(parsed);
174    var hero = ensureHeroElement();
175    if (!hero) return;
176
177    if (!heroKey) {
178      hero.hidden = true;
179      document.body.classList.remove(BODY_CLASS);
180      renderedKey = '';
181      lastScrollHash = '';
182      return;
183    }
184
185    var copy = TITLES[heroKey];
186    var titleText = (copy && copy[lang]) || (copy && copy.pt) || '';
187    var nextKey = heroKey + '|' + lang + '|' + titleText;
188    var hashNow = location.hash || '';
189    var hashChanged = hashNow !== lastScrollHash;
190
191    hero.hidden = false;
192    document.body.classList.add(BODY_CLASS);
193
194    if (renderedKey !== nextKey) {
195      var titleEl = hero.querySelector('.ab3-v2-page-hero__title');
196      if (titleEl) titleEl.textContent = titleText;
197
198      var bracketEl = hero.querySelector('.ab3-v2-page-hero__bracket');
199      if (bracketEl) {
200        bracketEl.innerHTML = BRACKET_SVG;
201      }
202
203      renderedKey = nextKey;
204    }
205
206    // Corrige ancora ao trocar hash (browser/Angular apontam pro fragment e
207    // escondem o banner). MutationObserver nao deve re-disparar o scroll.
208    if (hashChanged) {
209      lastScrollHash = hashNow;
210      scrollBannerIntoView();
211    }
212  }
213
214  function watchSpaNavigation() {
215    window.addEventListener('hashchange', updateHero);
216    window.addEventListener('popstate', updateHero);
217
218    ['pushState', 'replaceState'].forEach(function (method) {
219      var original = history[method];
220      history[method] = function () {
221        var result = original.apply(this, arguments);
222        updateHero();
223        return result;
224      };
225    });
226
227    var appRoot = document.querySelector('app-root');
228    if (appRoot && window.MutationObserver) {
229      var observer = new MutationObserver(function () {
230        updateHero();
231      });
232      observer.observe(appRoot, { childList: true, subtree: true });
233    }
234  }
235
236  function init() {
237    updateHero();
238    watchSpaNavigation();
239  }
240
241  if (document.readyState === 'loading') {
242    document.addEventListener('DOMContentLoaded', init);
243  } else {
244    init();
245  }
246})();

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.