J'utilise GULP pour :
- générer et minifier les CSS à partir de fichiers SCSS
- concaténer et minifier les JS.
Les fichiers sources sont situés dans le répertoire /src/
Les fichiers générés, les pages HTML et les images sont situés dans le répertoire /dist/.
Pour installer la routine gulp, dans une console, se placer au niveau du répertoire de dev et lancer la commande npm install.
Ne pas tenir compte des alertes de sécurité qui proviennent de composants qui ne sont pas utilisés...
Pour générer les fichiers, dans une console, se placer au niveau du répertoire de dev et lancer la commande gulp.
Tous les fichiers *.scss présent dans le répertoire /src/scss/ et ses sous-dossiers sont concaténés dans le fichier unique /dist/css/styles.css.
Tous les fichiers *.js présent dans le répertoire /src/js/ sont concaténés dans le dossier /dist/javascripts/.
Tous les fichiers *.js présents dans un sous-dossier de /src/js/ sont concaténés dans un fichier unique du nom du répertoire dans le dossier /dist/javascripts/.
Par exemple, tous les fichiers *.js présents dans le dossier /src/js/plugins/ sont concaténés et minifiés dans le fichier /dist/javascripts/plugins.js.
Un bloc de filtres de recherche est un <div class="filters"> contenant un <form> avec un <fieldset> (lui-même contenu dans un <div class="mobile-scrollable" pour avoir une scrollbar sous mobile) avec des checkboxes format généré par Drupal + 1 <input type="submit"> et 1 <input type="reset"> placés dans un <div class="actions">.
Il peut être affiché n'importe où et prend toute la largeur de son conteneur.
Les retours serveur sont séparés en deux éléments : la liste et la map.
La cible du retour AJAX pour la liste est l'élément <div class="js-ajax-list">.
Le retour attendu est une liste de pushes à un seul élément par ligne <ul class="push-list push-1-items"> (voir plus bas pour le détail de la structure HTML).
La cible du retour AJAX pour la map est l'élément <div id="js-leaflet-bigmap">.
Voir plus bas pour le détail.
La zone de filtres regroupe plusieurs blocs .filters dans un seul et même form.
Les blocs .filters sont très proches du filtre simple mais n'ont pas de <form> ni de <div class="mobile-scrollable">, celui-ci (classe spécifique .mobile-scrollable-filters) encadre tous les .filters.
Tous les styles sont déclarés dans le fichier /src/scss/modules/filters.scss
L'aspect étant très différent entre desktop et mobile, les déclarations des classes sont bien séparées avec @media.
Les filtres sont séparés en 3 blocs de forme "drop-down menu".
Chaque bloc de filtres contient ses boutons reset et submit.
Le reset vide les values des checkbox du bloc et déclenche le submit du form (tous les filtres sont donc envoyés en même temps).
Le submit déclenche le submit du form (tous les filtres sont donc envoyés en même temps).
Les filtres sont tous regroupés et ne s'affichent qu'au click sur le bouton flottant "Filtrer".
Les boutons reset et submit de chaque bloc de filtres sont masqués.
Un bouton submit général est affiché.
Le reset vide les values des checkbox et déclenche le submit du form.
Les fonctions sont déclarées dans le fichier /src/js/general.js et ne sont exécutées que lorsqu'un élément .multi-filters est présent dans le DOM.
À chaque élément .open-filters est appliqué un event click qui ajoute ou enlève la classe .open à l'élément .filters sibling.
Les boutons reset de chaque bloc de filtres vident les value de leurs checkbox puis déclenchent le submit du formulaire.
De même, le reset principal, après son action de base, déclenche le submit du form.
Les textes du bouton ouvert/fermé sont placé dans des attributs data-text-open et data-text-close de la balise <a>.
Le lien est en position fixed et placé tout de suite après l'ouverture de la <section>.
Le conteneur des filtres .multi-filters est identifié par un id unique.
Cet id est indiqué dans un attribut data-target du bouton d'ouverture :data-target="#js-multi-filters" (avec le dièse).
L'ouverture des filtres (ajout de classe .open) déclenche également le blocage du scroll du body et le masquage de l'éventuel bouton d'ouverture de la map (voir plus bas).
La fermeture des filtres revient à la normale...
La mise en place de maps Leaflet nécessite le rajout de fichiers CSS et JS spécifiques :
JS en bas de page
Si votre serveur de dev et le serveur de prod final sont en https, je recommande de pointer vers https://unpkg.com pour bénéficier des mises à jour automatiques.
Sinon, pointer vers le fichier local /javascripts/leaflet.js.
CSS, dans le <head> avant l'appel aux styles du site :
De façon à pouvoir styler correctement les markers et popups de la map leaflet, j'ai mis en place un process javascript qui pourra éventuellement vous servir de base pour la dynamisation.
J'ai placé le code dans un fichier *.js séparé pour vous permettre de ne pas l'inclure dans les pages dynamisées.
/src/js/projets-map.js pour la version non-minifiée.
/dist/javascripts/projets-map.js pour la version minifiée.
J'ai utilisé une structure JSON pour faciliter la génération des markers / popups leaflet.
/dist/json/projets-map.php
Une fonction callMapData() simule l'appel au webService en récupérant les datas du formulaire identifié #js-projects-form,charge le json en Ajax et exécute la fonction showMap() qui affiche la map et ses markers..
showMap() affiche la map leaflet dans l'élément identifié #js-leaflet-bigmap.
J'applique le TileLayer de base, c'est ici que vous pourrez choisir le TileLayer final.
Il construit ensuite tous les markers et leurs popups avec des document.createElement.
leaflet génère le code HTML des popup à la volée lorsqu'on clique sur le marker.
L'initialisation des sliders doit donc être effectuée à ce moment seulement (voir plus bas pour l'initialisation des sliders).
Il faut ajouter un évènement click à chaque marker :
Chaque item de la liste doit avoir une classe .js-push-map et est identifié par l'ID du projet avec le préfixe "push-".
Leaflet ne permet pas d'identifier directement un marker. Il faut donc passer par une petite ruse :
On stocke les markers présents sur la map au moment de leur création dans un objet curMarkers dans lequel chaque marker est identifié par l'ID présent dans le json.
On utilise ensuite cet objet pour retrouver le marker correspondant.
J'ai créé deux petites fonctions pour le rollover liste -> map :
Le fichier projets-map.js contient également la déclaration des autres map du site de démo qui seront remplacées par vos propres déclarations...
Pour les mobiles, la map est masquée par défaut et s'affiche en plein écran au click sur le bouton .open-map-mobile qui est position fixed en haut de l'écran.
Les textes ouvert / fermé sont stockés dans des attributs data-text-open et data-text-close.
L'ID de la map (avec le dièse) à ouvrir est stocké dans un attribut data-target.
Le code est placé dans le fichier general.js.
L'ouverture de la map (ajout de classe .open) déclenche également le changement du texte du bouton, le blocage du scroll du body, la fermeture du .main-header et le masquage de l'éventuel bouton d'ouverture des filtres (voir plus haut).
La fermeture des filtres revient à la normale...
Peuvent être affichées n'importe où dans le site.
Ce sont des liste non-ordonnées.
Le slider prend la largeur totale de son conteneur.
L'image placée dans un conteneur .slides-img prend toute la largeur.
La hauteur du slider dépend donc de la hauteur de l'image de chaque slide. Il se resize.
L'éventuel contenu de chaque slide est positionné par-dessus le visuel en absolute.
Le constructeur est inclus dans le fichier /dist/javascripts/plugins.js, /src/js/plugins/tiny-slider.js
Il s'agit du tiny-slider développé par William Lin.
Déclaration des sliders dans /javascripts/general.js.
Tous les éléments avec la classe .slides sont automatiquement traités :
L'appel au constructeur est inclus dans le fichier /javascripts/XXL.js.
Les paramètres sont :
container : l'élément qui va contenir le slider (div.slider);
items : le nombre de slides visibles;
slideBy : le nombre de slides déplacées au clic sur flèches ou bullets;
autoHeight : le slider change de hauteur selon hauteur de la slide active;
speed : la vitesse de déplacement;
autoplay : booléen détermine autoplay;
autoplayTimeout : tempo entre chaque autoplay.
/src/scss/components/_tiny-slider.scss pour les styles nécessaires au bon fonctionnement du plugin.
/src/scss/modules/_slider.scss pour les styles de mise en forme spécifiques au projet.
Les galeries utilisent aussi le constructeur de sliders tinySlider.
Même structure HTML que les sliders simples sauf leur classe générique qui n'est pas .sliders mais .gallery-slider.
Un élément supplémentaire est prévu pour les légendes :
Dans le fichier general.js.
Déclaration des galeries, tous les éléments avec la classe .slides sont automatiquement traités :
Ouverture des galeries par bouton avec classe .open-gallery contenant l'ID de la galerie dans un attribut data-gallery-id.
On peut choisir quel slide est affiché par défaut via un attribut data-index (le premier a l'indice 0).
L'ouverture d'une galerie (ajout d'une classe .open à la galerie) déclenche également les actions suivantes :
- blocage scroll body;
- on cache le .main-header;
- on déclare les actions du clavier.
Processus inverse à la fermeture...
La galerie est manipulable via le clavier.
- Flèche gauche: slide précédent.
- Flèche droite: slide suivant.
- Escape: fermeture de la galerie.
Des layouts de deux colonnes avec la méthode FLEX peuvent être affichés n'importe où.
Il suffit de respecter les structures suivantes :
Sur mobile, les colonnes sont forcées à 100% de largeur et se placent l'une en dessous l'autre.
Sur petites tablettes <769px, les 2 colonnes sont forcées à 50%.
J'ai prévu les largeurs repérées sur les créas (+ leur inversion).
1ere colonne 70% / 2e colonne 30%.
1ere colonne 60% / 2e colonne 40%.
1ere colonne 50% / 2e colonne 50%.
1ere colonne 40% / 2e colonne 60%.
1ere colonne 30% / 2e colonne 70%.
1ere colonne 66% / 2e colonne 34% (les Projets).
Exemple 70-30
Le player vidéo peut lire des vidéos Youtube, Viméo ou MP4 uploadé sur le serveur.
L'URL de la vidéo est à placer dans un attribut data-video du lien .play-video.
URL complète pour youtube ou viméo : https://www.youtube.com/watch?v=G7eIa1w_mVU ou https://vimeo.com/382054256
Chemin relatif vers le fichier MP4 :videos/Braziloid.mp4
Pour appliquer l'ouverture du player à un lien, il faut écrire le code :
La fonction playVideo est dans le fichier src/js/XXL/XXL.js.
Afin de ne pas avoir à ré-écrire tout le code XML des SVG à chaque fois, j'ai utilisé une méthode d'includes.
Tous les includes sont placés dans l'include /dist/includes/_header.php ainsi ils sont bien présents dans chaque page du site.
La valeur currentColor permet de récupérer la couleur de texte déclarée au parent du svg, pratique pour les effets de rollover par ex.
Pour des mises en forme simples sur l'ensemble du site.
Couleurs du texte.
.t-blue, .t-orange, .t-green, .t-grey, .t-black ou .t-white
Couleurs du background sans padding.
.b-blue, .b-orange, .b-green, .b-grey, .b-black ou .b-white
Couleurs du background + padding 3.2rem Desktop / 1.6rem mobile.
.bg-grey, .bg-orange, .bg-blue, .bg-green ou .bg-black
Texte en capitales.
.t-up
Image pleine largeur.
.full-width
Applicable au conteneur de l'image ou à l'image elle-même.
Sticky, reste fixé en haut de l'écran tant que son conteneur scrolle.
.sticky
Mobile: 16px (1.6rem) sous la nav fixed.
Desktop: 32px sous le haut de l'écran.
Angles arrondis (12px).
.radius
Listes ul avec bullet et texte décalé.
.bullet
Masquer pour les mobiles.
.no-mobile
Les étiquettes.
.label : applique border, padding et margin-right.
Couleurs de fond en rajoutant:
.blue, .orange, .grey ou .green
Les accroches.
Pour styler les textes comme intro des pages.
.accroche