Me ha interesado este proyecto, y se me ha ocurrido depurarlo un poco.
Creo que de esta otra manera, sería más personalizable (y eficaz).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>PASSWORDS</title>
<script language="Javascript" type="text/javascript">
function $(id) //función "getElementById"
{return document.getElementById(id);}
function BI(num) //función que devuelve número de dos dígitos
{return (num.length==1?'0'+num:num);}
var EXTREMS=new Array(new Array(255,0,00),new Array(50,200,0)); /*array(color 0%=array(RR,GG,BB), color 100%=array(RR,GG,BB)), ¡¡IMPORTANTE: los colores, en DECIMAL!!*/
var ESCALON=20; //grado de definición del degradado
var COLORES=new Array(); //matriz del degradado
for(i=0;i<ESCALON;i++)
{COLORES[i]=('#'+BI(Math.floor(EXTREMS[0][0]+i*(EXTREMS[1][0]-EXTREMS[0][0])/ESCALON).toString(16))+
''+BI(Math.floor(EXTREMS[0][1]+i*(EXTREMS[1][1]-EXTREMS[0][1])/ESCALON).toString(16))+
''+BI(Math.floor(EXTREMS[0][2]+i*(EXTREMS[1][2]-EXTREMS[0][2])/ESCALON).toString(16))).toUpperCase()
}
function verify(txt)
{var promo=new Array();
promo[0]=4; //puntuación por minúsculas
promo[1]=3; //puntuación por números
promo[2]=5; //puntuación por mayúsculas
promo[3]=6; //puntuación por caracteres no-alfanuméricos
promo[4]=-5; //puntuación por longitud =4
promo[5]=0; //puntuación por longitud =5
promo[6]=3; //puntuación por longitud =6
promo[7]=6; //puntuación por longitud =7
promo[8]=12; //puntuación por longitud >7
var total=promo[0]+promo[1]+promo[2]+promo[3]+promo[8]; //máximo de puntos posibles
var compl=0; //inicia el cómputo de puntos
var porce=0; //inicia el porcentaje
if(new RegExp('[a-z]+').test(txt)){compl+=promo[0];} //suma puntos por minúscula
if(new RegExp('[0-9]+').test(txt)){compl+=promo[1];} //suma puntos por números
if(new RegExp('[A-Z]+').test(txt)){compl+=promo[2];} //suma puntos por mayúscula
if(new RegExp('[^A-Za-z0-9_]+').test(txt)){compl+=promo[3];} //suma puntos por no-alfanumérico
switch (txt.length)
{case 4: compl+=promo[4]; break; //suma puntos por longitud =4
case 5: compl+=promo[5]; break; //suma puntos por longitud =5
case 6: compl+=promo[6]; break; //suma puntos por longitud =6
case 7: compl+=promo[7]; break; //suma puntos por longitud =7
default:
if(txt.length>7)
{compl+=promo[8];} //suma puntos por longitud >=8
else
{compl=0;} //para longitud <4, anula todos los puntos obtenidos
}
compl=compl>0?compl:0; //Si los punos son negativos, pone 0
var porce=Math.round(compl*100/total); //Transforma los puntos, en porcentaje
//dimensiona la barra, la pone en su color, y escribe el porcentaje de seguridad
$('DIV').style.width=porce+'%';
$('DIV').style.backgroundColor=COLORES[Math.round(ESCALON*porce/100)-1];
$('DIV').innerHTML=porce+'%';
}
window.onload=function(){verify($('PWD').value);};
</script>
<style media="all" type="text/css">
input{margin-bottom:5px;}
div {border:red 0px solid;}
.C1 {width:180px; height:18px; margin-top:10px; margin-bottom:-30px;}
.C2 {width:100px; height:18px; margin-top:10px; float:right; margin-top:-20px;}
.D1 {border:#000 1px solid; width:200px; height:15px; overflow:hidden;}
#DIV{background-color:#579; color:white; width:30%; height:15px; text-align:center; overflow:hidden; font-size:12px; padding:0px;}
</style>
</head>
<body>
<input type="text" id="PWD" onkeyup="javascript:verify(this.value);" />
<div class="D1"><div id="DIV">30%</div></div>
</body>
</html>
*** NOTA: en
rojo, los comentarios al código que debe/puede ser personalizado.
*** NOTA: en
azul, los comentarios "extra".
*** NOTA: aunque el código sea más largo que el que proponías, la función en cuestión es más sencilla.
La función así es más rápida, y más eficiente (menos bucles, menos "if" anidados...)
Además, es más personalizable, y "exacta".
También así se ahorra el "background-position", para poner los colores (si es que entendí bien cómo manejabas el color.)
NOTA: He estado informándome por ahí sobre que es un "password seguro", y he constatado que no se puede medir su seguridad en término de sumas aritméticcas, sino más bien termino exponencial, con lo que la fórmula que usamos (sumando "bonus") no es la adecuada.
De hecho, hay manera más apropiada, y fácil, de hecho.
Es: calcular cuánto tardaría en hackearse por "fuerza bruta", esto es... calcular las cadenas de texto que se podrían formar con su misma lonjitud, y mismo juego de caracteres.
(ejemplos:)
Password: 1234 -> juego de caracteres: [0-9] -> longitud: 4 -> posibilidades: 10^4 (10.000)
Password: casa -> juego de caracteres: [a-z] -> longitud: 4 -> posibilidades: 26^4 (457.000)
Password: c4sA -> juego de caracteres: [a-zA-z0-9] -> long: 4 -> posibilidads: 62^4 (14.800.000)
Como se ve... las posibilidades de dar con el pass, no crecen aritméticamente, sino exponencialmente.
Para eso, he creado otra función distinta, que analizará el problema desde ese otro punto de vista.
Quizá en un par de días me anime, y se lo proponga a
Freddie para tip. Si no, ya lo pondré por aquí.