Files
ByteCenter/public/js/chatbot.js
T
2026-08-04 19:45:50 -03:00

227 lines
4.7 KiB
JavaScript

/*
EVENTO: DOMContentLoaded
Se ejecuta cuando el HTML termina de cargarse
Esto asegura que todos los elementos del DOM existan antes de intentar utilizarlos desde JavaScript
*/
document.addEventListener("DOMContentLoaded", () => {
/*
REFERENCIAS DEL DOM
Obtenemos:
- form -> formulario del chat
- input -> input donde escribe el usuario
- chatBox -> contenedor de mensajes
*/
const form = document.getElementById("chat-form");
const input = document.getElementById("mensaje");
const chatBox = document.getElementById("chat-box");
// Se detiene el script si no existe algún elemento
if (!form || !input || !chatBox) return;
// EVENTO SUBMIT -> se ejecuta cuando el usuario envía el formulario
form.addEventListener("submit", async (e) => {
// PREVENIR RECARGA -> Evita que el formulario recargue la página
e.preventDefault();
// OBTENER MENSAJE
const mensaje = input.value.trim();
// VALIDAR MENSAJE
if (!mensaje) return;
// MOSTRAR MENSAJE DEL USUARIO -> Se agrega inmediatamente al chat
agregarMensaje("user", mensaje);
// LIMPIAR INPUT
input.value = "";
// MOSTRAR TYPING (ESCRIBIENDO...)
mostrarTyping();
try {
/*
FETCH AJAX
Realizamos una petición POST hacia chatbot.php
*/
const response = await fetch(
window.location.origin + "/ajax/chatbot.php",
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
/*
BODY
encodeURIComponent():
- Escapa caracteres especiales
*/
body:
"mensaje=" + encodeURIComponent(mensaje)
}
);
// ELIMINAR TYPING
removerTyping();
// CONVERTIR RESPUESTA JSON
const data = await response.json();
// ERROR BACKEND -> success === false
if (!data.success) {
console.error(data.error);
agregarMensaje(
"bot",
"Ocurrió un error al procesar la consulta."
);
return;
}
// RESPUESTA IA
agregarMensaje(
"bot",
data.respuesta
);
} catch (error) {
// ERROR FETCH / CONEXIÓN
removerTyping();
console.error(error);
agregarMensaje(
"bot",
"Error de conexión."
);
}
});
// Evita inyección HTML/XSS
function escaparHTML(texto)
{
return texto
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// AGREGAR MENSAJE VISUAL AL CHAT -> tipo: user / bot
function agregarMensaje(tipo, texto)
{
// CREAR DIV
const div = document.createElement("div");
// CLASE CSS
div.className =
tipo === "user" ? "mensaje-user" : "mensaje-bot";
div.innerHTML = `
<div class="mensaje-contenido">
${escaparHTML(texto).replace(/\n/g, "<br>")}
</div>
`;
// INSERTAR MENSAJE
chatBox.appendChild(div);
// AUTO SCROLL
scrollBottom();
}
// MOSTRAR TYPING
function mostrarTyping()
{
const div = document.createElement("div");
div.id = "typing";
div.className = "mensaje-bot";
div.innerHTML = `
<div class="mensaje-contenido">
Escribiendo...
</div>
`;
chatBox.appendChild(div);
scrollBottom();
}
// ELIMINAR TYPING
function removerTyping()
{
const typing = document.getElementById("typing");
if (typing) {
typing.remove();
}
}
// AUTO SCROLL -> Baja automáticamente el scroll del chat
function scrollBottom()
{
chatBox.scrollTop = chatBox.scrollHeight;
}
});
/*
EVENTO: load
Se ejecuta cuando toda la página termina de cargar:
HTML + CSS + imágenes + recursos
Se usa para restaurar el scroll abajo al refrescar la página
*/
window.addEventListener("load", () => {
const chatBox = document.getElementById("chat-box");
if (chatBox) {
chatBox.scrollTop = chatBox.scrollHeight;
}
});