L’élément de formulaire input
de type fichier file
n’est pas stylisable et est considéré comme laid à la fois par les utilisateurs et les développeurs. Il est néanmoins possible de le cacher et de le présenter avec un bouton et un texte et/ou une boîte de dépôt dropbox avec laquelle il est permis de glisser et déposer un ou plusieurs fichiers. Nous allons voir cela avec un input
simple.
L’élément input file
L’élément input
est simplement :
1 |
<input type="file" name="zipFontFile"> |
Pour accepter plusieurs fichiers, on ajoute l’attribut multiple
.
La boîte de dépôt et le bouton
On enveloppe cet élément dans une div
en y mettant devant un bouton et un texte span
.
1 2 3 4 5 6 |
<div id="zipFileDropbox" class="dropbox ic-uploads"> <p class="upload-message">Drop your zip file here or</p> <button id="zipFileSelect" class="button button-secondary">Choose svg font zip file</button> <span id="zipFileName" class="placeholder"></span> <input type="file" name="zipFontFile"> </div> |
Les textes Drop your zip file here or
et Choose svg font zip file
peuvent facilement être changés. L’élément input type file
sera caché.
Le style
On peut mettre en forme de la façon suivante avec SASS
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
.dropbox { width: 25em; border: 1px solid #c5c5c5; background-color: #fff; padding: 1em; line-height: 3em; .upload-message { margin: 0 0 0.5em; text-align: center; line-height: 2em } input[type="file"] { display: none; } .placeholder { margin-left: 1em; display: inline-block; transform: translateY(-0.5em); } } |
Le bouton a l’id
zipFileSelect
, le texte zipFileName
, la boîte de dépot zipFileDropbox
et l’élément input
a le nom zipFontFile
.
Javascript
On définit dans le Javascript les constantes suivantes :
1 2 3 4 |
const zipFileSelect = document.querySelector('#zipFileSelect'), zipFontFile = document.querySelector('[name="zipFontFile"]'), zipFileName = document.querySelector('#zipFileName'), dropbox = document.querySelector('#zipFileDropbox'); |
On écoute ensuite les événements dragenter
, dragover
et drop
sur l’élément dropbox
. Les évéments dragenter
et dragover
ne font rien, on empêche juste le comportement par défaut et la propagation aux parents. L’événement drop
envoie sur le traitement. On écoute l’événement click
sur le bouton qui simule un appui sur l’élément input file
. La fonction handleFiles()
s’occupe du traitement, à savoir la complétion de l’élément input
.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
const dragenter = e => { e.stopPropagation(); e.preventDefault(); } const drop = e => { e.stopPropagation(); e.preventDefault(); zipFontFile.files = e.dataTransfer.files; handleFiles(e.dataTransfer.files); } zipFileSelect.addEventListener('click', e => { e.preventDefault(); zipFontFile.click(); }); dropbox.addEventListener('dragenter', dragenter); dropbox.addEventListener('dragover', dragenter); dropbox.addEventListener('drop', drop); zipFontFile.addEventListener('change', () => { handleFiles(zipFontFile.files); }); |
La fonction handleFiles()
remplit l’élément input
et peut faire des vérifications par exemple sur le type de fichier, la taille ou autre. Dans mon cas, je teste que l’utilisateur sélectionne un fichier de type ZIP
. On place cette fonction avant la fonction dragenter
, Javascript n’aimant pas que l’on utilise des fonctions avant de les définir, surtout si l’on n’utilise pas l’événement DOMContentLoaded
sur le document
, ni le mot clé function
pour définir les fonctions.
6 7 8 9 10 11 12 13 |
const handleFiles = files => { if( files[0].type != 'application/x-zip-compressed' ) { zipFileName.innerText = 'This is not a ZIP file'; return; } zipFileName.innerText = files[0].name; document.querySelector('#uploadZipFontFiles').disabled = false; } |
Dans le cas de plusieurs fichiers, on pourra choisir une autre présentation. Ici, seulement le premier fichier sélectionné est montré (files[0]
). On en profite pour activer un bouton permettant le téléchargement. Sur mon exemple, j’ai un bouton Upload Font
avec l’id
uploadZipFontFiles
.
Traitement AJAX
Le fichier sélectionné est utilisé de façon habituelle, dans un traitement AJAX
avec jQuery
par exemple :
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
( $ => { // ... mySecurityParameter ... ex: ajax_nonce const $uploadButton = $( '#uploadZipFontFiles' ); $uploadButton.on( 'click', e => { const $response = $( '#uploadZipFontFilesResponse' ); $uploadButton.after( '<div id="ici-loader" />' ); const formData = new FormData(); formData.append( 'action', 'ici_option' ); formData.append( 'security', mySecurityParameter ); formData.append( 'method', 'upload-font' ); formData.append( 'zip', zipFontFile.files[0] ); $.ajax({ url: ajaxurl, type: 'POST', dataType: 'json', contentType: false, // Needed with input[type="file"] processData: false, // Needed with input[type="file"] data: formData }) .done( function( json ) { $( '#ici-loader' ).remove(); $response.html( json.response ); }); }); // ... })( jQuery ); |
On récupère alors le fichier dans la variable
$_FILES['zip'] dans le traitement en PHP
sur le serveur correspondant à l’adresse ajaxurl
.
Et hop, une jolie manière de présenter un élément inpu
t de type file
.