PageSourceSearch

https://nutrebem.prod.nutrebem.com.br/assets/controllers/sticky_header_controller-ff4654df.js

js nutrebem.com.br collected 2026-10-01 16:40:37 UTC 3,146 bytes, 87 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2
3// Cabecalho que acompanha a rolagem numa tabela larga demais para caber na tela. Quem gruda
4// nao e o `<thead>` original: uma copia dele vai para um bloco de posicao fixa, com a
5// largura de cada coluna medida na tabela real toda vez que aparece.
6//
7// `position: sticky` no proprio `<thead>` nao resolve o caso: a tabela tambem rola na
8// horizontal, dentro de um container com `overflow`, e o cabecalho preso acompanharia a
9// rolagem vertical da pagina mas nao a horizontal do container — as colunas sairiam do
10// lugar. A copia e reposicionada a cada exibicao justamente por isso.
11export default class extends Controller {
12  static values = { topo: { type: Number, default: 64 } }
13
14  connect() {
15    this.tabela = this.element.querySelector("table")
16    this.cabecalho = this.tabela?.querySelector("thead")
17    if (!this.cabecalho) return
18
19    this.#montarCopia()
20
21    this.aoRolar = () => this.#posicionar()
22    this.aoRedimensionar = () => this.#visivel() && this.#medir()
23
24    window.addEventListener("scroll", this.aoRolar, { passive: true })
25    window.addEventListener("resize", this.aoRedimensionar)
26    this.#posicionar()
27  }
28
29  disconnect() {
30    if (!this.cabecalho) return
31
32    window.removeEventListener("scroll", this.aoRolar)
33    window.removeEventListener("resize", this.aoRedimensionar)
34    this.copia?.remove()
35  }
36
37  #montarCopia() {
38    this.copiaCabecalho = this.cabecalho.cloneNode(true)
39
40    this.copiaTabela = document.createElement("table")
41    this.copiaTabela.className = this.tabela.className
42    this.copiaTabela.appendChild(this.copiaCabecalho)
43
44    // Fora do container que rola na horizontal: preso la dentro, o bloco fixo seria
45    // recortado pelo `overflow`.
46    this.copia = document.createElement("div")
47    this.copia.className = "sticky-thead-clone"
48    this.copia.style.top = `${this.topoValue}px`
49    this.copia.appendChild(this.copiaTabela)
50    document.body.appendChild(this.copia)
51  }
52
53  #posicionar() {
54    const cabecalho = this.cabecalho.getBoundingClientRect()
55    const tabela = this.tabela.getBoundingClientRect()
56    const passou = cabecalho.top < this.topoValue && tabela.bottom > this.topoValue
57
58    if (passou) this.#medir()
59    this.copia.style.display = passou ? "block" : "none"
60  }
61
62  #medir() {
63    const linhas = this.copiaCabecalho.querySelectorAll("tr")
64
65    this.cabecalho.querySelectorAll("tr").forEach((linha, indice) => {
66      const copias = linhas[indice]?.querySelectorAll("th")
67      if (!copias) return
68
69      linha.querySelectorAll("th").forEach((celula, coluna) => {
70        const copia = copias[coluna]
71        if (!copia) return
72
73        const largura = `${celula.getBoundingClientRect().width}px`
74        Object.assign(copia.style, { width: largura, minWidth: largura, maxWidth: largura, boxSizing: "border-box" })
75      })
76    })
77
78    const tabela = this.tabela.getBoundingClientRect()
79    this.copia.style.left = `${tabela.left}px`
80    this.copia.style.width = `${tabela.width}px`
81    this.copiaTabela.style.width = `${tabela.width}px`
82  }
83
84  #visivel() {
85    return this.copia.style.display === "block"
86  }
87}

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.