J'ai finalement eu un petit créneau de libre ce weekend ça m'a permis de bosser sur ton fameux script en javascript pur ES5 (ancien mais bon). La nouvelle version que je te propose est bien commentée et fonctionne comme tu l'avait souhaité. Seul bémol, il faudrait une légère touche d'AJAX pour que l'url générée soit interprétée par le PHP et renvoie les nouveaux résultats en fonction des filtres. J'aurais pu t'aider sur cette partie, mais je n'ai pas accès à ton code source. Ce qu'il me faudrait pour t'aider ce sont des articles de test avec la même config d'article anywhere que toi pour reproduire la même chose en local par exemple ou sur un site uniquement accessible par toi et ton équipe. Pour l'instant je t'envoie ci-joint le code source revisité et ainsi que le code directement dans ce message avec les balises appropriées.
Voici l'html:
Code HTML:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <base href="https://jdf.test/"> </head> <body> <h3>Demo for Filter via url ("input:") and for Pagination</h3> <h4>Filter by Custom Field of type List (Session), not adapting styling</h4> <p><a class="btn btn-default js_dynamic_filter_session_0" href="#">Tous</a> <a class="btn btn-success js_dynamic_filter_session_1" href="?session=slot-am-1">Session 1</a> <a class="btn btn-warning js_dynamic_filter_session_2" href="?session=slot-am-2">Session 2</a> <a class="btn btn-danger js_dynamic_filter_session_3" href="?session=slot-am-3">Session 3</a></p> <hr> <h4>Filter by Custom Field of type Articles Field (Room)</h4> <a class="btn btn-default js_dynamic_filter_room_0" href="#">Toutes</a> <a class="btn btn-default js_dynamic_filter_room_1" href="?room=35">Amphithéatre PlanetHoster</a> <a class="btn btn-default js_dynamic_filter_room_2" href="?room=199">Salle Infomaniak</a> <a class="btn btn-default js_dynamic_filter_room_3" href="?room=200">Salle atelier</a> <hr> <h4>Filter by Tag</h4><a class="btn btn-default js_dynamic_filter_tag_0" href="#">Tous</a> <a class="btn btn-default js_dynamic_filter_tag_1" href="?tag=vendredi">Vendredi</a> <a class="btn btn-default js_dynamic_filter_tag_2" href="?tag=samedi">Samedi</a> <a class="btn btn-default js_dynamic_filter_tag_3" href="?tag=test">Test</a> <hr> <h4>Filter by Creation Date (possible to filter on yyyy-mm-dd or yyyy-mm or yyyy for example. But using >= in the filter is not foreseen</h4> <a class="btn btn-default js_dynamic_filter_date_0" href="#">Tous</a> <a class="btn btn-default js_dynamic_filter_date_1" href="?date=2019-02-04">2019-02-04</a> <a class="btn btn-default js_dynamic_filter_date_2" href="?date=2019-02">2019-02</a> <hr> <h4>Example of text based on Pagination</h4> <p>Is this page 2 or not : no</p> <p></p> <hr> <script src="app.js"></script> </body> </html>
Code:
// using some information from this post: https://usefulangle.com/post/81/javascript-change-url-parameters /** * Chaque "categorie" de filtre écoute les clics sur les "elements" de filtre * Ex: Categorie Session ecoute les clics sur les liens session 1 session 2 et session 3 * Lorsque on clique une seule fois, le filtre associé est rajouté à la categorie correspondante * grâce à son alias (ici: 'session'). * Lorsque les catégories sont "notifiée" par les élements filtrés, ces élements récupèrent la valeur de retour de la categorie qui sont les filtres actifs. * Ensuite ils groupent les filtres actifs grace à l'alias de la categorie correspondante et modifie l'url si des filtres actifs existent. * Ce système utilise le patron de conception Observateur où les categories sont les Observateurs et les elements les Sujets observés. * * convention: * classe css ajoutees pour activer les filtres: * * js_dynamic_filter_session_0 : aucun filtre pour les sessions afficher tout * (tout ce qui se termine par _0 est associé à resetFilters() qui reinitialise les filtres) * * js_dynamic_filter_session_1 : FilterItemSession1 (1er element de filtre pour les sessions de conferences) * js_dynamic_filter_session_2 : FilterItemSession2 (2e element de filtre pour les sessions de conferences) * js_dynamic_filter_session_3 : FilterItemSession3 (3e element de filtre pour les sessions de conferences) * * js_dynamic_filter_room_1 : FilterItemRoom1 (1er element de filtre pour les salles de conferences) * js_dynamic_filter_room_2 : FilterItemRoom2 (2e element de filtre pour les salles de conferences) * js_dynamic_filter_room_3 : FilterItemRoom3 (3e element de filtre pour les salles de conferences) * * @author Alexandre ELISÉ <developpeur@alexandre-elise.fr> * @license GNU GPL-2.0-or-later * @copyright 2019 * @link https://alexandre-elise.fr */ (function (global) { "use strict"; if (!('URL' in global)) { throw 'Votre navigateur ne supporte pas la fonctionnalité URL()'; } if (!('URLSearchParams' in global)) { throw 'Votre navigateur ne supporte pas la fonctionnalité URLSearchParams()'; } var selecteurs = { filtrer_par_session: 'a[class*="js_dynamic_filter_session_"]', filtrer_par_salle: 'a[class*="js_dynamic_filter_room_"]', filtrer_par_tag: 'a[class*="js_dynamic_filter_tag_"]', filtrer_par_date: 'a[class*="js_dynamic_filter_date_"]' }; var siteBaseUrl = 'https://jdf.test/'; var allowedCategories = ['session', 'room', 'tag', 'date']; var mergedObserverFilters = {}; var previousCategoryCollection = []; var jsDynamicFilterSession; var jsDynamicFilterRoom; var jsDynamicFilterTag; var jsDynamicFilterDate; var filterClickCollection = {}; var FilterCategory; var FilterItem; var FilterCategorySession; var FilterCategoryRoom; var FilterCategoryTag; var FilterCategoryDate; var FilterItemSessionCollection = []; var FilterItemRoomCollection = []; var FilterItemTagCollection = []; var FilterItemDateCollection = []; var resetFilters; var processUrlHandler; /** * reinitiliaser les filtres */ resetFilters = function () { // reinitialiser les filtres agrégés mergedObserverFilters = ''; // reinitialiser la pile des categories precedentes previousCategoryCollection = []; // reinitialiser les compteurs de clics filterClickCollection = {}; }; /** * fonction de traitement de l'url en fonction des filtres recus */ processUrlHandler = function processUrlHandler(currentUrl, category) { var url; var searchParams; url = new global.URL(currentUrl); searchParams = new global.URLSearchParams(url.search); searchParams.sort(); return searchParams.getAll(category); }; // DEBUT code des prototypes FilterCategory = function (title, alias) { this.title = title || 'MyFilterCategory'; this.alias = alias || 'my-filter-category'; this.filterItemCounter = {}; this.filterItemCollection = []; global.console.info('Title: ', this.title, 'Alias: ', this.alias); }; FilterCategory.prototype.update = function (evt) { if (!evt || !evt.click.data || !evt.click.data.filters || (evt.click.data.filters.length < 1)) { return; } var self = this; evt.click.data.filters.forEach(function (currentClickedFilter) { var separator = encodeURI(','); var idxFilter = currentClickedFilter.indexOf(separator); if (idxFilter === -1) { if (self.filterItemCounter[currentClickedFilter] === undefined) { self.filterItemCounter[currentClickedFilter] = 1; self.filterItemCollection.push(currentClickedFilter); } else { self.filterItemCounter[currentClickedFilter]++; } if (self.filterItemCounter[currentClickedFilter] === 2) { var idx = self.filterItemCollection.indexOf(currentClickedFilter); if (idx !== -1) { self.filterItemCollection.splice(idx, 1); self.filterItemCounter[currentClickedFilter] = undefined; } } } else { // plusieurs filters dans un meme groupe ex: session=session1,session2,session3 currentClickedFilter.split(separator).forEach(function (currentFilterItem) { if (self.filterItemCounter[currentFilterItem] === undefined) { self.filterItemCounter[currentFilterItem] = 1; self.filterItemCollection.push(currentFilterItem); } else { self.filterItemCounter[currentFilterItem]++; } if (self.filterItemCounter[currentFilterItem] === 2) { var idx = self.filterItemCollection.indexOf(currentFilterItem); if (idx !== -1) { self.filterItemCollection.splice(idx, 1); self.filterItemCounter[currentFilterItem] = undefined; } } }); } }); return this.filterItemCollection; }; FilterItem = function (title, alias) { this.title = title || 'MyFilterItem'; this.alias = alias || 'my-filter-item'; this.observerCollection = []; global.console.info('Title: ', this.title, 'Alias: ', this.alias); }; FilterItem.prototype.registerObserver = function (observer) { this.observerCollection.push(observer); }; FilterItem.prototype.unregisterObserver = function (observer) { var index = this.observerCollection.indexOf(observer); if (index !== -1) { this.observerCollection.splice(observer); } }; FilterItem.prototype.notifyObservers = function (evt) { var currentBaseUrl = new global.URL(siteBaseUrl); var currentUrlParams = new global.URLSearchParams(currentBaseUrl.search); var newUrl; this.observerCollection.forEach(function (observer) { var currentObserverFilters; currentObserverFilters = observer.update.call(observer, evt); if (currentObserverFilters) { currentUrlParams.set(observer.alias, currentObserverFilters.join(',')); mergedObserverFilters[observer.alias] = currentObserverFilters.join(','); } }); var mergedResult = []; for (var currentMergedFilterKey in mergedObserverFilters) { if (!mergedObserverFilters.hasOwnProperty(currentMergedFilterKey)) { continue; } if (allowedCategories.indexOf(currentMergedFilterKey) !== -1) { mergedResult.push(currentMergedFilterKey + '=' + mergedObserverFilters[currentMergedFilterKey]); } } currentBaseUrl.search = mergedResult.join('&'); newUrl = currentBaseUrl.toString(); global.history.pushState({}, '', newUrl); global.console.log(newUrl); }; FilterItem.prototype.onClick = function (evt) { this.notifyObservers(evt); }; // FIN code des prototypes // Au chargement de la page global.document.addEventListener('DOMContentLoaded', function () { // Filter par session FilterCategorySession = new FilterCategory('MyFilterCategorySession', 'session'); jsDynamicFilterSession = global.document.querySelectorAll(selecteurs.filtrer_par_session); jsDynamicFilterSession.forEach(function (element, index) { if (index === 0) { element.addEventListener('click', resetFilters); } else { var ItemSession = new FilterItem('MyFilterItemSession' + (index + 1), 'my-filter-item-session-' + (index + 1)); ItemSession.registerObserver(FilterCategorySession); FilterItemSessionCollection.push(ItemSession); element.addEventListener('click', function (evt) { evt.preventDefault(); evt.stopPropagation(); ItemSession.onClick.call(ItemSession, { click: { data: { filters: processUrlHandler(evt.currentTarget.href, 'session') } } }); }); } }); // Filtrer par salle FilterCategoryRoom = new FilterCategory('MyFilterCategoryRoom', 'room'); jsDynamicFilterRoom = global.document.querySelectorAll(selecteurs.filtrer_par_salle); jsDynamicFilterRoom.forEach(function (element, index) { if (index === 0) { element.addEventListener('click', resetFilters); } else { var ItemRoom = new FilterItem('MyFilterItemRoom' + (index + 1), 'my-filter-item-room-' + (index + 1)); ItemRoom.registerObserver(FilterCategoryRoom); FilterItemRoomCollection.push(ItemRoom); element.addEventListener('click', function (evt) { evt.preventDefault(); evt.stopPropagation(); if (filterClickCollection[evt.currentTarget.href] === undefined) { filterClickCollection[evt.currentTarget.href] = 1; } else { filterClickCollection[evt.currentTarget.href]++; } ItemRoom.onClick.call(ItemRoom, { click: { data: { filters: processUrlHandler(evt.currentTarget.href, 'room') } } }); }); } }); // Filtrer par tag FilterCategoryTag = new FilterCategory('MyFilterCategoryTag', 'tag'); jsDynamicFilterTag = global.document.querySelectorAll(selecteurs.filtrer_par_tag); jsDynamicFilterTag.forEach(function (element, index) { if (index === 0) { element.addEventListener('click', resetFilters); } else { var ItemTag = new FilterItem('MyFilterItemTag' + (index + 1), 'my-filter-item-tag-' + (index + 1)); ItemTag.registerObserver(FilterCategoryTag); FilterItemTagCollection.push(ItemTag); element.addEventListener('click', function (evt) { evt.preventDefault(); evt.stopPropagation(); ItemTag.onClick.call(ItemTag, { click: { data: { filters: processUrlHandler(evt.currentTarget.href, 'tag') } } }); }); } }); // Filtrer par date FilterCategoryDate = new FilterCategory('MyFilterCategoryDate', 'date'); jsDynamicFilterDate = global.document.querySelectorAll(selecteurs.filtrer_par_date); jsDynamicFilterDate.forEach(function (element, index) { if (index === 0) { element.addEventListener('click', resetFilters); } else { var ItemDate = new FilterItem('MyFilterItemDate' + (index + 1), 'my-filter-item-date-' + (index + 1)); ItemDate.registerObserver(FilterCategoryDate); FilterItemDateCollection.push(ItemDate); element.addEventListener('click', function (evt) { evt.preventDefault(); evt.stopPropagation(); ItemDate.onClick.call(ItemDate, { click: { data: { filters: processUrlHandler(evt.currentTarget.href, 'date') } } }); }); } }); }); }(window));
Laisser un commentaire: