PageSourceSearch

https://www.designeroutletwarszawa.pl/_assets/6a101b282a6a03d13b1a…/modules/flying_focus.js?1791189229

js designeroutletwarszawa.pl collected 2026-10-08 02:50:37 UTC 4,959 bytes, 193 lines download raw bytes

1// thanks to https://codepen.io/Martins-shenanigans/pen/qEbzPVq
2(() => {
3  const DURATION = 150;
4
5  if (document.getElementById("FlyingFocus")) return;
6
7  const flyingFocus = document.createElement("div");
8  flyingFocus.id = "FlyingFocus";
9  document.body.appendChild(flyingFocus);
10
11  let staticCounter;
12  let hidden = true;
13  let keydownTime = 0;
14  let prevFocused = null;
15  let prevOffset = {};
16  let focusTimeout;
17  let hideTimeout;
18  let positionTimeout;
19
20  const alwaysFocus = (target) => {
21    // Konfigurierbar: bei Bedarf anpassen
22    return false;
23  };
24
25  const getBounds = (elem) => {
26    const rect = elem.getBoundingClientRect();
27    const docElem = document.documentElement;
28    const win = window;
29    const body = document.body;
30
31    const scrollTop = win.pageYOffset || docElem.scrollTop || body.scrollTop;
32    const scrollLeft = win.pageXOffset || docElem.scrollLeft || body.scrollLeft;
33    const clientTop = docElem.clientTop || body.clientTop || 0;
34    const clientLeft = docElem.clientLeft || body.clientLeft || 0;
35
36    const top = rect.top + scrollTop - clientTop;
37    const left = rect.left + scrollLeft - clientLeft;
38
39    return {
40      top,
41      left,
42      width: rect.width,
43      height: rect.height,
44      bottom: top + rect.height,
45      right: left + rect.width,
46    };
47  };
48
49  const getInputBounds = (element) => {
50    const elements = [element];
51    const id = element.getAttribute("id");
52    const labels = id
53      ? Array.from(
54        document.querySelectorAll(`label[for="${id}"]:not(.visuallyhidden)`)
55      )
56      : [];
57
58    elements.push(...labels);
59
60    const bounds = {
61      top: Infinity,
62      left: Infinity,
63      bottom: -Infinity,
64      right: -Infinity,
65    };
66
67    for (const el of elements) {
68      const b = getBounds(el);
69      bounds.top = Math.min(bounds.top, b.top);
70      bounds.left = Math.min(bounds.left, b.left);
71      bounds.bottom = Math.max(bounds.bottom, b.bottom);
72      bounds.right = Math.max(bounds.right, b.right);
73    }
74
75    bounds.width = bounds.right - bounds.left;
76    bounds.height = bounds.bottom - bounds.top;
77
78    return bounds;
79  };
80
81  const reposition = (target) => {
82    if (!target || hidden) return;
83
84    const offset = getInputBounds(target);
85
86    if (
87      offset.top !== prevOffset.top ||
88      offset.left !== prevOffset.left ||
89      offset.width !== prevOffset.width ||
90      offset.height !== prevOffset.height
91    ) {
92      flyingFocus.style.left = `${offset.left}px`;
93      flyingFocus.style.top = `${offset.top}px`;
94      flyingFocus.style.width = `${offset.width}px`;
95      flyingFocus.style.height = `${offset.height}px`;
96    }
97
98    return offset;
99  };
100
101  const show = () => {
102    clearTimeout(hideTimeout);
103    clearTimeout(positionTimeout);
104
105    flyingFocus.style.transitionDuration = hidden
106      ? "0s"
107      : `${DURATION / 1000}s`;
108
109    staticCounter = 0;
110    positionTimeout = setTimeout(checkPosition, 100);
111
112    if (hidden) {
113      flyingFocus.classList.add("FlyingFocus-visible");
114      hidden = false;
115    }
116  };
117
118  const hide = () => {
119    if (!hidden) {
120      clearTimeout(focusTimeout);
121      clearTimeout(hideTimeout);
122      hideTimeout = setTimeout(hideReally, 10);
123    }
124  };
125
126  const hideReally = () => {
127    flyingFocus.classList.remove("FlyingFocus-visible");
128    hidden = true;
129    clearTimeout(positionTimeout);
130  };
131
132  const checkPosition = () => {
133    const offset = reposition(prevFocused);
134    if (
135      offset.top !== prevOffset.top ||
136      offset.left !== prevOffset.left ||
137      offset.width !== prevOffset.width ||
138      offset.height !== prevOffset.height
139    ) {
140      prevOffset = offset;
141      staticCounter = 0;
142    } else {
143      staticCounter++;
144    }
145
146    positionTimeout = setTimeout(checkPosition, staticCounter < 3 ? 100 : 1000);
147  };
148
149  document.documentElement.addEventListener(
150    "keydown",
151    (event) => {
152      if (event.keyCode < 65) {
153        keydownTime = new Date();
154        document.body.classList.add("user-is-tabbing");
155      }
156    },
157    true
158  );
159
160  document.addEventListener("focusin", (event) => {
161    focusTimeout = setTimeout(() => {
162      const override = alwaysFocus(event.target);
163      if (!override) {
164        const focusTime = new Date();
165        if (hidden && focusTime - keydownTime > 100) {
166          return;
167        }
168      }
169
170      show();
171      prevOffset = reposition(event.target);
172      prevFocused = event.target;
173    }, 1);
174  });
175
176  document.addEventListener("focusout", hide);
177
178  document.documentElement.addEventListener("mousedown", (event) => {
179    document.body.classList.remove("user-is-tabbing");
180    if (!alwaysFocus(event.target) && event.detail) {
181      hideReally();
182    }
183  });
184
185  document.documentElement.addEventListener("touchstart", (event) => {
186    document.body.classList.remove("user-is-tabbing");
187    if (!alwaysFocus(event.target) && event.detail) {
188      hideReally();
189    }
190  });
191
192  window.addEventListener("resize", () => reposition(prevFocused));
193})();

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.