En aquest article et mostre com fem el control del número de paraules en el Mantis per a evitar que els usuaris no envien peticions sense descriure bé el seu problema.
Al Mantis Bug Tracker, de vegades, rebem peticions que no entenem o on els usuaris no han descrit exacatment el seu problema, i això ens fa perdre temps perquè ens obligar a telefonar o escriure a l'usuari per a demanar-li més informació.
Doncs bé, amb aquest script de Javascript fem un compte del número de paraules que els usuaris escriuen en el camp de descripció i si escriuen menys de 8 paraules, els apareix un missatge 'alert' de Javascript en el navegador informant-los que han escrit molt poc i els impedeix enviar la petició si no escriuen més paraules:
Ací es mostra el missatge alert informant-los de que han escrit molt poques paraules:
I finalment, si l'usuari escriu més paraules, ja se li mostra el compte en color verd i ja podran enviar la petició:
Haurem d'afegir an fitxer /bug_report_page.php del teu projecte mantis afegint:
El codi de l'script és el següent:
< !-- Script per a comptar paraules en la descripció de les peticions -->
< script type="text/javascript" src="validarParaules.js">< /script>
El codi de l'script javascript és el següent:
// Función para contar palabras mejorada
function contarParaules(texto) {
if (!texto || texto.trim() === '') {
return 0;
}
// Limpiar el texto: eliminar espacios múltiples, saltos de línea, etc.
var textoLimpio = texto.trim()
.replace(/\s+/g, ' ') // Reemplazar múltiples espacios por uno
.replace(/[\r\n]+/g, ' ') // Reemplazar saltos de línea por espacios
.replace(/^\s+|\s+$/g, ''); // Eliminar espacios al inicio y final
if (textoLimpio === '') {
return 0;
}
// Dividir por espacios y contar
var palabras = textoLimpio.split(' ');
// Filtrar palabras vacías (por si acaso)
palabras = palabras.filter(function(palabra) {
return palabra.length > 0;
});
return palabras.length;
}
// Función principal de validación
function validarParaules() {
console.log('Validant paraules...');
// Buscar el textarea de descripción principal
// En Mantis, el campo de descripción suele ser el más grande o tener name="bugnote_text" o "description"
var textareas = document.querySelectorAll('textarea');
var textareaPrincipal = null;
// Buscar el textarea más probable (el más grande o con ciertas características)
textareas.forEach(function(textarea) {
// Priorizar textareas grandes (más de 5 filas)
if (textarea.rows > 5 || textarea.cols > 50) {
textareaPrincipal = textarea;
}
// Si tiene un nombre específico, es definitivamente el principal
if (textarea.name && (textarea.name.includes('description') ||
textarea.name.includes('bugnote') ||
textarea.name.includes('text'))) {
textareaPrincipal = textarea;
}
});
// Si no encontramos uno específico, tomar el primer textarea grande
if (!textareaPrincipal && textareas.length > 0) {
textareaPrincipal = textareas[0];
}
if (!textareaPrincipal) {
console.error('No s\'ha trobat cap textarea');
return true; // Permitir envío si no hay textarea
}
console.log('Textarea trobat:', textareaPrincipal);
var texto = textareaPrincipal.value;
var numParaules = contarParaules(texto);
console.log('Text introduït:', texto.substring(0, 50) + '...');
console.log('Paraules comptades:', numParaules);
if (numParaules < 8) {
alert('Hola, \n\nhem detectat que has escrit molt poques paraules (concretament ' + numParaules + ') en el camp descriptiu.\n\n Escriu almenys 8 paraules per tal de descriure correctament el problema que vols reportar.');
// Enfocar el textarea
textareaPrincipal.focus();
// Resaltar temporalmente
textareaPrincipal.style.border = '2px solid red';
textareaPrincipal.style.boxShadow = '0 0 5px red';
setTimeout(function() {
textareaPrincipal.style.border = '';
textareaPrincipal.style.boxShadow = '';
}, 3000);
return false; // Prevenir el envío del formulario
}
return true; // Permitir el envío
}
// Función para añadir contador en tiempo real
function afegirContador() {
var textareas = document.querySelectorAll('textarea');
var textareaPrincipal = null;
// Buscar el textarea principal (misma lógica que antes)
textareas.forEach(function(textarea) {
if (textarea.rows > 5 || textarea.cols > 50) {
textareaPrincipal = textarea;
}
if (textarea.name && textarea.name.includes('description')) {
textareaPrincipal = textarea;
}
});
if (!textareaPrincipal && textareas.length > 0) {
textareaPrincipal = textareas[0];
}
if (!textareaPrincipal) {
console.log('No s\'ha trobat textarea per al contador');
return;
}
// Crear elemento para el contador
var contadorDiv = document.createElement('div');
contadorDiv.id = 'contador-paraules';
contadorDiv.style.marginTop = '5px';
contadorDiv.style.fontSize = '12px';
contadorDiv.style.color = '#666';
contadorDiv.style.padding = '3px 8px';
contadorDiv.style.backgroundColor = '#f5f5f5';
contadorDiv.style.borderRadius = '3px';
contadorDiv.style.display = 'inline-block';
// Insertar después del textarea
textareaPrincipal.parentNode.insertBefore(contadorDiv, textareaPrincipal.nextSibling);
// Función para actualizar el contador
function actualitzarContador() {
var texto = textareaPrincipal.value;
var numParaules = contarParaules(texto);
var color = numParaules < 8 ? '#d32f2f' : '#388e3c'; // Rojo si <8, verde si >=8
contadorDiv.innerHTML = 'Paraules: ' +
numParaules + ' / 8 mínim';
if (numParaules < 8) {
contadorDiv.innerHTML += ' ✗';
contadorDiv.style.backgroundColor = '#ffebee'; // Fondo rojo claro
} else {
contadorDiv.innerHTML += ' ✓';
contadorDiv.style.backgroundColor = '#e8f5e9'; // Fondo verde claro
}
}
// Actualizar al escribir
textareaPrincipal.addEventListener('input', actualitzarContador);
textareaPrincipal.addEventListener('change', actualitzarContador);
// Actualizar inicialmente
actualitzarContador();
console.log('Contador afegit correctament');
}
// Esperar a que el DOM esté cargado
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM carregat, configurant validació...');
// Añadir contador en tiempo real
setTimeout(afegirContador, 500);
// Buscar todos los formularios en la página
var forms = document.querySelectorAll('form');
console.log('Formularis trobats:', forms.length);
forms.forEach(function(form, index) {
console.log('Configurant formulari', index, ':', form.id || form.name || 'sense nom');
// Añadir evento submit a cada formulario
form.addEventListener('submit', function(event) {
console.log('Formulari intentant enviar-se');
// Validar las palabras antes de enviar
if (!validarParaules()) {
event.preventDefault(); // Detener el envío
event.stopPropagation(); // Evitar que otros manejadores se ejecuten
return false;
}
console.log('Formulari vàlid, enviant...');
return true;
});
// También manejar envíos por JavaScript (por si acaso)
form.onsubmit = function() {
return validarParaules();
};
});
// También capturar envíos programáticos
var originalSubmit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = function() {
console.log('Submit cridat programàticament');
if (!validarParaules()) {
console.log('Validació fallida, aturant submit');
return false;
}
return originalSubmit.apply(this, arguments);
};
});
// Función para probar desde consola
window.comprobarParaulesActuals = function() {
var textareas = document.querySelectorAll('textarea');
textareas.forEach(function(ta, i) {
var paraules = contarParaules(ta.value);
console.log('Textarea ' + i + ' (' + (ta.name || 'sense nom') + '): ' + paraules + ' paraules');
});
};





