PageSourceSearch

https://donadigital.cat/wp-content/plugins/chatbot-plugin/assets/js/chatbot-ui.js?ver=1.0

js donadigital.cat collected 2026-09-30 08:28:25 UTC 5,200 bytes, 137 lines download raw bytes

1// /chatbot-plugin/assets/js/chatbot-ui.js
2
3document.addEventListener("DOMContentLoaded", () => {
4  const botoToggle = document.getElementById("laia-boto-toggle");
5  const contenidorChat = document.getElementById("laia-chatbot-fullscreen");
6
7  if (botoToggle && contenidorChat) {
8    botoToggle.addEventListener("click", () => {
9      const esObert = !contenidorChat.classList.contains("ocult");
10      if (esObert) {
11        contenidorChat.classList.add("ocult");
12        botoToggle.textContent = "💬";
13      } else {
14        contenidorChat.classList.remove("ocult");
15        botoToggle.textContent = "✖";
16
17        // Col·loca ABAIX-DRETA només el primer cop que s'obre
18        if (contenidorChat.classList.contains("popup")) {
19          placeInitiallyAtBottomRight(contenidorChat, { marginRight: 20, marginBottom: 80 });
20        }
21        clampToViewport(contenidorChat);
22      }
23    });
24  }
25
26  // Drag/resize només en mode popup
27  if (typeof interact !== "undefined" && contenidorChat && contenidorChat.classList.contains("popup")) {
28    contenidorChat.dataset.x = contenidorChat.dataset.x || "0";
29    contenidorChat.dataset.y = contenidorChat.dataset.y || "0";
30
31    // DRAG només pel header
32    interact("#laia-chatbot-fullscreen").draggable({
33      allowFrom: "#laia-header",
34      ignoreFrom: "#laia-box, #laia-form, #laia-voice-interface",
35      listeners: {
36        move(event) {
37          const target = event.target;
38          let x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx;
39          let y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;
40
41          const rect = target.getBoundingClientRect();
42          const maxX = window.innerWidth - rect.width;
43          const maxY = window.innerHeight - rect.height;
44          x = Math.min(Math.max(0, x), Math.max(0, maxX));
45          y = Math.min(Math.max(0, y), Math.max(0, maxY));
46
47          target.style.transform = `translate(${x}px, ${y}px)`;
48          target.setAttribute("data-x", String(x));
49          target.setAttribute("data-y", String(y));
50        },
51      },
52    });
53
54    // RESIZE per totes les vores (ajusta x/y si s’estira per dalt/esquerra)
55    interact("#laia-chatbot-fullscreen").resizable({
56      edges: { left: true, right: true, bottom: true, top: true },
57      listeners: {
58        move(event) {
59          const target = event.target;
60          let x = parseFloat(target.getAttribute("data-x")) || 0;
61          let y = parseFloat(target.getAttribute("data-y")) || 0;
62
63          const reqW = Math.round(event.rect.width);
64          const reqH = Math.round(event.rect.height);
65
66          const minW = 320;
67          const minH = 360;
68
69          const maxW = Math.min(reqW, window.innerWidth - 16 - x);
70          const maxH = Math.min(reqH, window.innerHeight - 16 - y);
71
72          const finalW = Math.max(minW, Math.min(maxW, reqW));
73          const finalH = Math.max(minH, Math.min(maxH, reqH));
74
75          target.style.width = `${finalW}px`;
76          target.style.height = `${finalH}px`;
77
78          if (event.deltaRect) {
79            x += event.deltaRect.left || 0;
80            y += event.deltaRect.top || 0;
81          }
82
83          const rect = target.getBoundingClientRect();
84          const maxX = Math.max(0, window.innerWidth - rect.width);
85          const maxY = Math.max(0, window.innerHeight - rect.height);
86          if (x < 0) x = 0;
87          if (y < 0) y = 0;
88          if (x > maxX) x = maxX;
89          if (y > maxY) y = maxY;
90
91          target.style.transform = `translate(${x}px, ${y}px)`;
92          target.setAttribute("data-x", String(x));
93          target.setAttribute("data-y", String(y));
94        },
95      },
96    });
97
98    window.addEventListener("resize", () => clampToViewport(contenidorChat));
99  }
100
101  function clampToViewport(el) {
102    let x = parseFloat(el.getAttribute("data-x")) || 0;
103    let y = parseFloat(el.getAttribute("data-y")) || 0;
104    const rect = el.getBoundingClientRect();
105
106    const maxX = Math.max(0, window.innerWidth - rect.width);
107    const maxY = Math.max(0, window.innerHeight - rect.height);
108
109    if (x > maxX) x = maxX;
110    if (y > maxY) y = maxY;
111    if (x < 0) x = 0;
112    if (y < 0) y = 0;
113
114    el.style.transform = `translate(${x}px, ${y}px)`;
115    el.setAttribute("data-x", String(x));
116    el.setAttribute("data-y", String(y));
117  }
118
119  // Abans tenies bottom/right: calculem el translate perquè surti ABAIX-DRETA igual
120  function placeInitiallyAtBottomRight(el, { marginRight = 20, marginBottom = 80 } = {}) {
121    if (el.dataset.posInit === "1") return;
122    const rect = el.getBoundingClientRect();
123    const cs = getComputedStyle(el);
124    const leftCSS = parseFloat(cs.left || "0");
125    const topCSS  = parseFloat(cs.top || "0");
126
127    let x = window.innerWidth  - rect.width  - marginRight - leftCSS;
128    let y = window.innerHeight - rect.height - marginBottom - topCSS;
129    if (x < 0) x = 0;
130    if (y < 0) y = 0;
131
132    el.style.transform = `translate(${x}px, ${y}px)`;
133    el.setAttribute("data-x", String(x));
134    el.setAttribute("data-y", String(y));
135    el.dataset.posInit = "1";
136  }
137});

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.