1document.addEventListener("DOMContentLoaded", () => { 2 /*ââââââââââââââ CONFIG ââââââââââââââ*/ 3 const WEBHOOK = 4 "https://n8n.xmatica.ai/webhook/f505c057-6040-4cad-9652-4f7be4ffd8d4/chat"; 5 6 /*ââââââââââââââ SESIÃN ââââââââââââââ*/ 7 const getSessionId = () => { 8 let sid = localStorage.getItem("chatSessionId"); 9 if (!sid) { 10 sid = `session-${Date.now()}`; 11 localStorage.setItem("chatSessionId", sid); 12 } 13 return sid; 14 }; 15 16 /*ââââââââââ CARGA RECURSOS ââââââââââ*/ 17 const fa = document.createElement("link"); 18 fa.rel = "stylesheet"; 19 fa.href = 20 "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"; 21 document.head.appendChild(fa); 22 23 const css = document.createElement("style"); 24 css.textContent = ` 25 /* Botón flotante */ 26 #chatbot-button{ 27 position:fixed!important; 28 bottom:20px; 29 right:20px; 30 width:60px; 31 height:60px; 32 background:#007BFF; 33 color:#fff; 34 border-radius:50%; 35 display:flex; 36 align-items:center; 37 justify-content:center; 38 box-shadow:0 4px 10px rgba(0,0,0,.3); 39 cursor:pointer; 40 transition:transform .2s ease-in-out; 41 z-index:9999; 42 } 43 #chatbot-button:hover{transform:scale(1.1);} 44 #chatbot-button i{font-size:24px;} 45 46 /* Ventana de chat */ 47 #chat-container{ 48 position:fixed!important; 49 bottom:90px; 50 right:20px; 51 width:350px; 52 max-width:90%; 53 height:500px; 54 background:#fff; 55 border-radius:10px; 56 box-shadow:0 8px 15px rgba(0,0,0,.3); 57 display:none; 58 flex-direction:column; 59 z-index:9998; 60 resize:both; 61 overflow:hidden; 62 } 63 64 /* Encabezado */ 65 #chat-header{ 66 background:#007BFF; 67 color:#fff; 68 padding:10px; 69 border-top-left-radius:10px; 70 border-top-right-radius:10px; 71 font-size:16px; 72 font-weight:bold; 73 display:flex; 74 justify-content:space-between; 75 align-items:center; 76 cursor:move; 77 } 78 #maximize-button{background:none;border:none;color:#fff;font-size:16px;cursor:pointer;} 79 80 /* Ãrea de mensajes */ 81 #messages{ 82 flex-grow:1; 83 overflow-y:auto; 84 padding:10px; 85 background:#f9f9f9; 86 border-radius:0 0 10px 10px; 87 } 88 .message{margin-bottom:10px;display:flex;align-items:flex-start;} 89 .message.user{justify-content:flex-end;} 90 .message.bot{justify-content:flex-start;} 91 .bubble{ 92 max-width:70%; 93 padding:12px; 94 border-radius:20px; 95 font-size:14px; 96 line-height:1.5; 97 } 98 .message.bot .bubble{background:#f1f0f0;color:#333;border-radius:20px 20px 20px 0;} 99 .message.user .bubble{background:#007BFF;color:#fff;border-radius:20px 20px 0 20px;} 100 101 .icon{width:30px;height:30px;margin:0 10px;display:flex;align-items:center;justify-content:center;} 102 .message.bot .icon i, 103 .message.user .icon i{font-size:20px;color:#007BFF;} 104 105 /* Input */ 106 #input-container{display:flex;padding:10px;border-top:1px solid #ddd;background:#fff;} 107 #message-input{flex:1;padding:10px;border:1px solid #ddd;border-radius:5px;} 108 #send-button{margin-left:10px;padding:10px 20px;background:#007BFF;color:#fff;border:none;border-radius:5px;cursor:pointer;} 109 #send-button:hover{background:#0056b3;} 110 111 /* Indicador âescribiendoâ */ 112 .typing-indicator{display:flex;align-items:center;margin-top:5px;} 113 .dot{ 114 width:8px;height:8px;margin:0 3px; 115 background:gray;border-radius:50%; 116 animation:typing 1.5s infinite; 117 } 118 .dot:nth-child(2){animation-delay:.3s;} 119 .dot:nth-child(3){animation-delay:.6s;} 120 @keyframes typing{0%,100%{opacity:.2;}50%{opacity:1;}} 121 `; 122 document.head.appendChild(css); 123 124 /*ââââââââââ CREAR ELEMENTOS âââââââââ*/ 125 const btn = document.createElement("div"); 126 btn.id = "chatbot-button"; 127 btn.innerHTML = '<i class="fa-solid fa-robot"></i>'; 128 document.body.appendChild(btn); 129 130 const chat = document.createElement("div"); 131 chat.id = "chat-container"; 132 chat.innerHTML = ` 133 <div id="chat-header"> 134 Chatbot 135 <button id="maximize-button"><i class="fa-solid fa-expand"></i></button> 136 </div> 137 <div id="messages"></div> 138 <div id="input-container"> 139 <input id="message-input" type="text" placeholder="Escribe tu mensaje..." autocomplete="off"> 140 <button id="send-button">Enviar</button> 141 </div>`; 142 document.body.appendChild(chat); 143 144 /*ââââââââââââ MOSTRAR/OCULTAR âââââââ*/ 145 btn.onclick = () => { 146 chat.style.display = chat.style.display === "flex" ? "none" : "flex"; 147 }; 148 149 let maximized = false;
150 document.getElementById("maximize-button").onclick = (e) => { 151 const nav = document.querySelector("nav"); 152 maximized = !maximized; 153 if (maximized) { 154 chat.style.cssText = 155 "display:flex;width:calc(100% - 20px);height:calc(100% - 40px);bottom:20px;right:20px;border-radius:10px;resize:none"; 156 btn.style.display = "none"; 157 if (nav) nav.style.display = "none"; 158 e.target.innerHTML = '<i class="fa-solid fa-compress"></i>'; 159 } else { 160 chat.style.cssText = 161 "display:flex;width:350px;height:500px;bottom:90px;right:20px;resize:both"; 162 btn.style.display = "flex"; 163 if (nav) nav.style.display = "flex"; 164 e.target.innerHTML = '<i class="fa-solid fa-expand"></i>'; 165 } 166 }; 167 168 /*ââââââââââ FUNCIONES AUX âââââââââââ*/ 169 const msgDiv = () => document.getElementById("messages"); 170 171 const appendTyping = () => { 172 const div = document.createElement("div"); 173 div.className = "message bot"; 174 div.innerHTML = ` 175 <div class="icon"><i class="fa-solid fa-robot"></i></div> 176 <div class="bubble"><div class="typing-indicator"> 177 <span class="dot"></span><span class="dot"></span><span class="dot"></span> 178 </div></div>`; 179 msgDiv().appendChild(div); 180 msgDiv().scrollTop = msgDiv().scrollHeight; 181 return div.querySelector(".bubble"); 182 }; 183 184 const sendReq = async (text) => { 185 const res = await fetch(WEBHOOK, { 186 method: "POST", 187 headers: { "Content-Type": "application/json" }, 188 body: JSON.stringify({ 189 message: text, 190 sessionId: getSessionId(), 191 origen: "chatweb", 192 }), 193 }); 194 return res.json(); 195 }; 196 197 const sendUserMsg = async (text) => { 198 const ud = document.createElement("div"); 199 ud.className = "message user"; 200 ud.innerHTML = `<div class="bubble">${text}</div><div class="icon"><i class="fa-solid fa-user"></i></div>`; 201 msgDiv().appendChild(ud); 202 203 const bub = appendTyping(); 204 try { 205 const data = await sendReq(text); 206 bub.innerHTML = (data.response || "Sin respuesta.").replace( 207 /\n/g, 208 "<br>" 209 ); 210 } catch { 211 bub.textContent = "Error al conectar."; 212 } 213 msgDiv().scrollTop = msgDiv().scrollHeight; 214 }; 215 216 const sendHidden = async (text) => { 217 const bub = appendTyping(); 218 try { 219 const data = await sendReq(text); 220 bub.innerHTML = (data.response || "Sin respuesta.").replace( 221 /\n/g, 222 "<br>" 223 ); 224 } catch { 225 bub.textContent = "Error al conectar."; 226 } 227 }; 228 229 /*âââââââââ EVENTOS MENSAJE ââââââââââ*/ 230 document.body.addEventListener("click", (e) => { 231 if (e.target.id === "send-button") { 232 const inp = document.getElementById("message-input"); 233 const val = inp.value.trim(); 234 if (val) { 235 inp.value = ""; 236 sendUserMsg(val); 237 } 238 } 239 }); 240 document.body.addEventListener("keypress", (e) => { 241 if (e.key === "Enter") { 242 const inp = document.getElementById("message-input"); 243 const val = inp.value.trim(); 244 if (val) { 245 inp.value = ""; 246 sendUserMsg(val); 247 } 248 } 249 }); 250 251 /*âââââ FORMULARIO FOOTER â BOT âââââ*/ 252 document.body.addEventListener("click", async (e) => { 253 if (e.target.id !== "contact-submit") return; 254 e.preventDefault(); 255 const n = document.getElementById("contact-name")?.value.trim(); 256 const m = document.getElementById("contact-email")?.value.trim(); 257 if (!n || !m) { 258 alert("Completá nombre y correo."); 259 return; 260 } 261 chat.style.display = "flex"; // abre chat 262 await sendHidden( 263 `Me conecte por la web de xmatica, quisiera saber de que se trata los servicios de uds: Nombre=${n}, Email=${m}` 264 ); 265 document.getElementById("contact-name").value = ""; 266 document.getElementById("contact-email").value = ""; 267 }); 268 269 /*âââââââââ AUTOOPEN opcional ââââââââ*/ 270 if (new URLSearchParams(location.search).get("autoOpen") === "true") { 271 chat.style.display = "flex"; 272 sendHidden("Hola, vine de la invitación en redes y quiero ver la demo."); 273 } 274 275 console.log("ð Chatbot JS cargado"); 276});
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.