PageSourceSearch

https://www.discourse.org/a/js/pricing.js?1790174693181339485

js discourse.org collected 2026-09-24 06:55:25 UTC 4,580 bytes, 141 lines download raw bytes

1document.addEventListener("DOMContentLoaded", function () {
2  if (typeof tippy !== "undefined") {
3    // Initialize tooltips for feature list items (uses template for HTML content)
4    const tooltipElements = document.querySelectorAll(".feature-with-tooltip");
5
6    tooltipElements.forEach(function (element) {
7      const template = element.previousElementSibling;
8      if (template && template.classList.contains("tooltip-template")) {
9        tippy(element, {
10          allowHTML: true,
11          placement: "top",
12          theme: "dark",
13          arrow: true,
14          interactive: false,
15          maxWidth: 300,
16          content: template.innerHTML,
17        });
18      }
19    });
20
21    // Initialize tooltips for footnote tooltips (uses data-tippy-content for simple text)
22    tippy(".footnote-tooltip", {
23      placement: "top",
24      theme: "dark",
25      arrow: true,
26      interactive: false,
27    });
28  }
29
30  // Add shadow to sticky comparison header only when it's actually sticky
31  function updateScrolledComparisonHeader() {
32    const comparisonHeader = document.querySelector(
33      ".comparison__shared-header"
34    );
35    if (!comparisonHeader) {
36      return;
37    }
38
39    // Check if the header is actually in sticky position
40    // The header becomes sticky at top: 75px, so check if its top position equals 75px
41    const rect = comparisonHeader.getBoundingClientRect();
42    const stickyTop = 75; // matches top: 75px in CSS
43
44    // Header is sticky when its top position equals the sticky top value
45    // Add a small tolerance (1px) for rounding
46    if (Math.abs(rect.top - stickyTop) < 1) {
47      comparisonHeader.classList.add("is-scrolled");
48    } else {
49      comparisonHeader.classList.remove("is-scrolled");
50    }
51  }
52
53  // Update sticky header section title based on which table is visible
54  function updateStickySectionTitle() {
55    const stickyTitle = document.querySelector(
56      ".comparison__sticky-section-title"
57    );
58    if (!stickyTitle) {
59      return;
60    }
61
62    const sections = document.querySelectorAll(".comparison__table-section");
63    const stickyHeader = document.querySelector(".comparison__shared-header");
64    if (!stickyHeader) {
65      return;
66    }
67
68    const stickyHeaderRect = stickyHeader.getBoundingClientRect();
69    const stickyTop = 75; // matches top: 75px in CSS
70    const isSticky = Math.abs(stickyHeaderRect.top - stickyTop) < 1;
71
72    // Only update title when header is sticky
73    if (!isSticky) {
74      stickyTitle.textContent = "";
75      return;
76    }
77
78    // Find which section title is currently closest to or above the sticky header
79    let currentSection = null;
80    let closestDistance = Infinity;
81
82    sections.forEach((section) => {
83      const sectionTitle = section.querySelector(
84        ".comparison__table-section-title"
85      );
86      if (!sectionTitle) {
87        return;
88      }
89
90      const titleRect = sectionTitle.getBoundingClientRect();
91      const sectionRect = section.getBoundingClientRect();
92
93      // Check if the section title is above or at the sticky header position
94      // We want to show the title of the section that's currently being viewed
95      if (titleRect.bottom <= stickyTop + 150) {
96        // Section title is above or near the sticky header
97        const distance = Math.abs(titleRect.bottom - stickyTop);
98        if (distance < closestDistance) {
99          closestDistance = distance;
100          currentSection = sectionTitle;
101        }
102      } else if (
103        sectionRect.top <= stickyTop + 50 &&
104        sectionRect.bottom > stickyTop
105      ) {
106        // Section is currently visible at the sticky header position
107        const distance = Math.abs(sectionRect.top - stickyTop);
108        if (distance < closestDistance) {
109          closestDistance = distance;
110          currentSection = sectionTitle;
111        }
112      }
113    });
114
115    // Update the sticky header title
116    if (currentSection) {
117      const newTitle = currentSection.textContent.trim();
118      if (stickyTitle.textContent !== newTitle) {
119        stickyTitle.textContent = newTitle;
120      }
121    }
122  }
123
124  // Throttle scroll events for better performance
125  let scrollTimeout;
126
127  function handleScroll() {
128    if (scrollTimeout) {
129      cancelAnimationFrame(scrollTimeout);
130    }
131    scrollTimeout = requestAnimationFrame(() => {
132      updateScrolledComparisonHeader();
133      updateStickySectionTitle();
134    });
135  }
136
137  // Set up scroll listener and initialize on page load
138  window.addEventListener("scroll", handleScroll, { passive: true });
139  updateScrolledComparisonHeader();
140  updateStickySectionTitle();
141});

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.