NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @namespace http://openuserjs.org/users/Francute // @name Kongregate - AutoCompletar nombres // @description En el chat de la página, simplemente escribir parte de un nombre de usuario y autocompletar con Tab. Shif + Tab para volver a la recomendación anterior. // @copyright Francute // @license MIT // @version 0.15 // @include http://www.kongregate.com/games/*/* // ==/UserScript== // ==OpenUserJS== // @author Francute // ==/OpenUserJS== (function() { 'use strict'; class Chat { constructor(selectorContenedorDelChat, selectorContenedorDeNodosUsuarios, selectorTextArea) { this.pestanasChat = []; this.nodoContenedorDeChats = document.querySelector(selectorContenedorDelChat); this.selectorContenedorDeUsuarios = selectorContenedorDeNodosUsuarios; this.selectorEntrada = selectorTextArea; this.cargarPestanas(); } cargarPestanas() { let self = this; new MutationObserver(function(mutaciones) { mutaciones.forEach(function(mutacion) { if (seAgregaronChats(mutacion)) { mutacion.addedNodes.forEach(nodoChatNuevo => this.cargarNuevaPestana(nodoChatNuevo)); } else if (seRemovieronChats(mutacion)) { mutacion.removedNodes.forEach(nodoChatEliminado => this.eliminarPestana(nodoChatEliminado)); } }, self); }).observe(this.nodoContenedorDeChats, { childList: true }); function seAgregaronChats(mutacion) { return mutacion.addedNodes.length > 0; } function seRemovieronChats(mutacion) { return mutacion.removedNodes.length > 0; } } cargarNuevaPestana(nodoChat) { this.pestanasChat.push(new ComponentePestana(nodoChat, this.selectorContenedorDeUsuarios, this.selectorEntrada)); } eliminarPestana(nodoChat) { let indicePestanaEncontrada; let seEncontroPestana = this.pestanasChat.some(function(pestana, indice) { indicePestanaEncontrada = indice; return pestana.nodoChat == nodoChat; }); if (seEncontroPestana) { this.pestanasChat.splice(indicePestanaEncontrada, 1); } } cargarPestanasChats(selectorContenedorDeNodosUsuarios, selectorTextArea) { this.pestanasChat = []; Array.from(this.nodoContenedorDeChats.children) .forEach(nodoChat => this.pestanasChat.push(new ComponentePestana(nodoChat, selectorContenedorDeNodosUsuarios, selectorTextArea))); } } class ComponentePestana { constructor(nodo, selectorContenedorDeNodosUsuarios, selectorTextArea) { this.nodoChat = nodo; this.usuarios = new ComponenteUsuarios(nodo.querySelector(selectorContenedorDeNodosUsuarios)); this.nodoEntrada = new ComponenteEntrada(this.usuarios, nodo.querySelector(selectorTextArea)); } } class ComponenteUsuarios { constructor(nodoUsuarios) { this.posiblesUsuarios = []; this.posicionUsuarioActual = -1; this.nodoUsuarios = nodoUsuarios; this.actualizarListaDeUsuarios(); } actualizarListaDeUsuarios() { this.usuarios = Array.from(this.nodoUsuarios.querySelectorAll("span > span.username")) .map(nodo => nodo.innerHTML) .sort((a, b) => (a.toLowerCase() > b.toLowerCase()) ? 1 : -1); } buscarPosiblesUsuarios(parteDelNombre) { this.actualizarListaDeUsuarios(); this.posiblesUsuarios = this.usuarios.filter(usuario => usuario.search(new RegExp(parteDelNombre + "\\w*$", "i")) === 0) .sort((a, b) => (a.toLowerCase() > b.toLowerCase()) ? 1 : -1); this.posicionUsuarioActual = -1; return this.posiblesUsuarios; } esUnUsuarioYaDevuelto(nombreUsuario) { return (this.posiblesUsuarios.indexOf(nombreUsuario) != -1); } existenUsuariosQueConcuerdenCon(parteDelNombreDeUsuario) { return this.buscarPosiblesUsuarios(parteDelNombreDeUsuario).length > 0; } siguiente() { return this.posiblesUsuarios[(++this.posicionUsuarioActual) % this.posiblesUsuarios.length]; } anterior() { if (this.posicionUsuarioActual <= 0) { this.posicionUsuarioActual = this.posiblesUsuarios.length; } return this.posiblesUsuarios[--this.posicionUsuarioActual % this.posiblesUsuarios.length]; } finalizarBusqueda() { if (this.posiblesUsuarios.length > 0) this.posiblesUsuarios = []; } } class ComponenteEntrada { constructor(usuarios, nodoEntrada) { this.usuarios = usuarios; this.entrada = nodoEntrada; this.separador = " "; this.activarEventos(); } activarEventos() { /* Bugs pronosticados: Escenario 1: Busco por un usuario cuyo nombre comience con "la", y encuentra a "ladillaFeliz" y "LaEraWakeista". Se conecta un usuario "laxvio". Si continúo haciendo Tab sin buscar de nuevo, no podré encontrar a "laxvio". -¿Posible solución? Dejar Kong. Escenario 2: Busco un usuario que justo se desconectó, no lo voy a poder encontrar. ¿Será un bug realmente? Escenario 3: Busco por un usuario cuyo nombre comience con "la", y encuentra a "ladillaFeliz" y "laxvio". Selecciono alguno de los 2 y sigo escribiendo en el chat con normalidad. Escribo luego "laxvio" y al tocar Tab debería cambiarla por "ladillaFeliz". - Se puede resolver fácil actualizando cuando toque algo diferente de Shift o Tab, pero... Doy posibilidades a bugs que se desprenden de este? */ this.entrada.addEventListener("keydown", function(evento) { if (evento.code === 'Tab') { evento.preventDefault(); if (this.usuarios.esUnUsuarioYaDevuelto(this.traerUltimaPalabra())) { this.borrarUltimaPalabra(); if (seEstaPresionandoLaTeclaShift()) { this.agregarAlMensaje(this.usuarios.anterior()); } else { this.agregarAlMensaje(this.usuarios.siguiente()); } } else { if (this.usuarios.existenUsuariosQueConcuerdenCon(this.traerUltimaPalabra())) { this.borrarUltimaPalabra(); this.agregarAlMensaje(this.usuarios.siguiente()); } } } function seEstaPresionandoLaTeclaShift() { return evento.shiftKey; } }.bind(this)); } traerPalabrasActualmenteIngresadas() { this.modeloTextArea = this.entrada.value.trim().split(this.separador); return this.modeloTextArea; } traerUltimaPalabra() { let palabrasIngresadas = this.traerPalabrasActualmenteIngresadas(); return palabrasIngresadas[palabrasIngresadas.length - 1]; } borrarUltimaPalabra() { this.modeloTextArea.pop(); } agregarAlMensaje(texto) { this.entrada.value = ( this.modeloTextArea.join(this.separador) + this.separador + texto ).trim(); } } document.observe('holodeck:ready', function() { new Chat("#chat_rooms_container", ".users_in_room", ".chat_input"); }); })();