Projet 2 jQuery

Barre latérale à position fixe avec défilement animé

  1. Objectifs

    • Utiliser Jquery pour créer une barre latérale à position fixe avec défilement animé
  2. Présentation

    1. Description
      • Dans ce tutoriel nous allons, créer un widget de téléchargement de fichiers complet avec HTML5 et jQuery.
      • Nous pouvons facilement ajouter la prise en charge de fonctionnalités avancées telles que les téléchargements multiples et une interface de glisser-déposer, et avec juste un peu d’aide de jQuery.
      • Nous pouvons également ajouter des fonctionnalités d’interface utilisateur attrayantes telles que des informations détaillées sur les fichiers et des commentaires de progression.
      • Ce qui suit est une capture d’écran qui montre le résultat final de ce projet:
    2. Tâches
      • Pour terminer ce projet, nous devrons effectuer les tâches suivantes:
        1. Création de la page et du wrapper de plugin
        2. Génération du balisage sous-jacent
        3. Ajout de gestionnaires d’événements pour la réception de fichiers à télécharger
        4. Affichage de la liste des fichiers sélectionnés
        5. Retrait de fichiers de la liste de téléchargement
        6. Ajout d’un indicateur de progression de l’interface utilisateur jQuery
        7. Téléchargement de l’élément sélectionné files
        8. Reportage du succès et rangement



    3. Création de la page et du wrapper du plugin
        • Dans cette tâche, nous allons créer la page qui établit un lien vers les ressources requises, ainsi que l’ajout de l’encapsuler dans lequel notre plugin vivra.
        • La nouvelle page doit être liée à la feuille de style de l’interface utilisateur jQuery afin que nous obtenions le style requis par le widget Progressbar, ainsi que la feuille de style pour ce projet dans le <head> de la page, directement après le lien existant vers css:
        • ……………….

        • Tout ce dont notre plugin aura besoin est un conteneur dans lequel le widget peut restituer le balisage requis. Dans le <body> de la page.
        • En plus de créer un lien vers le fichier de script qui contient le code de notre plugin, nous devrons également appeler le plugin afin de l’initialiser. Directement après l’existant <script>
        • L’encapsuleur du plugin est une construction simple que nous utiliserons pour initialiser le widget. Dans uploader.js, ajoutez le code suivant:
        • 
          ;(function ($) {
               var defaults = { 
                   strings: { 
                       title: "Up - A jQuery uploader",
                       dropText: "Drag files here", 
                       altText: "Or select using the button",
                       buttons: { choose: "Choose files",
                       upload: "Upload files" },
                       tableHeadings: [ "Type", "Name", "Size", "Remove all x" 
                      ]
                      } 
                  }
                  function Up(el, opts) { 
                      this.config = $.extend(true, {}, 
                          defaults, opts); 
                          this.el = el; 
                          this.fileList = []; 
                          this.allXHR = []; 
                      }
                      $.fn.up = function(options) { 
                          new Up(this, options);
                          return this; };
          }(jQuery));
      • Explication
        • l’élément <script> que nous ajoutons au bas de l’élément <body> appelle notre méthode de plugin afin d’invoquer le plugin, c’est ainsi que quelqu’un qui utilise notre plugin l’invoquerait
        • Dans notre script fichier, nous commençons avec un point-virgule et une fonction anonyme immédiatement invoquée. Le point-virgule prend en charge la nature modulaire des plugins jQuery et protège notre plugin des autres plugins qui n’arrêtent pas l’exécution correctement.
        • Si un autre plugin utilisé sur la page ne termine pas sa déclaration ou expression finale par un point-virgule, et que nous ne démarrons pas notre plugin par un point-virgule, cela peut produire des erreurs de script qui empêchent notre plugin de fonctionner.
        • Nous utilisons une fonction anonyme comme enveloppe pour notre plugin et l’invoquons immédiatement avec un jeu de parenthèses supplémentaire après le corps de la fonction. Nous pouvons également nous assurer que notre plugin fonctionne avec la méthode noConflict() de jQuery en scopant localement le caractère $ dans notre plugin et en passant l’objet jQuery dans la fonction anonyme comme argument.
        • Dans la fonction anonyme, nous définissons d’abord un littéral d’objet appelé defaults qui sera utilisé comme objet de configuration pour notre plugin. Cet objet contient un autre objet appelé chaînes, qui est l’endroit où nous stockons tous les différents bits de texte qui sont affichés dans divers éléments.

    4. Génération du balisage sous-jacent
      • Dans cette tâche, nous allons ajouter une méthode d’initialisation à notre plugin qui générera le balisage requis dont le widget a besoin
      • Tout d’abord, nous devons ajouter le code suivant directement après la fonction constructeurUp() dans projet02.js:
      • Up.prototype.init = function() { 
                        var widget = this, 
                        strings = widget.config.strings, container = $("<article/>", { "class": "up" }),
                        heading = $("<header/>").appendTo(container), 
                        title = $("</h1>", { text: strings.title }).appendTo(heading), 
                        drop = $("</div>", {
                            "class": "up-drop-target", html: $("</h2>", 
                            { text: strings.dropText }) }).appendTo(container), 
                            alt = $("</h3>", { text: strings.altText }).appendTo(container),
                             upload = $("</input>", 
                             { type: "file" }).prop("multiple", true).appendTo(container),
                              select = $("", { href: "#", "class": "button up-choose", 
                              text: strings.buttons.choose }).appendTo(container),
                               selected = $("</a>", { "class": "up-selected" }).appendTo(container), 
                               upload = $("", { href: "#", "class": "button up-upload", 
                               text: strings.buttons.upload }).appendTo(container); 
                               widget.el.append(container);
                            }
      • Nous devons également appeler cette méthode new init(). Modifiez la méthode ajoutée au fnobject de jQuery afin qu’elle apparaisse comme suit:
      • $.fn.up = function(options) { 
            new Up(this, options).init(); return this;
        };
        
      • Nous pouvons également ajouter le CSS pour le balisage généré par le plugin. Dans projet02.css, ajoutez le style suivant:
      • article.up { 
            width:90%; 
            padding:5%; 
        }
        article.up input { 
            display:none; 
        }
        .up-drop-target { 
            height:10em; 
            border:5px dashed #ccc; 
            border-radius:5px; 
            margin-bottom:1em; 
            text-align:center;
        }.up-drop-target h2 { 
            margin-top:-.5em; 
            position:relative; top:50%; 
        }.up-selected { 
            margin:1em 0; 
            border-bottom:1px solid #ccc; 
        }
    5. Explication
      • Nous pouvons ajouter une méthode init() qui prend soin de créer et d’injecter le balisage à partir duquel le widget est construit en l’ajoutant au prototype de notre constructeur. Tous les objets créés par le constructeur hériteront de la méthode.
      • Nous stockons d’abord l’objet this, qui à l’intérieur de la méthode init() fait toujours référence à la collection d’éléments jQuery, afin que nous puissions facilement y faire référence à l’intérieur des gestionnaires d’événements, que nous ajouterons dans la tâche suivante.
      • Nous étendons également localement la propriété strings pour rendre la résolution légèrement plus rapide, car nous nous référons fréquemment à cette propriété afin d’ajouter les chaînes de texte visibles à l’interface utilisateur visible du widget.
      • Ensuite, nous créons les nouveaux éléments HTML et stockons chacun d’eux dans des variables. Cela signifie que nous pouvons créer le conteneur et y ajouter tous les éléments requis pendant qu’il est encore en mémoire, puis injecter le widget entier dans le DOM de la page en une seule fois, au lieu de modifier à plusieurs reprises le DOM et d’ajouter les éléments un par un .
      • Le conteneur externe du widget est un élément <article> qui a un nom de classe pour un style facile. La spécification HTML5 décrit un <article> en tant que widget interactif autonome, donc je pense que c’est le conteneur parfait pour notre widget. Bien que tout aussi pertinent, le <article> ne se limite pas à ce que nous qualifierions traditionnellement d ‘”article” – par exemple, un blog / une nouvelle ou un article de style éditorial.
      • Nous avons un <header> élément pour contenir l’en-tête principal du widget, dans lequel nous utilisons un standard <h1>. Nous utilisons également deux éléments <h1> à l’intérieur du widget pour afficher les différentes sections (la zone de glisser-déposer et le fichier plus traditionnel
      • L’élément <input> a un attribut type de fichier et reçoit également le multiple attribut, en utilisant la méthode jQuery prop(), afin que plusieurs fichiers puissent être téléchargés dans les navigateurs compatibles.
      • Nous ajoutons également un élément <a> directement après la <input>, que nous utiliserons pour ouvrir la boîte de dialogue Ouvrir utilisée pour sélectionner les fichiers à télécharger. Le problème avec le type file standard <input>, c’est qu’il n’y a pas de standard!

    6. Ajout de gestionnaires d’événements pour la réception de fichiers à télécharger
      • Nous pouvons utiliser la méthode init() que nous avons ajoutée dans la dernière tâche pour attacher les gestionnaires d’événements dont notre widget aura besoin pour gérer les fichiers sélectionnés pour le téléchargement. Cela peut se produire soit lorsque des fichiers sont déposés sur la cible de dépôt, soit lorsqu’ils sont sélectionnés à l’aide du bouton.
      • Directement après avoir ajouté les nouveaux éléments HTML au conteneur à la fin de la méthode init() dans projet02.js (mais toujours dans la méthode init()), ajoutez le code suivant:
      •                         widget.el.on("drop change dragover", "article.up", function(e) { 
                                    if (e.type === "dragover") { 
                                        e.preventDefault();
                                        e.stopPropagation(); 
                                        return false; 
                                    } else if (e.type === "drop") { 
                                        e.preventDefault();
                                        e.stopPropagation(); 
                                        widget.files = e.originalEvent.dataTransfer.files; 
                                    } else { 
                                        widget.files = widget.el 
                                        .find("input[type='file']")[0] 
                                        .files; 
                                    } 
                                    widget.handleFiles();
                                });
      • Explication
        • Nous utilisons d’abord la méthode on() de jQuery, en mode délégation d’événement, pour attacher un gestionnaire d’événements au conteneur externe du widget. Nous spécifions l’événement click comme premier argument et un sélecteur qui correspond à notre bouton avec le nom de classe up-choose comme second argument.
        • Dans la fonction de gestionnaire passée à on() comme troisième argument, nous empêchons d’abord le comportement par défaut de le navigateur en utilisant preventDefault() de JavaScript, puis déclencher un événement de clic pour l’élément caché <input> utilisé pour sélectionner les fichiers à télécharger. Cela entraînera l’ouverture de la boîte de dialogue Fichier dans le navigateur et permettra la sélection des fichiers.
        • Nous avons ensuite attaché un autre gestionnaire d’événements. Cette fois, nous recherchons les événements de drop, dragover, et change.
        • L’événement drop sera déclenché lorsque des fichiers sont déposés dans la zone drop, l’événement dragover sera déclenché pendant que les fichiers sont maintenus sur la zone drop et l’événement change sera déclenché si des fichiers sont supprimés.

    7. Affichage de la liste des fichiers sélectionnés
      • Dans cette tâche, nous pouvons remplir le <div> nous avons créé afin d’afficher la liste des fichiers qui ont été sélectionnés pour le téléchargement. Nous allons construire un tableau où chaque ligne du tableau répertorie un seul fichier avec des informations telles que le nom et le type du fichier.
      • Directement après la méthode init () dans projet02.js, ajoutez le code suivant:
      • Up.prototype.handleFiles = function() { 
                                    var widget = this, container = widget.el.find("div.up-selected"), 
                                    row = $("</tr>"), cell = $("</td>"), remove = $("</a>", { href: "#" }), 
                                    table;
                                    if (!container.find("table").length) { table = $("</table>"); 
                                    var header = row.clone().appendTo(table), 
                                    strings = widget.config.strings.tableHeadings; 
                                    $.each(strings, function(i, string) { 
                                        var cs = string.toLowerCase().replace(/\s/g, "_"), 
                                        newCell = cell.clone() 
                                        .addClass("up-table-head " + cs) 
                                        .appendTo(header); if (i === strings.length - 1) { 
                                            var clear = remove.clone() 
                                            .text(string) 
                                            .addClass("up-remove-all"); 
                                            newCell.html(clear).attr("colspan", 2); 
                                        } else { newCell.text(string); } 
                                    }); 
                                } else {
                                     table = container.find("table");
                                    } 
                                    $.each(widget.files, function(i, file) { 
                                        var fileRow = row.clone(), 
                                        filename = file.name.split("."), 
                                        ext = filename[filename.length - 1], 
                                        del = remove.clone() .text("x") 
                                        .addClass("up-remove"); cell.clone() 
                                        .addClass("icon " + ext) .appendTo(fileRow); 
                                        cell.clone() .text(file.name).appendTo(fileRow); 
                                        cell.clone() .text((Math.round(file.size / 1024)) + " kb") 
                                        .appendTo(fileRow);
                                        cell.clone().html(del).appendTo(fileRow); 
                                        cell.clone().html("<div class='up-progress'/>") 
                                        .appendTo(fileRow); 
                                        fileRow.appendTo(table); 
                                        widget.fileList.push(file); 
                                    }); 
                                    if (!container.find("table").length) { 
                                        table.appendTo(container); 
                                    }
                                }
         
      • Nous pouvons également ajouter du CSS supplémentaire pour le nouveau balisage que nous avons créé. Ajoutez le code suivant au bas de projet02.css:
      • .up-selected table { width:100%; border-spacing:0; margin-bottom:1em;}
        .up-selected td { padding:1em 1% 1em 0; 
            border-bottom:1px dashed #ccc; font-size:1.2em;}
        .up-selected td.type { width:60px; }
        .up-selected table { width:100%; border-spacing:0; margin-bottom:1em;}
        .up-selected td { padding:1em 1% 1em 0; 
            border-bottom:1px dashed #ccc; font-size:1.2em;}
        .up-selected td.type { width:60px; }
        .up-selected td.name { width:45%; }
        .up-selected td.size { width:25%; }
        .up-selected td.remove_all_x { width:20%; }
        .up-selected tr:last-child td { border-bottom:none; }
        .up-selected a { font-weight:bold; text-decoration:none;}
        .up-table-head { font-weight:bold; }
        .up-remove-all { color:#ff0000; }
        .up-remove { display:block; width:17px; height:17px; 
            border-radius:500px; text-align:center; 
            color:#fff; background-color:#ff0000;}
            .icon { background:url(../img/page_white.png) no-repeat 0 50%; }
            .doc, .docx { background:url(../img/doc.png) no-repeat 0 50%; }
            .exe { background:url(../img/exe.png) no-repeat 0 50%; }
            .html { background:url(../img/html.png) no-repeat 0 50%; }
            .pdf { background:url(../img/pdf.png) no-repeat 0 50%; }
            .png { background:url(../img/png.png) no-repeat 0 50%; }
            .ppt, .pptx { background:url(../img/pps.png) no-repeat 0 50%; }
            .txt { background:url(../img/txt.png) no-repeat 0 50%; }
            .zip { background:url(../img/zip.png) no-repeat 0 50%; }
      • Explication
        • Nous avons commencé par ajouter la méthode handleFiles() au prototype du widget, en faisant fonctionner la méthode appel widget.handleFiles() que nous avons ajoutée à la fin de la dernière tâche. Il a été ajouté exactement de la même manière que la méthode init() plus tôt, et tout comme dans init(), cet objet pointe vers l’instance du widget à l’intérieur de handleFiles (). Cela facilite l’accès à l’élément sur la page, aux options de configuration et à la liste de fichiers sélectionnée.
        • À l’intérieur de la méthode, nous avons d’abord créé une série de variables. Comme dans la méthode
        • init()
        • , nous créons une variable locale appelée widget qui stocke l’objet this. Nous n’ajouterons aucun gestionnaire d’événements à cette méthode, nous n’avons donc pas à le faire, mais nous accédons à l’objet plusieurs fois, il est donc logique de le mettre en cache dans une variable.

    8. Retrait de fichiers de la liste de téléchargement
        • Dans cette tâche, nous allons ajouter les gestionnaires d’événements qui feront fonctionner les liens Supprimer et Supprimer tous les éléments de la nouvelle liste de fichiers. Nous pouvons attacher les gestionnaires d’événements au même endroit que nous avons ajouté d’autres gestionnaires d’événements plus tôt pour garder les choses organisées.
        • Dans projet02.js, dans la méthode init() du widget et directement après les appels existants à la méthode on() de jQuery, ajoutez le nouveau code suivant:
        •  widget.el.on("click", "td a", function(e) { 
                                      var removeAll = function() { 
                                          widget.el.find("table").remove();
                                           widget.el.find("input[type='file']").val(""); 
                                           widget.fileList = []; } 
                                           if (e.originalEvent.target.className == "up-remove-all") { 
                                               removeAll(); 
                                              } else { 
                                                  var link = $(this), 
                                                  removed, 
                                                  filename = link.closest("tr") .children() .eq(1).text(); 
                                                  link.closest("tr").remove(); $.each(widget.fileList, function(i, item) { 
                                                      if (item.name === filename) {
                                                           removed = i; } 
                                                          }); 
                                                          widget.fileList.splice(removed, 1); 
                                                  if (widget.el.find("tr").length === 1) { 
                                                      removeAll(); } 
                                                  }
                                              });
      • Explication

    9. Ajout d’un indicateur de progression de l’interface utilisateur jQuery
        • Dans cette tâche, nous allons ajouter les éléments et le code d’initialisation requis par le widget jQuery UI Progressbar. Le widget ne fera rien pour le moment car nous ne téléchargerons rien avant la prochaine tâche, mais nous devons tout câbler prêt.
        • Nous allons ajouter une méthode initProgress() au prototype de notre widget pour sélectionner le <div> les éléments que nous avons ajoutés à l’élément et les convertissons en widgets Progressbar. Nous pouvons également ajouter la méthode qui sera utilisée pour mettre à jour les Progressbars.
        • Directly after thehandleFiles() method, add the following code:
        • Up.prototype.initProgress = function() { 
                                      this.el.find("div.up-progress").each(function() { 
                                          var el = $(this); 
                                          if (!el.hasClass("ui-progressbar")) { 
                                              el.progressbar(); } 
                                          });
                                      }
        • Ensuite, nous devrons appeler cette méthode après avoir ajouté de nouvelles lignes à <table>. Ajoutez l’appel suivant à notre nouvelle méthode à la fin de la méthode handleFiles():
        • widget.initProgress();
        • Nous pouvons maintenant ajouter le code qui met à jour la barre de progression. Ajoutez le code suivant directement après la méthode initProgress() que nous venons d’ajouter
        • 
          Up.prototype.handleProgress = function(e, progress) { 
                                          var complete = Math.round((e.loaded / e.total) * 100); 
                                          progress.progressbar("value", complete);
                                      }
        • Nous avons également besoin d’un tout petit peu de CSS pour les nouvelles barres de progression. Ajoutez le code suivant à la fin de uploader.css:
        • .up-progress { height:1em; width:100px; position:relative; top:4px; }
      • Explication

    10. Téléchargement des fichiers sélectionnés
        • Nous avons maintenant une liste de fichiers attachés à l’instance de notre plugin prêts à être téléchargés. Dans cette tâche, nous ferons exactement cela et téléchargerons les fichiers de manière asynchrone à l’aide de jQuery. Ce comportement sera lié au bouton Télécharger les fichiers que nous avons ajouté au balisage généré par le plugin.
        • Nous pouvons également utiliser cette tâche pour mettre à jour nos barres de progression avec la progression actuelle de chaque fichier en cours de téléchargement.
        • Comme il s’agit d’un autre gestionnaire d’événements, nous l’ajouterons dans la méthode init() avec tous les autres gestionnaires d’événements afin qu’ils soient tous conservés au même endroit. Ajoutez le code suivant à la fin de la méthode init(), après les gestionnaires d’événements existants:
        •  widget.el.on("click", "a.up-upload", function(e) { 
                                                  e.preventDefault(); 
                                                  widget.uploadFiles();});
        • Ajoutez ensuite la méthode new uploadFiles (). Cela peut aller après les méthodes liées au progrès que nous avons ajoutées dans la dernière tâche:
        •  Up.prototype.uploadFiles = function() { 
                                                      var widget = this, a = widget.el.find("a.up-upload"); 
                                                      if (!a.hasClass("disabled")) { a.addClass("disabled"); 
                                                      $.each(widget.fileList, function(i, file) { 
                                                          var fd = new FormData(), 
                                                          prog = widget.el .find("div.up-progress") .eq(i); 
                                                          fd.append("file-" + i, file); 
                                                          widget.allXHR.push($.ajax({ type: "POST", url: "/upload.asmx/uploadFile", 
                                                          data: fd, contentType: false, processData: false, xhr: function() { 
                                                              var xhr = jQuery.ajaxSettings.xhr(); 
                                                              if (xhr.upload) {
                                                                  xhr.upload.onprogress = function(e) { 
                                                                      widget.handleProgress(e, prog); 
                                                                  } 
                                                              } return xhr; } 
                                                          })); 
                                                      }); 
                                                  }}
      • Explication



      Source: inspiration du livre JQuery Hotshot : Ten Practical Projects That Exercise Your Skill, Build Your Confidence, and Help You Master JQuery
      Auteurs: Wellman, Dan
      Informations sur la publication: Birmingham, U.K. : Packt Publishing. 2013

Abonnez vous à notre chaîne YouTube gratuitement