[CSS & JS]Personalizar input file

Iniciado por Once, Mayo 24, 2014, 08:04:16 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Mayo 24, 2014, 08:04:16 PM Ultima modificación: Mayo 24, 2014, 08:05:56 PM por 11Sep
Los que alguna vez jugueteamos con el diseño web, muy seguramente nos encontramos con el problema de personalizar los input file. Inteentaré mostrar la forma en que logré personalizar los input file usando sólo CSS, JS, y el DOM de una manera sencilla. Que además nos permite eliminar archivos que ya estan en la lista para ser subidos al servidor.


La idea es convertir esto:


en esto:



Código: html5

<html>
    <head>
        <link href="input.css" rel="stylesheet" />
        <script src="input.js"></script>
    </head>
    <body>
        <center>
            <form action="http://127.0.0.1:5000/upload" enctype="multipart/form-data" method="POST" id="frm_upload">
                <div id="upload">
                    <input id="archivos" type="file" name="file[]" multiple="multiple" onchange="seleccionados();"/>
                </div>
                <span id="filename"></span>
                <p/>
                <input type="button" name="submit" value="Subir" onclick="subir();"/>
            </form>
        </center>
    </body>
</html>


Para eso, vamos a usar un formulario normal, estructurado así:

un div con id "upload" dentro del cual meteremos el input file; es el div que moldearemos para que tome la forma que nuestro upload tenga.
un input file configurado para seleccionar multiples archivos. Cuando se selecciona un archivo (evento onchange) llama a la función seleccionados
un span con id "filename" que es donde mostraremos los archivos seleccionados
un input button que se encargara cuando hagamos click sobre el de enviar el formulario.

El css (input.css):

Código: css
input[type=file] {
    opacity: 0;
    width: 100%;
    height: 100%;
}

#upload {
    background: url("https://cdn2.iconfinder.com/data/icons/internet/512/Upload-128.png") #111 center center no-repeat;
    width: 150px;
    border-radius: 5px;
    height: 150px;
    box-shadow: 0 0 5px #111;
}


Este sencillo CSS simplemente hace invisible el input file (opacity: 0) y le da un ancho y alto de 100% para que ocupe la totalidad del div (upload)
en el bloque #upload, damos la apariencia que queremos que tengo nuestro upload agrgando un simple background, una sombra y unas dimensiones (150x150).

Hasta ahora, nuestro upload se ve así:

Si lo clickeamos, nos abre la ventana para seleccionar los archivos, pero una vez seleccionados, NO LOS MUESTRA. Así que ahora vamos a codear el JS:

El JS (input.js): Los navegadores no nos dejan modificar los datos de los input file, pero si que nos permite juguetear un poco con los datos. Así que lo que haremos sera obtener la lista de los elementos seleccionados y la guardaremos en un array que podremos modificar (ara eliminar los elemento que no queremos subir) y a la hora de enviar el formulario al servidor, lo que haremos es simular un formulario que llenaremos con la informacion del array y lo enviamos al servidor.

La función seleccionados:

Código: javascript
//Creamos el array que usaremos para almacenar y enviar la informacion
var ELEMENTOS = new Array();

function seleccionados() {
    //Obtenemos el inputfile
    var input = document.getElementById("archivos");
    //Obtenemos los archivos
    var archivos = input.files;
    //Aca es donde mostraremos los elementos seleccionados
    var elementos = document.getElementById("filename");
       
    //Limpiamos los elementos seleccionados anteriormente
    elementos.innerHTML = " ";
    ELEMENTOS = [];
   
    //Recorremos archivo por archivo
    for (item=0; item< archivos.length; item++) {
        //duplicamos el archivo seleccionado en el array elementos
        ELEMENTOS[item] = archivos[item];
        //Creamos un div donde mostramos el archivo seleccionado
        crear_div("file", elementos, archivos[item].name);
    }
}


La funcion crear_div: Esta funcion se encarga de crear un div, agregarle propiedades y luego incrustarlo en un elemento padre

Código: javascript

//funcion que crea un div
function crear_div(clase, padre, informacion) {
    //Escapamos la variable informacion para evitar posibles XSS
    informacion = escape(informacion);
    //Creamos el div
    var div = document.createElement("div");
    //Le agregamos al div sus propiedades
    div.setAttribute("class", clase);
    div.setAttribute("title", "click para eliminar");
   
    //en caso de hacer click en un elemento, lo elimina de la lista de los archivos a subir
    div.onclick = function() {
        var index = -1;
        //eliminamos el archivo seleccionado de la lista
        for (indice=0; indice < ELEMENTOS.length; indice++) {
            //Buscamos el index del elemnto seleccionado para ser eliminado
            if (ELEMENTOS[indice].name == unescape(informacion)) {
                index = indice;
            }
        }
        if (index != -1) {
            //removemos el elemento de la lista
            ELEMENTOS.splice(index, 1);
            padre.removeChild(div);
        } else {
            alert("No se pudo eliminar el elemento");
        }
       
    }
   
    //Agregamos el div al padre
    padre.appendChild(div);
    div.innerHTML = informacion;
}



Hasta ahora, nuestro upload se ve así.

Sólo nos resta darle un estilo a los div que contienen el nombre de los archivos seleccionados (que tienen la clase file):

Código: css
.file {
    background: #111;
    display: inline-block;
    margin: 5px;
    color: #FFF;
    line-height: 25px;
    padding: 5px;
    border-radius: 5px;
    box-shadow: 0 0 5px #000;
}


Y programar la función para subir los archivos al servidor:

Código: javascript
function subir() {
    //creamos un nuevo formulario y lo llenamos con la información del array con los elementos a enviar
    var formulario = new FormData();
   
    for (file=0; file < ELEMENTOS.length; file++) {
        formulario.append("file[]", ELEMENTOS[file]);
    }
   
    //obtenemos el action y method del formulario original
    var frm = document.getElementById("frm_upload");
    var metodo = frm.method.toUpperCase();
    var action = frm.action;
   
    //enviamos el formulario
    var request = new XMLHttpRequest;
    request.open(metodo, action);
    request.send(formulario);
}


Y nuestro uploader está listo.

Saludos!







No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Muchisimas gracias, nunca me terminaba de gustar el estilo del uploader, ya que sabía ponerle lo básico de estilos pero nunca tan currado...

Mañana hago uno para practicar, gracias otra vez :)

Un saludo.

Enviado desde BlackMovil5




No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Muchisimas gracias, nunca me terminaba de gustar el estilo del uploader, ya que sabía ponerle lo básico de estilos pero nunca tan currado...

Mañana hago uno para practicar, gracias otra vez :)

Un saludo.

Enviado desde BlackMovil5

Espero te sirva el post. si tienenes alguna duda o algo, sólo comenta.

Saludos!







No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Wow! De verdad buenísimo!
Pero ¿cómo se envían los archivos al server? Digo, como los "agarro" con PHP...

Enviado desde mi ST25a mediante Tapatalk

Visita mi blog: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Wow! De verdad buenísimo!
Pero ¿cómo se envían los archivos al server? Digo, como los "agarro" con PHP...

Enviado desde mi ST25a mediante Tapatalk

No soy un tipo de PHP (programé el uploader para usarlo con flask y ajax) pero esto te debería servir:

Código: php
<?php
    if (isset($_FILES["file"])) {
    $error = true;
    $len = count($_FILES["file"]["name"]);

    for ($index=0; $index < $len; $index++) {
    $temporal = $_FILES["file"]["tmp_name"][$index];
    $nombre = $_FILES["file"]["name"][$index];
   
    if (move_uploaded_file($temporal, "subidos/".$nombre)) {
    $error = false;
    }
   
    }

    if ($error) {
    echo("Ocurrio un error");
    } else {
    echo("Subida con exito");
    }
   
    }
?>


OJO: El código es bypaseable. Asíq ue cuidado dónde lo uses.

Saludos!







No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Aaah, gracias :D Lo que quería saber es cómo quedaba el array $_FILES

Enviado desde mi ST25a mediante Tapatalk

Visita mi blog: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

No se como agradecerte  ;D es lo que necesitaba!
Una pregunta, sabras como hacer una pestaña flotante en el centro de la pantalla (que no sea pop-up) con javascript, donde se pueda introducir este mismo input. Es para un proyecto, una pagina donde se puedan subir wallpapers con terminacion en (.jpg, .jpeg y .png).
Un saludo! :D