PageSourceSearch

https://www.georgetowncoc.com/assets/controllers/website_agent_response_controller-bf8ee935.js

js georgetowncoc.com collected 2026-09-25 04:06:25 UTC 3,196 bytes, 97 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2
3const MAX_REQUIRED_VISIBLE_HEIGHT = 96
4
5export default class extends Controller {
6  static values = {
7    viewedUrl: String,
8    kind: String,
9    version: String,
10    viewed: { type: Boolean, default: false },
11  }
12
13  connect() {
14    this.markingViewed = false
15    this.retryTimer = null
16    this.visibilityChanged = () => this.acknowledgeIfVisible()
17    document.addEventListener("visibilitychange", this.visibilityChanged)
18
19    if (this.viewedValue) return
20    this.responseVisible = this.responseIsInViewport()
21
22    if (!("IntersectionObserver" in window)) {
23      this.acknowledgeIfVisible()
24      return
25    }
26
27    this.observer = new IntersectionObserver((entries) => {
28      this.responseVisible = entries.some((entry) => this.responseEntryIsVisible(entry))
29      this.acknowledgeIfVisible()
30    }, { threshold: this.requiredVisibleRatio() })
31    this.observer.observe(this.element)
32    this.acknowledgeIfVisible()
33  }
34
35  disconnect() {
36    document.removeEventListener("visibilitychange", this.visibilityChanged)
37    this.observer?.disconnect()
38    this.clearRetryTimer()
39  }
40
41  acknowledgeIfVisible() {
42    if (this.viewedValue || this.markingViewed || document.hidden || !this.responseVisible) return
43    if (!this.hasViewedUrlValue || !this.hasKindValue || !this.hasVersionValue) return
44
45    const csrfToken = document.querySelector("meta[name='csrf-token']")?.content
46    const headers = { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" }
47    if (csrfToken) headers["X-CSRF-Token"] = csrfToken
48
49    this.clearRetryTimer()
50    this.markingViewed = true
51    fetch(this.viewedUrlValue, {
52      method: "PATCH",
53      credentials: "same-origin",
54      headers,
55      body: new URLSearchParams({ kind: this.kindValue, version: this.versionValue }),
56    }).then((response) => {
57      if (!response.ok) throw new Error("Website request response acknowledgement failed")
58
59      this.viewedValue = true
60    }).catch(() => {
61      this.retryTimer = window.setTimeout(() => this.acknowledgeIfVisible(), 15000)
62    }).finally(() => {
63      this.markingViewed = false
64    })
65  }
66
67  responseIsInViewport() {
68    const bounds = this.element.getBoundingClientRect()
69    if (bounds.width <= 0 || bounds.height <= 0) return false
70
71    const visibleHeight = Math.min(bounds.bottom, window.innerHeight) - Math.max(bounds.top, 0)
72    const visibleWidth = Math.min(bounds.right, window.innerWidth) - Math.max(bounds.left, 0)
73    return visibleHeight >= this.requiredVisibleHeight(bounds.height) && visibleWidth > 0
74  }
75
76  responseEntryIsVisible(entry) {
77    return entry.isIntersecting &&
78      entry.intersectionRect.height >= this.requiredVisibleHeight(entry.boundingClientRect.height) &&
79      entry.intersectionRect.width > 0
80  }
81
82  requiredVisibleRatio() {
83    const height = this.element.getBoundingClientRect().height
84    return height > 0 ? this.requiredVisibleHeight(height) / height : 0.15
85  }
86
87  requiredVisibleHeight(height) {
88    return Math.min(height * 0.15, MAX_REQUIRED_VISIBLE_HEIGHT)
89  }
90
91  clearRetryTimer() {
92    if (!this.retryTimer) return
93
94    window.clearTimeout(this.retryTimer)
95    this.retryTimer = null
96  }
97}

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.