Bouton upload sans submit ni zone de texte (AJAX)

Après avoir chercher sur différents forums et site pour réaliser cela, voici une synthèse qui fonctionne.

Ce bouton permet de faire un upload de fichier en cliquant sur un seul bouton => dès que le fichier est sélectionnés, il est envoyé en POST en ajax.

Partie Javascript:

 $('.Bimport').click(function(e){
       e.preventDefault();
       $('Input[name="fichiercsv"]').click();
   });

   $('Input[name="fichiercsv"]').change(function (){
       $("#formimportcsv").submit();
   });

   $("body").on('submit','#formimportcsv', function(e) {
       e.preventDefault();
       $.ajax({
           type: 'POST',
           url: "/importcsv",
           data: new FormData(this),
           contentType: false,
           cache: false,    
           processData:false,  
           success: function (retour) {
               alert(retour);
               window.location.reload();
           },
           dataType: "html"
       });
  });

Partie HTML:

<form class="form-inline" action="/importcsv" method="post" role="form" id="formimportcsv" enctype="multipart/form-data">
    <a class='btn btn-primary Bimport' href=''>Import fichier TXT</a>
    <input type="file" style='position:absolute;z-index:2;top:0;left:0;filter: alpha(opacity=0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;background-color:transparent;color:transparent;' accept=".txt" name="fichiercsv" size="255">
</form>

 

Partie PHP (Laravel):

définir la route /importcsv » vers la fonction suivante:

public function importcsv(){
    $erreur="";

    if (!isset($_FILES["fichiercsv"])) {
         return "pas de réception de File";
    } else {

        if ($_FILES["fichiercsv"]["error"])
        {
            switch ($_FILES['fichiercsv']['error']){
                case 1: // UPLOAD_ERR_INI_SIZE
                     return "Le fichier dépasse la limite autorisée par le serveur (fichier php.ini) !";
                    break;
                case 2: // UPLOAD_ERR_FORM_SIZE
                     return "Le fichier dépasse la limite autorisée dans le formulaire HTML !";
                    break;
                case 3: // UPLOAD_ERR_PARTIAL
                     return "L'envoi du fichier a été interrompu pendant le transfert !";
                    break;
                case 4: // UPLOAD_ERR_NO_FILE
                     return "Le fichier que vous avez envoyé a une taille nulle !";
                    break;
            }

        }
        else {
            $typeautorises = Array('text/plain');
            if (!in_array($_FILES["fichiercsv"]["type"], $typeautorises)) {
                return 'Format non accepté';
            } else {
                if (!$_FILES["fichiercsv"]["name"]) {
                    return 'Nom de fichier vide';
                } else {
                    if ($_FILES["fichiercsv"]["size"] == 0) {
                        return 'Fichier reçu vide';
                    } else {
                    
                    // votre traitement ici

                    }

                }
            }
        }
    }
    return "Importation OK";
}

 

Explications:

  • Le champ input est invisible et le click du bouton affiché déclenche un click sur le champ caché.
  • Une fois le fichier choisi, l’évènement change déclenche la soumission du formulaire
  • La soumission est interceptée et envoyée en ajax.
  • La fonction PHP analyse la validité du fichier, puis exécute votre traitement.
  • Le texte renvoyé par la fonction PHP est affiché dans une boite d’alerte, puis la fenêtre html est réactualisée.

Utiliser les checkbox modifiées par uniform.js

Case à cochée "uniform"Uniform.js est un composant permettant d’améliorer le design des checkbox, des bouton radios, des listes déroulantes etc…
Sur leur site vous trouverez aisément comment créer des checkbox « uniformisée » …
Le seul truc qu’on oublier les créateurs de ce plugin jquery, c’est d’expliquer utiliser comment les objets ainsi modifié … car on créer rarement une case à cocher pour décorer sa page…

Or, le fonctionnement des checkbox « uniformisée » est différents des checkbox classique.

uniform.js entoure le checkbox d’un span dans lequel il place une classe « checked » quand l’élément est cochée. La case elle même ne comporte pas d’indication d’état.

Donc on récupère l’état ainsi:

var etat=$("#macaseacocher").parent().hasClass("checked");

Le principal défaut de ce composant c’est le délais entre le click et l’actualisation de son état. Selon les navigateurs, il est courant que l’événement .change arrive avant que la classe ai été ajoutée… => la lecture de valeur est donc faussée:

// code non fiable => résultat 
$("#macaseacocher").change(function(){
 var etat= $("this").parent().hasClass("checked");
 alert(etat);
});

La solution est alors d’intégrer l’appel de la fonction de mise à jour et de ne faire le test qu’après l’exécution de celle ci :

$("#macaseacocher").change(function(){
   // force l'update de uniform avant le test pour fiabiliser le résultat.
   $.uniform.update($(this));
   var etat= $("this").parent().hasClass("checked");
   alert(etat);
});

Ci dessous quelques routines que j’ai extrait d’un script ou je me sert des cases a cochées « uniformisée » pour sélectionner des éléments dans un tableau. En bas de ce tableau, une case a cocher nommée checktout permettait de cocher toute les autres.

Autre exemples de codes:

// compter le nombre de cases cochées (pour un tableau par exemple)
function CompteCasesCochees(){
 //sélecteur des enregistrements cochés sauf "checktout":
 var CasesCochees=$(":checkbox:not('#checktout')").parent(".checked").children();
 return CasesCochees.length;
}
// Recuperer les valeurs des cases cochées d'un tableau
// Ce tableau comportant en derniere ligne une case nommée cochertout permettant de tout (de)selectionner
function getValeursCasesCochees(){
 //selecteur des enregistrements cochés sauf "cochertout":
 var CasesCochees=$(":checkbox:not('#cochertout')").parent(".checked").children();
 var valeurs = [];
 CasesCochees.each(function() {
   valeurs.push($(this).val());
 });
 return valeurs;
}

Additif du 12 septembre:
Pour la lecture et le comptage des cases, la vérification de la classe « checked » sur l’élément le span parent suffit.
En revanche, pour cocher ou décocher par programmation une ou plusieurs cases, il faut réaliser l’action d’une case classique (à savoir ajouter l’attribut « checked » true sur la case) ET ajouter la classe « checked » sur le span parent.

Exemple:

    $(":checkbox").change(function(){
 // force l'update du theme uniform avant le test pour être sur du résultat.

        $.uniform.update($(this));
        if ($(this).attr("id")=="cochetout")
        //l'utilisateur a cliqué sur "tous (de)cocher"
        {
            var indicateur=$(this).parent();
            var cases=$(":checkbox:not('#cochetout')");/
            if ( indicateur.hasClass("checked")){
                cases.attr("checked", true);
                cases.parent().addClass("checked");

            } else {
                cases.attr("checked", false);
                cases.parent().removeClass("checked");
            }
            // on renvoi une mise à jour car on a changé l'état des cases.
            $.uniform.update($(this));
        }
        affichenbcasescochees();
    });

function affichenbcasescochees(){
//selecteur des enregistrements cochés sauf "cochetout":
var CasesCochees=$(":checkbox:not('#cochetout')").parent(".checked").children();
$("#nbselect").html("Nombre d'élements cochés:  "+ CasesCochees.length );
}