Se me pasó totalmente por alto ese detalle. Para una solución global tenemos que sustituir la línea del replaceChild con ésto:
caja.parentNode.replaceChild(nuevo,caja);
Así trabajaremos independientemente de dónde esté anidado
caja.
Una sugerencia de presentación (en la que me han salido muchas dudas) es ésta:
Código PHP:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Sugerencia de presentación: script cambiar caja pass</title>
<meta name="Author" content="derkeNuke">
<style>
input {
font-size:10px;
color:gray;
}
</style>
</head>
<body>
<script language="javascript">
function tratarUsuario(caja) {
if(caja.value=="Usuario") caja.value=""; // con valor original vaciaremos
else if(caja.value=="") caja.value="Usuario"; // con valor vacío restauraremos valor original
//un poco de estilo ;-)
caja.style.color= (caja.value=="Usuario")?"gray":"black";
}
function tratarPass(caja) {
if(caja.value=="Contraseña") cambiarCajaPass(caja); //era valor original, cambiamos a tipo password
else if(caja.value=="") cambiarCajaNormal(caja); //estaba vacía, restauramos valor original y caja tipo password
//el estilo se impone en la función cambiaCajaXXX
}
var nuevo, funcionFocus, funcionBlur;
function cambiarCajaPass(caja) {
nuevo=document.createElement("input");
nuevo.setAttribute("type","password");
nuevo.setAttribute("name", caja.name);
nuevo.style.color="gray";
//guardamos las funciones de los eventos en variables globales
funcionFocus=caja.onfocus;
funcionBlur=caja.onblur;
caja.parentNode.replaceChild(nuevo,caja);
//primero damos el foco a la caja nueva
setTimeout( "nuevo.focus();" ,100);
//después otorgamos los eventos previamente guardados
setTimeout( function() {
nuevo.onfocus=funcionFocus;
nuevo.onblur=funcionBlur;
},500); //despues de haber realizado el foco!!
}
function cambiarCajaNormal(caja) {
nuevo=document.createElement("input");
nuevo.setAttribute("type","text");
nuevo.setAttribute("name",caja.name);
nuevo.style.color="gray";
nuevo.setAttribute("value","Contraseña");
//guardamos
funcionFocus=caja.onfocus;
funcionBlur=caja.onblur;
caja.parentNode.replaceChild(nuevo,caja);
//otorgamos
setTimeout( function() {
nuevo.onfocus=funcionFocus;
nuevo.onblur=funcionBlur;
},100);
}
</script>
<form name="formulario">
<input type="text" name="user" value="Usuario" onfocus="tratarUsuario(this);" onblur="tratarUsuario(this);" />
<input type="text" name="pass" value="Contraseña" onfocus="tratarPass(this);" onblur="tratarPass(this);"/>
</form>
</body>
</html>
Si os parece bien, os pediría que la testeárais un poco, que le metáis caña, a ver dónde falla. Fijáos cómo los eventos se mantienen (como he podido hacerlo..) y da igual cuántas veces se convierte en pass o en caja normal. También observad el efecto cuando vaciamos el campo, como vuelve al estado original. Y también hay un cambio de color en el campo.
Las dudas que me han salido son (no creo que merezca abrir nuevo post):
1) En Firefox, el tamaño de las cajas no varía al hacer la sustitución. En IE la caja de tipo password es más pequeña (en ancho y en alto). ¿A quién se le ocurrió esto? Además en FF lo que se escribe son
* y en windows puntos gordos. Si se mantuviera la capacidad de caracteres se tendría que empequeñecer mucho más en FF.
Si tuviera que cambiar el style a las cajas sería un lío porque:
2) He intentado traspasar todo el atributo style de la caja vieja a la caja nueva, pero no he podido.
caja.style existe en FF y en IE, pero
caja.style[0] en FF da el nombre de la propiedad [0] y en IE no. En FF hacía
Código:
propiedad - caja.style[0]
su valor - caja.style[ caja.style[0] ]
pero en IE no da resultado.
3) Si alguien conoce un método más elegante de pasar todos los eventos, que lo postee por favor. No he sabido hacerlo de otra manera.
Buf cómo está dando de sí 4 líneas de código.
Un saludo y lo siento por haceros leer tanto