Nous savons tous que les entrées de fichiers sont très limitées en termes de personnalisation et bien qu'il existe de nombreux plugins alambiquées avec des dizaines de solutions de repli qui vous permettent de les personnaliser, c'est toujours un défi parfois de le faire fonctionner. Ce tutoriel vous guidera à travers le processus de création d'un plugin jQuery pour remplacer ce vilain entrée à la recherche avec le soutien de plusieurs fichiers et un repli simple pour les vieux navigateurs, ahem, IE9-8.
Maintenant que nous avons tout ce dont nous avons besoin nous allons ouvrir notre fichier HTML et ajouter un conteneur et un fichier d'entrée avec son étiquette:
Suivant ouverts
En cliquant sur le bouton "ouvrir" déclenchera un événement "click" sur le fichier d'entrée d'origine. Après avoir choisi un fichier d'entrée d'origine déclenche un événement «change», où nous allons définir la valeur de l'entrée en accédant à l'ensemble du fichier si le fichier est pris en charge l'API, ou en accédant à la valeur d'origine autrement.
Ensuite, nous allons «se débarrasser» de l'entrée d'origine. Au lieu de le cacher, nous allons retirer de la fenêtre en la déplaçant vers la gauche, de cette façon on peut encore l'utiliser même si elle n'est pas visible, ce qui est utile pour déclencher des événements qui peuvent être problématiques si l'entrée est littéralement caché.
Maintenant, nous pouvons utiliser le
Le code suivant va après le plugin car il est destiné à être appliqué à toutes les entrées de fichiers personnalisés. Ici, nous avons besoin d'utiliser
Le plugin a été testé sur IE9-8 et tous les navigateurs modernes. Saisissez le code complet ou de jouer avec la démo . Si vous avez des suggestions s'il vous plaît laissez un commentaire ci-dessous.
Comment créer un fichier d'entrée personnalisé avec jQuery, CSS3 et PHP
Mise en place du projet
D'abord nous allons créer un dossiercustomFile
et 3 photos, jquery.customFile.js
, jquery.customFile.css
et customFile.html
. Pour commencer rapidement, saisissez cette template HTML et copiez / collez-le dans votre projet. Maintenant que nous avons tout ce dont nous avons besoin nous allons ouvrir notre fichier HTML et ajouter un conteneur et un fichier d'entrée avec son étiquette:
<div class="customfile-container"> <label>File: </label> <input type="file" id="file" name="myfiles[]" multiple /> </div>Assurez-vous également de lui donner un
id
et un nom de tableau, comme myfiles[]
de sorte que le serveur peut récupérer tous les fichiers avec le repli IE qui sera traité plus tard. Suivant ouverts
jquery.customFile.js
et configurer une base réutilisable jQuery plugin: ;(function( $ ) { $.fn.customFile = function() { return this.each(function() { var $file = $(this).addClass('customfile'); // the original file input // code here }); }; }( jQuery ));Enfin, appelez le plugin dans votre balisage:
<script>$('input[type=file]').customFile()</script>
Comment ça marche?
Pour construire le remplacement sur mesure nous avons besoin d'une structure de balisage simple:En cliquant sur le bouton "ouvrir" déclenchera un événement "click" sur le fichier d'entrée d'origine. Après avoir choisi un fichier d'entrée d'origine déclenche un événement «change», où nous allons définir la valeur de l'entrée en accédant à l'ensemble du fichier si le fichier est pris en charge l'API, ou en accédant à la valeur d'origine autrement.
Construire le Plugin
Premièrement, nous devons tester le navigateur demultiple
soutien. Le plus simple est de créer une entrée et vérifier si elle a un multiple
propriété disponible sinon le navigateur ne prend pas en charge les fichiers multiples. Nous devons également vérifier si le navigateur est IE pour quelques corrections par la suite. Ce code peut être déplacé à l'extérieur du plugin, car elle ne dépend pas de l'élément lui-même. // Browser supports HTML5 multiple file? var multipleSupport = typeof $('<input/>')[0].multiple !== 'undefined', isIE = /msie/i.test( navigator.userAgent ); // simple but not super secure...Maintenant, nous allons créer les éléments nécessaires pour le remplacement. IE des mesures de sécurité strictes qui empêchent le nom de fichier en cours de récupération si l'entrée est déclenchée à l'extérieur donc nous allons utiliser une
label
au lieu d'un button
. En déclenchant l'événement sur l'étiquette on peut contourner ce problème. var $wrap = $('<div class="customfile-wrap">'), $input = $('<input type="text" class="customfile-filename" />'), $button = $('<button type="button" class="customfile-upload">Open</button>'); $label = $('<label class="customfile-upload" for="'+ $file[0].id +'">Open</label>');Le
type="button"
attribut est nécessaire pour la cohérence, pour éviter certains navigateurs de soumettre le formulaire. Ensuite, nous allons «se débarrasser» de l'entrée d'origine. Au lieu de le cacher, nous allons retirer de la fenêtre en la déplaçant vers la gauche, de cette façon on peut encore l'utiliser même si elle n'est pas visible, ce qui est utile pour déclencher des événements qui peuvent être problématiques si l'entrée est littéralement caché.
$file.css({ position: 'absolute', left: '-9999px' });Enfin nous allons ajouter nos nouveaux éléments au DOM:
$wrap.insertAfter( $file ).append( $file, $input, ( isIE ? $label : $button ) );À ce stade, vous devriez avoir quelque chose qui ressemble à ça dans un navigateur décent, nous nous occupons de IE plus tard.
Fixation des événements
La première chose que nous devons faire est d'empêcher l'entrée d'origine de gagner mise au point, ainsi que le bouton nouvellement créé. Seule la saisie de texte doit être en mesure de recevoir le focus.$file.attr('tabIndex', -1); $button.attr('tabIndex', -1);Nous allons déclencher le
click
événement sur le bouton pour ouvrir la boîte de dialogue. Dans IE, car il n'ya pas de vrai bouton, l'étiquette doit déjà déclencher le dialogue sans travail supplémentaire. $button.click(function () { $file.focus().click(); // Open dialog });L'
focus
événement doit être déclenché sur certains navigateurs ainsi l'événement de clic fonctionne correctement. Si vous essayez de cliquer "ouvert" dans votre navigateur, à ce stade, il convient d'ouvrir la boîte de dialogue de fichier. Maintenant, nous pouvons utiliser le
change
événement qui est déclenché après avoir choisi un fichier pour remplir la valeur de la saisie de texte avec le fichier choisi (s). $file.change(function() { var files = [], fileArr, filename; // If multiple is supported then extract // all filenames from the file array if ( multipleSupport ) { fileArr = $file[0].files; for ( var i = 0, len = fileArr.length; i < len; i++ ) { files.push( fileArr[i].name ); } filename = files.join(', '); // If not supported then take the value // and remove the path to show only the filename } else { filename = $file.val().split('\\').pop(); } $input.val( filename ) // Set the value .attr('title', filename) // Show filename in title tootlip .focus(); // Regain focus });
Améliorer la convivialité
Tout fonctionne bien jusqu'à présent, mais il ya certaines choses que nous pouvons faire pour améliorer la convivialité et le comportement global de notre nouveau remplacement.- Déclencher le
blur
événement sur l'entrée d'origine lorsque le remplacement perd le focus. - Ouvrez la boîte de dialogue lorsque l'utilisateur appuie sur "Entrée" sur la saisie de texte, sauf IE (en raison des limitations de sécurité ça ne marchera pas).
- Supprimer les fichiers avec "backspace" ou "delete", sinon, l'utilisateur est contraint d'ouvrir la boîte de dialogue et appuyez sur "annuler" pour effacer l'entrée.
$input.on({ blur: function() { $file.trigger('blur'); }, keydown: function( e ) { if ( e.which === 13 ) { // Enter if ( !isIE ) { $file.trigger('click'); } } else if ( e.which === 8 || e.which === 46 ) { // Backspace & Del // On some browsers the value is read-only // with this trick we remove the old input and add // a clean clone with all the original events attached $file.replaceWith( $file = $file.clone( true ) ); $file.trigger('change'); $input.val(''); } else if ( e.which === 9 ){ // TAB return; } else { // All other keys return false; } } });
Repli pour les anciens navigateurs
Le plus simple repli pour permettre aux fichiers multiples est de créer des entrées multiples. Quand un fichier est choisi, nous créons une nouvelle entrée, lorsque l'entrée est effacée, nous l'enlever.Le code suivant va après le plugin car il est destiné à être appliqué à toutes les entrées de fichiers personnalisés. Ici, nous avons besoin d'utiliser
on
de déléguer le cas pour les entrées futures qui n'existent pas encore. if ( !multipleSupport ) { $( document ).on('change', 'input.customfile', function() { var $this = $(this), // Create a unique ID so we // can attach the label to the input uniqId = 'customfile_'+ (new Date()).getTime(); $wrap = $this.parent(), // Filter empty input $empty = $wrap.siblings().find('.customfile-filename') .filter(function(){ return !this.value }), $file = $('<input type="file" id="'+ uniqId +'" name="'+ $this.attr('name') +'"/>'); // 1ms timeout so it runs after all other events // that modify the value have triggered setTimeout(function() { // Add a new input if ( $this.val() ) { // Check for empty field to prevent // creating new inputs when changing files if ( !$empty.length ) { $wrap.after( $file ); $file.customFile(); } // Remove and reorganize inputs } else { $empty.parent().remove(); // Move the input so it's always last on the list $wrap.appendTo( $wrap.parent() ); $wrap.find('input').focus(); } }, 1); }); }
Personnalisation de l'apparence
Tout doit être travaillent à cet endroit afin épices Regardons les choses en place avec certains styles:/* It's easier to calculate widths * with border-box layout */ .customfile-container * { box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; font: normal 14px Arial, sans-serif; /* Global font to use ems with precision */ } .customfile-container { width: 300px; background: #FFF2B8; padding: 1em; } .customfile-container label:first-child { width: 100px; display: block; margin-bottom: .5em; font: bold 18px Arial, sans-serif; color: #333; } .customfile-wrap { position: relative; padding: 0; margin-bottom: .5em; } .customfile-filename, .customfile-upload { margin: 0; padding: 0; } .customfile-filename { width: 230px; padding: .4em .5em; border: 1px solid #A8A49D; border-radius: 2px 0 0 2px; box-shadow: inset 0 1px 2px rgba(0,0,0,.2); } .customfile-filename:focus { outline: none; } .customfile-upload { display: inline-block; width: 70px; padding: .4em 1em; border: 1px solid #A8A49D; background: #ddd; border-radius: 0 2px 2px 0; margin-left: -1px; /* align with input */ cursor: pointer; background: #fcfff4; background: -moz-linear-gradient(top, #fcfff4 0%, #e9e9ce 100%); background: -webkit-linear-gradient(top, #fcfff4 0%, #e9e9ce 100%); background: -o-linear-gradient(top, #fcfff4 0%, #e9e9ce 100%); background: -ms-linear-gradient(top, #fcfff4 0%, #e9e9ce 100%); background: linear-gradient(to bottom, #fcfff4 0%, #e9e9ce 100%); } .customfile-upload:hover { background: #fafafa; box-shadow: 0 0 2px rgba(0,0,0,.2); } .customfile-upload::-moz-focus-inner { /* Fix firefox padding */ padding: 0; border: 0; }Allez-y et personnaliser le CSS pour créer votre propre look.
Récupération des fichiers sur le serveur
Tout d'abord, enveloppez votre entrée dans un formulaire et ajoutez un bouton d'envoi:<form action="test.php" method="post" enctype="multipart/form-data"> <div class="customfile-container"> <label>File: </label> <input type="file" id="file" name="myfiles[]" multiple /> </div> <button type="submit">Submit</button> </form>Ensuite, nous pouvons obtenir tous les noms de fichiers et de les imprimer dans
test.php
: <?php $files = $_POST['myfiles']; // Array containing all files echo implode( $files, '<br/>' );Comme nous utilisons un nom de tableau
myfiles[]
, le serveur va récupérer tous les fichiers, même lorsque le repli est utilisé. Vous pouvez en lire plus à ce sujet dans le manuel PHP sur Téléchargement de plusieurs fichiers . Conclusion
Sans beaucoup d'effort entrées de fichiers sont assez faciles à personnaliser. Le repli n'est évidemment pas idéal, mais ça fonctionne et c'est simple à entretenir sans introduire des centaines de lignes de code, ou d'autres technologies comme Flash, Silverlight, etc ..Le plugin a été testé sur IE9-8 et tous les navigateurs modernes. Saisissez le code complet ou de jouer avec la démo . Si vous avez des suggestions s'il vous plaît laissez un commentaire ci-dessous.
Aucun commentaire:
Enregistrer un commentaire
Nous vous invitons ici à donner votre point de vue, vos informations, vos arguments. Nous refusons les messages haineux, diffamatoires, racistes ou xénophobes, les menaces, incitations à la violence ou autres injures. Merci de garder un ton respectueux et de penser que de nombreuses personnes vous lisent.
La rédaction