"Stylear" un < input type="file" / >

SeiYa

Buenas, para empezar, me cago en la putisima madre de MV, por que había escrito el "minitutorial" y al enviar desapareció, así que estoy escribiéndolo de nuevo:

Bien, esto lo he conseguido hacer gracias a: http://www.quirksmode.org/dom/inputfile.html

Si bien es cierto, siguiéndolo al pie de la letra no conseguí nada, pero bueno, gracias a lo que encontré, conseguí hacer algo parecido.

Ahora el tema a tratar xD

< anuncio >
¿Cúantas veces has hecho un formulario preciosamente "stylado" pero te le ha jodido un input del tipo file?
< /anuncio >

Bien, supongamos que tenemos este formulario:

http://img481.imageshack.us/img481/9059/11hz.jpg

Queda feo, a pesar de ser estilos muy simples los usados, como empieces a meter sombras o "efectos" bonitos a base de imágenes te quedará un formulario horrendo al tener un input file.

Bien, lo que yo hice siguiendo los consejos de esa página web y adaptándoles a mis necesidades:

Primero, meter el input file en una capa invisible, pero no por la propiedad hidden, sino por la opacidad en los estilos:

< div class="caparchivo" >
&nbsp;&nbsp;&nbsp; < input type="file" id="archivo" name="Archivo" class="archivo" / >
< /div >

Ahora veamos el estilo "archvo":

input.archivo
{
&nbsp;&nbsp;&nbsp;position: relative;
&nbsp;&nbsp;&nbsp;text-align: left;
&nbsp;&nbsp;&nbsp;-moz-opacity:0;
&nbsp;&nbsp;&nbsp;filter:alpha(opacity: 0);
&nbsp;&nbsp;&nbsp;opacity: 0;
&nbsp;&nbsp;&nbsp;z-index: 2;
}

Bueno, ya tenemos nuestra capa "invisible", ahora proseguiremos.

Crearemos otra capa, donde meteremos un input text normalito que si cogerá nuestros estilos:

< div class="archivofalso" >
&nbsp;&nbsp;&nbsp;< input id="nuevoarchivo" / >
< /div >

Ahora veremos el estilo "archivofalso":

div.archivofalso
{
&nbsp;&nbsp;&nbsp;position: relative;
&nbsp;&nbsp;&nbsp;top: 0px;
&nbsp;&nbsp;&nbsp;left: 0px;
&nbsp;&nbsp;&nbsp;z-index: 3;
}

Con esto, estará "encima" de nuestro input file, a pesar de este ser invisible, de este modo podremos escribir en nuestro input text.

Ahora el botón, podemos usar un botón, pero aconsejo una imagen y javascript:

< div class="examinar" >
&nbsp;&nbsp;&nbsp;< img src="imagenes/examinar_normal.jpg" id="examinar" / >
< /div >

Veamos el estilo "examinar":

div.examinar
{
&nbsp;&nbsp;&nbsp;position: relative;
&nbsp;&nbsp;&nbsp;top: 0px;
&nbsp;&nbsp;&nbsp;left: 0px;
&nbsp;&nbsp;&nbsp;z-index: 1;
}

Bien, esta imagen, realmente aparecerá debajo del botón de Examinar, solo que este al ser "transparente" dejara ver la imagen, al pulsar la imagen, realmente pulsamos el botón "Examinar..." del input file, solo que al ser transparente parece que pulsemos la imagen.

Con esto básicamente está todo arreglado, mejoras:

1.- Meter en una tabla de una fila y dos columnas, en la primera columna, la capa "archivofalso" con su input y en la segunda la capa "examinar" con su imagen/botón, ponerles un valign="top" o algo similar para que no descuadren.

2.- Comportamientos, queremos que al seleccionar un archivo se modifique en el cuadro de texto falso:

onChange= "getElementById('nuevoarchivo').value=getElementById('archivo').value;"

Con eso conseguiremos que el usuario vea la ruta en el cuadro.

Nuestro archivo subir.php o el que tenga el código encargado de subir el archivo no hará falta modificarle, ya que realmente cogerá el archivo del input file de siempre, lo que hacemos es para que quede bonito.

3.- Que parezca que pulso la imagen:

Es fácil:

Pondremos los dos comportamientos siguientes en el input file:

onMouseDown = "if(event.button==0){getElementById('examinar').src='imagenes/examinar_sobre.jpg'};"

onMouseUp = "if(event.button==0){getElementById('examinar').src='imagenes/examinar_normal.jpg'};"

Controlarán que se pulse el botón derecho o se suelte para cambiar la imagen.

En mi ejemplo, el comportamiento de la imagen es como el de un botón, se hunde de la misma manera que los botones de mi css.

4.- Queremos que si cambiamos la ruta o la escribimos nosotros manualmente, cambie también en el input file, luego haremos lo mismo que en 2 pero a la inversa:

onChange = "getElementById('archivo').value=getElementById('nuevoarchivo').value;"

5.- Ocurren problemas, puesto que en ocasiones, si la ruta la copiamos y pegamos y después damos a enviar, no hará el onchange correctamente, esto se soluciona poninedo un onclick en el submit:

onClick = "getElementById('archivo').value=getElementById('nuevoarchivo').value;"

Bien, el resultado es el siguiente:

http://img293.imageshack.us/img293/7615/26lq.jpg

Si la capa de examinar no fuese transparente veríamos esto:

http://img405.imageshack.us/img405/6201/30jr1.jpg

Si la imagen del "botón" examinar fuese más grande, veríamos que está detrás:

http://img528.imageshack.us/img528/7433/43uw.jpg

Ya apreciamos que está de la forma:

Cuadro de texto falso.

Input type file.

Imagen o botón falso de examinar.

Colocado de tal manera que de el pego.

El código que tengo yo, enlazando todo lo anterior sería:

Imagen:< br / >
< div class="caparchivo" >
&nbsp;&nbsp;&nbsp;< input type="file" id="archivo" name="Archivo" class="archivo" onChange= "getElementById('nuevoarchivo').value=getElementById('archivo').value;" onMouseDown = "if(event.button==0){getElementById('examinar').src='imagenes/examinar_sobre.jpg'};" onMouseUp = "if(event.button==0){getElementById('examinar').src='imagenes/examinar_normal.jpg'};" / >
< /div >
< table cellpadding="0" cellspacing="0" >< tr >< td valign="top" >
&nbsp;&nbsp;&nbsp;< div class="archivofalso" >
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;< input id="nuevoarchivo" onChange = "getElementById('archivo').value=getElementById('nuevoarchivo').value;" / >
&nbsp;&nbsp;&nbsp;< /div >
< /td >< td valign="top" >
&nbsp;&nbsp;&nbsp;< div class="examinar" >
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;< img src="imagenes/examinar_normal.jpg" id="examinar" / >
&nbsp;&nbsp;&nbsp;< /div >
< /td >< /tr >< /table >
< input type="submit" name="Submit" value="Insertar imagen!" onClick = "getElementById('archivo').value=getElementById('nuevoarchivo').value;" / >

Y aquí una muestra del funcionamiento sin transparencias:

http://www.wallack.es/mv/2.htm

Y con transparencias.

http://www.wallack.es/mv/1.htm

Un saludo y espero que os sirva.

SeiYa

Ya está bien puesto creo, no edito que me quita los espacios, diré que en el paso 3 el botón que se controla del ratón es el izquierdo no el derecho que se me fue la pinza.

Saludines.

erdanblo

Yo puse un post preguntando en domestika sobre esto.

Cuando me encontre que no era posible ni cambiar casi nada y me encontre con la solución, lo mande a tomar por *** xD, no me complico yo tanto para tal tonteria.

SeiYa

xD eso pensé yo, pero dije voy a ver, una vez has hecho uno puedes hacer el resto, es más, te haces una función en php, javascript, asp o lo que quieras que se llame por ejemplo: inputfile("nombredelinput"); y que te lo cree y a tomar por culo, así lo hago yo XD.

Un saludín :)

guner

Lo vi hace tiempo. Puede que el resultado sea bueno. No voy a entrar en polémica sobre en qué navegadores funciona y en cuales no, pero, es evidente que es una solución muy, MUY cutre.

De momento opacity no es un standar hasta que salga CSS3, tener que recurrir a ponerle opacidad 0 al input para que el botón quede encima de la imagen ...

Quedará bonito, pero es una chapuza.

La solución ideal sería [/i]simular el click en el input file mediante javascript, y que este input file estviera en una capa hidden.

SeiYa

#5 eso lo intenté pero no conseguí simular un click en javascript ... ¿se puede? xD y de poderse ¿cómo? aunque supongo que no se podrá xD

guner

No, claro que no se puede. Seguro que cualquiera que se le haya pasado por la cabeza "Stylear" un < input type="file" / > pensó en eso, creo yo.

SeiYa

Yo no digo que sea la solución idónea xD pero vamos, creo que es la única manera de stylear tu input file, aunque depende de factores como a quién va dirigida la web y demás.

Un saludo.

Usuarios habituales

  • SeiYa
  • guner
  • erdanblo