1ready(() => { 2 3 // Get params from WordPress wp_localize_script (Noyau\Script) 4 let currentPage = Number(PostsQueryParams.current_page) 5 6 // Get the containers' ID 7 const loadMoreBTN = document.getElementById('load-older-posts') 8 const $listingContainer = document.getElementById('post_publications') 9 const $categoryFilter = document.querySelector('#categoryFilter') 10 const $categoryButton = document.getElementsByClassName('button--filter') 11 const $countPostPerPage = document.getElementById('posts_per_page') 12 const $countTotal = document.getElementById('foundPosts') 13 const $subCategorieFilter = document.getElementById('sub-categories') 14 const $subCategoriesInput = document.getElementById('subCategoriesInput') 15 const $subCategoriesCount = document.getElementById('selectedSubCategoriesCount') 16 const $toggleSubCategoriesChoices = document.getElementById('toggleSubCategories') 17 const $toggleFilter = document.querySelector('.button--toggler') 18 const $validateFilter = document.getElementById('val
18idateSystemeFilter') 19 const $resetFilter = document.getElementById('resetSystemeFilter') 20 const $dateInput = document.getElementById('dateInput') 21 const $subCategoriesFilterContainer = document.querySelector('#subCategorieList') 22 const $dateFilterContainer = document.querySelector('#publicationDate') 23 const $keywordsFilter = document.querySelector('#keywordsFilter') 24 const $statusFilterContainer = document.querySelector('#reportStatus') 25 const $statusInput = document.getElementById('statusInput') 26 const $filters = document.querySelector('.filter__options') 27 const $resetKeywordInput = document.getElementById('keywordsReset') 28 29 // Documents 30 const $monthsFilterInput = document.querySelector('#monthsReleaseInput') 31 const $monthsFilter = document.querySelector('#monthsReleaseDate') 32 const $yearsFilterInput = document.querySelector('#yearsReleaseInput') 33 const $yearsFilter = document.querySelector('#yearsReleaseDate') 34 35 36 // Custom filters 37 const $customFiltersInput = document.querySelectorAll('.filter_custom .filter__input-container input') 38 const $customFilters = document.querySelectorAll('.filter_custom .filter__custom-container ul') 39 40 // Events 41 const $inputStartDate = jQuery('input#startDateFilterHidden'); 42 const $inputTextStartDate = jQuery('input#startDateFilter'); 43 const $inputEndDate = jQuery('input#endDateFilterHidden'); 44 const $inputTextEndDate = jQuery('input#endDateFilter'); 45 46 // Search 47 const $postTypeInput = document.querySelector('#postTypeInput') 48 const $postTypeFilter = document.querySelector('#postType') 49 50 let $archivePage = document.getElementById('archivePage') 51 let postsPerPage = 10 52 53 if (!!$archivePage) { 54 postsPerPage = $archivePage.dataset.postsperpage 55 } 56 57 // Init the PostsQuery Class 58 let Query = new PostsQuery() 59 Query._APIRoute = 'postsQuery' 60 61 62 /* 63 * INIT parts 64 */ 65 if (!!$listingContainer) { 66 67 const selectBoxes = document.querySelectorAll('.filter__input-container') 68 69 !!selectBoxes && 70 selectBoxes.forEach((selectBox) => { 71 selectBox.addEventListener('click', function () { 72 if (this.closest('.select-box').classList.contains('is-closed')) { 73 this.closest('.select-box').classList.replace('is-closed', 'is-open') 74 } else { 75 this.closest('.select-box').classList.replace('is-open', 'is-closed') 76 } 77 }) 78 }) 79 80 document.addEventListener('click', function (event) { 81 let selectBoxes = document.querySelectorAll('.select-box.is-open') 82 selectBoxes.forEach((selectBox) => { 83 if (selectBox !== null && selectBox !== event.target.closest('.select-box')) { 84 selectBox.classList.replace('is-open', 'is-closed') 85 } 86 87 if (selectBox === event.target.closest('.select-box')) { 88 let radios = selectBox ? selectBox.querySelectorAll('input[type=radio]') : [] 89 !!radios && radios.forEach((radio) => { 90 if (event.target === radio) { 91 selectBox.classList.replace('is-open', 'is-closed') 92 } 93 }) 94 } 95 }) 96 }) 97 98 let elementSelected = $filters.querySelectorAll('.selected') 99 // If no element fit the selector, we restore the "reset button" to its original state 100 if (elementSelected.length !== 0) { 101 $resetFilter.classList.remove('empty-selection') 102 } 103 104 const searchQuery = window.location.search 105 // Get the page CPT 106 window.cpt = $listingContainer.dataset.cpt 107 // Get the first count of posts (before fetching on API) 108 let countPostPerPage_HTML = $countPostPerPage.innerHTML 109 let countPostPerPage_INT = parseInt(countPostPerPage_HTML) 110 111 // Init every params 112 let initParams = new URLSearchParams(searchQuery) 113 114 if (window.cpt) { 115 Query.URLQuery = `?systemeParams=${cpt}` 116 } else { 117 let params = new URLSearchParams(searchQuery); 118 let searchedWords = String(params.get("s")); 119 Query.URLQuery = `?s=${searchedWords}` 120 } 121 122 // Init every params 123 let params = new URLSearchParams(searchQuery) 124 125 // Add view in URLQuery base 126 let view = initParams.get('view') 127 if (view) { 128 Query.URLArgs.view = {} 129 Query.URLArgs.view.parameterValue = view 130 } 131 132 // Mapping CPT â taxonomie pour les pages avec catégorie parente forcée 133 const cptTaxonomyMap = { 134 contacts: 'contacts_category', 135 events: 'events_category', 136 post: 'category', 137 documents: 'documents_category', 138 adverts: 'adverts_category', 139 consultations: 'consultations_category', 140 } 141 142 // Si catégorie parente forcée : init categoryID + taxonomy avant de charger les sous-catégories 143 if ($subCategorieFilter && $subCategorieFilter.dataset.forcedParent === '1') { 144 if ($archivePage && $archivePage.dataset.forcedCategory) { 145 window.categoryID = Number($archivePage.dataset.forcedCategory) 146 Query.URLArgs.category = {} 147 Query.URLArgs.category.parameterValue = [window.categoryID] 148 } 149 window.taxonomy = cptTaxonomyMap[window.cpt] || window.cpt + '_category' 150 151 // Si subCategories est dans l'URL, les pré-sélectionner dans le filtre
152 // pour qu'ils soient inclus dans la query initiale 153 const subCatsFromURL = params.get('subCategories') 154 if (subCatsFromURL && $subCategoriesFilterContainer) { 155 $subCategoriesFilterContainer.dataset.ids = subCatsFromURL 156 Query.URLArgs.subCategories = {} 157 Query.URLArgs.subCategories.parameterValue = subCatsFromURL.split(',') 158 } 159 160 displaySubCategories() 161 } 162 163 for (const [key, value] of params.entries()) { 164 if (key.includes('category') && value && window.cpt !== 'jobs') { 165 window.categoryID = Number(value) 166 167 if ($categoryFilter) { 168 let $categoryCheckbox = $categoryFilter.querySelector('input[data-id="' + value + '"]') 169 if ($categoryCheckbox) { 170 window.categorySlug = $categoryCheckbox.dataset.slug 171 window.taxonomy = $categoryCheckbox.dataset.taxonomy 172 $validateFilter.classList.remove('empty-selection') 173 } else { 174 // Pas de checkbox correspondante : fallback comme avant 175 if ($subCategoriesFilterContainer) { 176 $subCategoriesFilterContainer.dataset.ids = value 177 } 178 window.taxonomy = key 179 } 180 displaySubCategories() 181 } else if ($subCategorieFilter && $subCategorieFilter.dataset.forcedParent === '1') { 182 // Catégorie parente forcée : taxonomy et categoryID déjà initialisés plus haut 183 } else { 184 if ($subCategoriesFilterContainer) { 185 $subCategoriesFilterContainer.dataset.ids = value 186 } 187 window.taxonomy = key 188 displaySubCategories() 189 } 190 } 191 } 192 193 /** 194 * CATEGORY Parts 195 * 196 * */ 197 198 // Handle category select 199 if (!!$categoryFilter) { 200 let $categorieInputs = $categoryFilter.querySelectorAll('input[name="category"]') 201 $categorieInputs.forEach(($categorieInput) => { 202 $categorieInput.addEventListener('change', () => { 203 204 if ($subCategorieFilter) { 205 delete Query.URLArgs.subCategories 206 207 $subCategorieFilter.dataset.disabled = 'disabled' 208 $subCategoriesFilterContainer.dataset.ids = '' 209 // Prepare the toggler for it's next action (select all) 210 $toggleSubCategoriesChoices.dataset.selected = 'true' 211 212 // Restore the text of the input 213 $subCategoriesInput.value = 'Sous-catégories' 214 // Restore the text in the toggler 215 $toggleSubCategoriesChoices.innerHTML = 'Tout sélectionner' 216 // Restore the default style for an inactive filter 217 $subCategoriesInput.classList.remove('selected') 218 219 let $subCategoriesCheckboxes = $subCategoriesFilterContainer.querySelectorAll('input[type="checkbox"]:checked') 220 // Unchecked all the sub categories checkboxes 221 for (let checkbox of $subCategoriesCheckboxes) { 222 checkbox.checked = false 223 } 224 } 225 226 // Get the selected range date 227 let $categoryCheckbox = $categoryFilter.querySelector('input[type="radio"]:checked') 228 document.querySelector('#filter_category').classList.add('selected') 229 window.categoryID = Number($categoryCheckbox.dataset.id) 230 231 // Store the category slug 232 window.categorySlug = $categoryCheckbox.dataset.slug 233 234 // Store the category taxonomy 235 window.taxonomy = $categoryCheckbox.dataset.taxonomy 236 237 // Execute the function that will get the subcategories and add them
238 239 document.querySelector('#filter_category').value = $categoryCheckbox.dataset.label ?? $categoryCheckbox.getAttribute('data-placeholder') 240 $validateFilter.classList.remove('empty-selection') 241 242 displaySubCategories() 243 updateCustomFiltersVisibility(getActiveCategoryIDs()) 244 245 }) 246 }) 247 248 249 } 250 251 /*** 252 * This listener is used to 253 * 1. Display the number of selected sub categories in the $subCategoriesCount 254 * 2. Display the subcategories' names in the $subCategoriesFilterContainer 255 * ***/ 256 if (!!$subCategoriesFilterContainer) { 257 $subCategoriesFilterContainer.addEventListener('click', (e) => { 258 259 260 // Get the list of the checked input in the UL 261 let $subCategoriesCheckboxes = $subCategoriesFilterContainer.querySelectorAll('input[type="checkbox"]:checked') 262 263 // Init values 264 let value = '' 265 266 // We control that the number of checked element is === 0 267 // If it's true we remove all the data register during the subCatogories choice 268 // And restore to original condition 269 if ($subCategoriesCheckboxes.length === 0) { 270 271 // Remove the argument from the URL builder 272 delete Query.URLArgs.subCategories 273 274 // Restore the state and the text of the sub categories choices toggler 275 $toggleSubCategoriesChoices.dataset.selected = 'true' 276 $toggleSubCategoriesChoices.innerHTML = 'Tout sélectionner' 277 $subCategoriesCount.innerHTML = "0 sélectionnée" 278 279 // Restore the original $subCategoriesInput condition 280 $subCategoriesInput.value = 'Sous-catégories' 281 $subCategoriesInput.classList.remove('selected') 282 283 // Get all elements which have .selected as class 284 let elementSelected = $filters.querySelectorAll('.selected') 285 // If no element fit the selector, we restore the "reset button" to its original state 286 if (elementSelected.length === 0) { 287 $resetFilter.classList.add('empty-selection') 288 $validateFilter.classList.add('empty-selection') 289 } 290 291 updateCustomFiltersVisibility(getActiveCategoryIDs()) 292 } else { 293 // If we have a selection of checkboxes : 294 295 // The reset button is enabled 296 297 $validateFilter.classList.remove('empty-selection') 298 299 // The $subCategoriesInput has class selected 300 $subCategoriesInput.classList.add('selected') 301 302 // Change the state and the text of the sub categories choices toggler 303 $toggleSubCategoriesChoices.innerHTML = 'Tout désélectionner' 304 $toggleSubCategoriesChoices.dataset.selected = 'false' 305 306 // Prepare the data which are sent to the Query object 307 // Used to build the url arguments 308 Query.URLArgs.subCategories = {} 309 Query.URLArgs.subCategories.parameterValue = [] 310 311 // We loop through all the selected sub categories 312 for (let i = 0; i < $subCategoriesCheckboxes.length; i++) { 313 // We store the checkbox value 314 let checkbox = $subCategoriesCheckboxes[i] 315 Query.URLArgs.subCategories.parameterValue.push(checkbox.value) 316 317 $subCategoriesCount.innerHTML = $subCategoriesCheckboxes.length + " sélectionnée(s)" 318 319 // todo... Si non est là c'est qu'elle est checkée la checkbox non ? 320 checkbox.checked = true 321 322 // If we are on the last checkbox element of the NodeList 323 // We don't add a comma 324 if (i === Number($subCategoriesCheckboxes.length - 1)) { 325 value += `${checkbox.dataset.name}` 326 } else { 327 value += `${checkbox.dataset.name}, ` 328 } 329 // We limit the value to 80 characters based of a Query class method 330 $subCategoriesInput.value = Query.truncate(value, 80, '...', ',') 331 } 332 333 updateCustomFiltersVisibility(getActiveCategoryIDs()) 334 } 335 }) 336 } 337 338 339 /*** 340 * The sub categorie filter has a button that allows to toggle the selection (all/none) 341 * ***/ 342 if (!!$toggleSubCategoriesChoices) { 343 $toggleSubCategoriesChoices.addEventListener('click', () => { 344 345 // Prepare the data which are sent to the Query object 346 // Used to build the url arguments 347 Query.URLArgs.subCategories = {} 348 Query.URLArgs.subCategories.parameterValue = [] 349 // Init values 350 let count = 0 351 let value = '' 352 353 // Get all the checkbox 354 let $subCategoriesCheckboxes = $subCategoriesFilterContainer.querySelectorAll('input[type="checkbox"]') 355 356 // Get the selected state of the toggler 357 let checked = $toggleSubCategoriesChoices.dataset.selected 358
359 // If the toggler data selected is on false we restore the filter on its default state 360 if (checked === 'false') { 361 // Remove the subcategories args in the URL 362 delete Query.URLArgs.subCategories 363 364 // Prepare the toggler for it's next action (select all) 365 $toggleSubCategoriesChoices.dataset.selected = 'true' 366 367 // Restore the text of the input 368 $subCategoriesInput.value = 'Sous-catégories' 369 // Restore the text in the toggler 370 $toggleSubCategoriesChoices.innerHTML = 'Tout sélectionner' 371 // Restore the default style for an inactive filter 372 $subCategoriesInput.classList.remove('selected') 373 374 // Unchecked all the sub categories checkboxes 375 for (let checkbox of $subCategoriesCheckboxes) { 376 checkbox.checked = false 377 } 378 379 // Get all elements which have .selected as class 380 let elementSelected = $filters.querySelectorAll('.selected') 381 // If no element fit the selector, we restore the "reset button" to its original state 382 if (elementSelected.length === 0) { 383 $resetFilter.classList.add('empty-selection') 384 $validateFilter.classList.add('empty-selection') 385 } 386 387 updateCustomFiltersVisibility(getActiveCategoryIDs()) 388 } else { 389 // This is the part where we check all the checkbox 390 // Enable the $resetFilter 391 392 $toggleSubCategoriesChoices.dataset.selected = 'false' 393 $toggleSubCategoriesChoices.innerHTML = 'Tout désélectionner' 394 $validateFilter.classList.remove('empty-selection') 395 396 // Apply the style for a active filter 397 $subCategoriesInput.classList.add('selected') 398 399 // We loop through all the selected sub categories 400 for (let i = 0; i < $subCategoriesCheckboxes.length; i++) { 401 // We store the checkbox value 402 let checkbox = $subCategoriesCheckboxes[i] 403 Query.URLArgs.subCategories.parameterValue.push(checkbox.value) 404 405 // todo... Si non est là c'est qu'elle est checkée la checkbox non ? 406 checkbox.checked = true 407 408 // If we are on the last checkbox element of the NodeList 409 // We don't add a comma 410 if (i === Number($subCategoriesCheckboxes.length - 1)) { 411 value += `${checkbox.dataset.name}` 412 } else { 413 value += `${checkbox.dataset.name}, ` 414 } 415 // We limit the value to 80 characters based of a Query class method 416 $subCategoriesInput.value = Query.truncate(value, 80, '...', ',') 417 418 // We increment the count to display it in $subCategoriesCount 419 count++ 420 } 421 422 updateCustomFiltersVisibility(getActiveCategoryIDs()) 423 } 424 // Update the checked categories count for the $subCategoriesCount 425 if (count === 1 || count === 0) { 426 $subCategoriesCount.innerHTML = `${count} sélectionnée(s)` 427 } else { 428 $subCategoriesCount.innerHTML = `${count} sélectionnée(s)` 429 } 430 }) 431 } 432 433 /** 434 * Function used to get all the subcategories for a given parent category (displayed in the filter list) 435 * It is triggered on load and when a parent category is selected 436 * 437 * */ 438 function displaySubCategories() { 439 if (!!$subCategorieFilter) { 440 // Init the PostsQuery Class 441 let Query = new PostsQuery() 442 443 // Set the custom creasit api route 444 Query._APIRoute = 'taxonomies' 445 446 if (window.cpt && window.cpt === 'consultations') { 447 Query.URLArgs.state = {} 448 Query.URLArgs.state.parameterValue = $archivePage.dataset.state 449 } 450 // Init the params to build the API endpoint (= url) 451 const params = { 452 cpt: window.cpt, 453 category: window.categoryID ?? '', 454 taxonomy: window.taxonomy, 455 } 456 457 458 if (Query.URLArgs.state) { 459 params.state = Query.URLArgs.state.parameterValue 460 } 461 462 // Get API endpoint (= url) 463 let URL = Query.getURL(params) 464 // Submit the fetch we need to get the subcategories 465 Query.fetchAPI(URL, 'GET').then( 466 data => { 467 let value = '' 468 let count = 0 469 // Exectute the code below only if more than 0 data are found 470 if (data.length > 0) { 471 $subCategoriesFilterContainer.innerHTML = '' 472 $subCategoriesCount.innerHTML = '0 sélectionnée' 473 474 // Get all the subcategories from [data-ids] 475 let selectedsubCategories = $subCategoriesFilterContainer.dataset.ids 476 selectedsubCategories = selectedsubCategories.split(',') 477 selectedsubCategories = selectedsubCategories.map(function (x) { 478 return parseInt(x, 10); 479 }); 480 481 // Remove the class hide apply on the sub-categories select 482 $subCategorieFilter.dataset.disabled = '' 483 484 // For each terms that are returned we create its option 485 // and add it to the sub-categories select 486 data.forEach((term) => { 487 if (term.parent !== 0) { 488 let checkState = '' 489 // If some subCategories are set in the URL params exec the code below 490 if (selectedsubCategories.includes(term.term_id)) { 491 492 selectedsubCategories.forEac
492h((category, index) => { 493 if (term.term_id === Number(category)) { 494 if (index === Number(selectedsubCategories.length - 1)) { 495 value += `${term.name}` 496 } else { 497 value += `${term.name}, ` 498 } 499 count++ 500 } 501 }) 502 $subCategoriesInput.value = Query.truncate(value, 80, '...', ',') 503 504 // Update the checked categories count for the $subCategoriesCount 505 if (count === 1) { 506 $subCategoriesCount.innerHTML = `${count} sélectionnée(s)` 507 } else { 508 $subCategoriesCount.innerHTML = `${count} sélectionnée(s)` 509 } 510 511 $subCategoriesInput.classList.add('selected') 512 $toggleSubCategoriesChoices.dataset.selected = 'false' 513 $toggleSubCategoriesChoices.innerHTML = 'Tout désélectionner' 514 515 $validateFilter.classList.remove('empty-selection') 516 517 // Checked the sub categories that are set in the URL params 518 checkState = 'checked' 519 } 520 521 // Display the subcategories checkboxes and checked the selected 522 $subCategoriesFilterContainer.innerHTML += `<li data-level="${term.level}"> 523 <input type="checkbox" value="${term.term_id}" name="0" data-slug="${term.slug}" 524 id="${term.term_id}" data-name="${term.name}" ${checkState}> 525 <label for="${term.term_id}"> 526 ${term.name} 527 </label> 528 </li>` 529 } else { 530 // Si $categoryFilter existe (pas de restriction parente forcée) 531 if ($categoryFilter) { 532 let $categoryCheckbox = $categoryFilter.querySelector('input[data-id="' + term.term_id + '"]') 533 if ($categoryCheckbox) { 534 $categoryCheckbox.checked = true 535 window.categoryID = Number($categoryCheckbox.dataset.id) 536 window.categorySlug = $categoryCheckbox.dataset.slug 537 window.taxonomy = $categoryCheckbox.dataset.taxonomy 538 document.querySelector('#filter_category').value = $categoryCheckbox.dataset.label ?? $categoryCheckbox.getAttribute('data-placeholder') 539 document.querySelector('#filter_category').classList.add('selected') 540 } 541 $validateFilter.classList.remove('empty-selection') 542 $resetFilter.classList.remove('empty-selection') 543 displaySubCategories() 544 } 545 // Si catégorie forcée parente : categoryID/taxonomy déjà initialisés 546 } 547 }) 548 549 // Toutes les checkboxes sont dans le DOM et cochées : 550 // on réévalue avec parent + sous-catégories sélectionnées 551 updateCustomFiltersVisibility(getActiveCategoryIDs()) 552 553 } else { 554 // If no data are found we hide the su-categories select 555 $subCategoriesInput.value = 'Sous-catégories' 556 $subCategoriesInput.classList.remove('selected') 557 $subCategoriesFilterContainer.innerHTML = '' 558 $toggleSubCategoriesChoices.innerHTML = 'Tout sélectionner' 559 $subCategoriesCount.innerHTML = '0 sélectionnée' 560 $subCategorieFilter.dataset.disabled = 'disabled' 561 } 562 } 563 ).catch(err => { 564 // TODO handle error to send 565 console.log(err) 566 }) 567 } 568 } 569 570 571 /** 572 * Show/hide custom filters based on the currently selected category. 573 * 574 * Each `.filter_custom` wrapper must have these data-attributes set in PHP: 575 * data-activate-categories="0|1" 576 * data-allowed-categories="[12,34,56]" (JSON array, IDs for the current CPT) 577 * 578 * Logic mirrors setCustomFilters() in PHP: 579 * - activate_categories == 0 â always show 580 * - activate_categories == 1 AND allowed-categories is empty/false â always show 581 * - activate_categories == 1 AND categoryID is in allowed-categories â show 582 * - otherwise â hide (and reset the filter's value) 583 * 584 * @param {number|string|null} categoryID The selected category ID, or null/'' when none. 585 */ 586 /** 587 * Returns all currently active category IDs : 588 * the selected parent category + any checked subcategories. 589 * 590 * @returns {number[]} 591 */ 592 function getActiveCategoryIDs() { 593 const ids = [] 594 595 // Parent category 596 const parentID = parseInt(window.categoryID, 10) 597 if (!isNaN(parentID) && parentID !== 0) { 598 ids.push(parentID) 599 } 600 601 // Selected subcategories 602 if ($subCategoriesFilterContainer) { 603 $subCategoriesFilterContainer 604 .querySelectorAll('input[type="checkbox"]:checked') 605 .forEach(cb => { 606 const subID = parseInt(cb.value, 10) 607 if (!isNaN(subID) && subID !== 0) { 608 ids.push(subID) 609 } 610 }) 611 } 612 613 return ids 614 } 615 616 /** 617 * Show/hide custom filters based on the currently active category IDs 618 * (parent category + selected subcategories). 619 * 620 * Logic: 621 * - activate_categories == 0 â always show 622 * - activate_categories == 1 + allowedCategories empty â always show 623 * - activate_categories == 1 + at least one active ID in allowed list â show 624 * - otherwise â hide (and reset the filter's value) 625 * 626 * @param {number|number[]|null} categoryIDs 627 */ 628 function updateCustomFiltersVisibility(categoryIDs) { 629 // Normalize to a clean array of valid integers 630 const activeIDs = (Array.isArray(categoryIDs) ? categoryIDs : [categoryIDs]) 631 .map(id => parseInt(id, 10)) 632 .filter(id => !isNaN(id) && id !== 0) 633 634 const $customFilterWrappers = document.querySelectorAll('.filter_custom') 635
636 $customFilterWrappers.forEach(function ($wrapper) { 637 const activateCategories = parseInt($wrapper.dataset.activateCategories ?? '0', 10) 638 let allowedCategories = [] 639 640 try { 641 allowedCategories = JSON.parse($wrapper.dataset.allowedCategories ?? '[]') 642 } catch (e) { 643 allowedCategories = [] 644 } 645 646 let shouldShow = true 647 648 if (activateCategories === 1 && allowedCategories.length > 0) { 649 // Show if at least one active ID (parent or subcat) is in the allowed list 650 shouldShow = activeIDs.some(id => allowedCategories.includes(id)) 651 } 652 653 if (shouldShow) { 654 $wrapper.style.display = '' 655 } else { 656 $wrapper.style.display = 'none' 657 658 const $input = $wrapper.querySelector('.filter__input-container input') 659 const $ul = $wrapper.querySelector('.filter__custom-container ul') 660 661 if ($input) { 662 $input.classList.remove('selected') 663 $input.value = '' 664 } 665 666 if ($ul) { 667 $ul.querySelectorAll('input[type="checkbox"]:checked').forEach(cb => { 668 cb.checked = false 669 }) 670 671 const param = $input ? $input.getAttribute('id') : null 672 if (param && Query.URLArgs[param]) { 673 delete Query.URLArgs[param] 674 } 675 } 676 } 677 }) 678 } 679 680 /*** 681 * Check for the filter validation button's presence and listen his click 682 * 683 * This function is used to build and submit the query to the WP API 684 * Although it builds the url parameter that will be pushed in the page url 685 ****/ 686 // Apply custom filters visibility on initial load based on any category already in the URL 687 updateCustomFiltersVisibility(getActiveCategoryIDs()) 688 !!$validateFilter && 689 $validateFilter.addEventListener('click', function () { 690 let selectedSubCategoriesID = [] 691 let selectedMonths = [] 692 let selectedYears = [] 693 let selectedCustomFilters = [] 694 let selectedKeyword = '' 695 let selectedStatus = '' 696 let selectedDate = '' 697 698 // Add view in URLQuery base 699 let initParams = new URLSearchParams(window.location.search) 700 let view = initParams.get('view') 701 if (view) { 702 Query.URLArgs.view = {} 703 Query.URLArgs.view.parameterValue = view 704 } else { 705 delete Query.URLArgs.view 706 } 707 708 if (!!$subCategoriesFilterContainer) { 709 let selectedSubCategories = $subCategoriesFilterContainer.querySelectorAll('input[type="checkbox"]:checked') 710 selectedSubCategories.forEach((category) => { 711 selectedSubCategoriesID.push(category.value) 712 }) 713 714 if (selectedSubCategoriesID.length > 0) { 715 Query.URLArgs.subCategories = {} 716 Query.URLArgs.subCategories.parameterValue = selectedSubCategoriesID 717 } else { 718 delete Query.URLArgs.subCategories 719 } 720 } 721 722 if (!!$dateFilterContainer) { 723 let dateCheckbox = $dateFilterContainer.querySelector('input[type="radio"]:checked') 724 725 // Init the Query.URLArgs object with the date entry 726 Query.URLArgs.date = {} 727 Query.URLArgs.date.parameterValue = [] 728 729 if (dateCheckbox !== null) { 730 if (dateCheckbox.value !== 'no_date') { 731 // We push its value in the Query.URLArgs.cpt.parameterValue 732 selectedDate = dateCheckbox.value 733 Query.URLArgs.date.parameterValue.push(dateCheckbox.value) 734 } else { 735 selectedDate = dateCheckbox.value 736 delete Query.URLArgs.date 737 } 738 } 739 } 740 741 if (!!$monthsFilter) { 742 let monthsCheckbox = $monthsFilter.querySelectorAll('input[type="checkbox"]:checked') 743
744 monthsCheckbox.forEach((month) => { 745 selectedMonths.push(month.dataset.monthnumber) 746 }) 747 748 if (monthsCheckbox.length > 0) { 749 Query.URLArgs.months = {} 750 Query.URLArgs.months.parameterValue = selectedMonths 751 } else { 752 delete Query.URLArgs.months 753 } 754 } 755 756 if (!!$yearsFilter) { 757 let yearsCheckboxes = $yearsFilter.querySelectorAll('input[type="checkbox"]:checked') 758 759 yearsCheckboxes.forEach((year) => { 760 selectedYears.push(year.dataset.yearnumber) 761 }) 762 763 if (yearsCheckboxes.length > 0) { 764 Query.URLArgs.years = {} 765 Query.URLArgs.years.parameterValue = selectedYears 766 } else { 767 delete Query.URLArgs.years 768 } 769 } 770 771 let customParams = [] 772 if (!!$customFilters) { 773 $customFilters.forEach(function ($customFilter) { 774 let customFilterCheckboxes = $customFilter.querySelectorAll('input[type="checkbox"]:checked') 775 let param = $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').getAttribute('id') 776 selectedCustomFilters[param] = [] 777 778 customParams.push($customFilter.closest('.filter_custom').querySelector('.filter__input-container input').getAttribute('id')) 779 customFilterCheckboxes.forEach((option) => { 780 selectedCustomFilters[param].push(option.value) 781 }) 782 783 if (customFilterCheckboxes.length > 0) { 784 Query.URLArgs[param] = {} 785 Query.URLArgs[param].parameterValue = selectedCustomFilters[param] 786 } else { 787 delete Query.URLArgs[param] 788 } 789 }) 790 } 791 792 // Init the Query.URLArgs object with the keyword entry 793 if (!!$keywordsFilter) { 794 selectedKeyword = $keywordsFilter.value 795 if (selectedKeyword.length > 0) { 796 Query.URLArgs.keyword = {} 797 Query.URLArgs.keyword.parameterValue = selectedKeyword 798 } else { 799 delete Query.URLArgs.keyword 800 } 801 } 802 803 if (!!$statusFilterContainer) { 804 let statusCheckbox = $statusFilterContainer.querySelector('input[type="radio"]:checked') 805 806 // Init the Query.URLArgs object with the date entry 807 Query.URLArgs.status = {} 808 Query.URLArgs.status.parameterValue = [] 809 810 if (statusCheckbox !== null) { 811 if (statusCheckbox.value !== null) { 812 // We push its value in the Query.URLArgs.cpt.parameterValue 813 selectedStatus = statusCheckbox.value 814 Query.URLArgs.status.parameterValue.push(statusCheckbox.value) 815 } else { 816 selectedStatus = statusCheckbox.value 817 delete Query.URLArgs.status 818 } 819 } 820 } 821 822 if (window.cpt && window.cpt === 'consultations') { 823 Query.URLArgs.state = {} 824 Query.URLArgs.state.parameterValue = $archivePage.dataset.state 825 } 826 827 $resetFilter.classList.remove('empty-selection') 828 829 // Init the params to build the API endpoint (= url) 830 const params = { 831 pages: 1, 832 cpt: cpt, 833 category: window.categoryID ?? '', 834 subCategories: selectedSubCategoriesID, 835 numberPosts: postsPerPage, 836 months: selectedMonths ?? '', 837 years: selectedYears ?? '', 838 post_status: ['publish'], 839 dateRange: selectedDate ?? '', 840 keyword: selectedKeyword ?? '', 841 status: selectedStatus ?? '', 842 } 843 844 if (customParams.length > 0) {
845 customParams.forEach(function (customParam) { 846 params[customParam] = selectedCustomFilters[customParam] ?? '' 847 848 if (Query.URLArgs[customParam]) { 849 params[customParam] = Query.URLArgs[customParam].parameterValue 850 } 851 }) 852 } 853 854 if (Query.URLArgs.startDate) { 855 params.startDate = Query.URLArgs.startDate.parameterValue 856 } 857 858 if (Query.URLArgs.endDate) { 859 params.endDate = Query.URLArgs.endDate.parameterValue 860 } 861 862 if (!!$archivePage) { 863 params.orderBy = $archivePage.dataset.orderby 864 params.order = $archivePage.dataset.order ?? '' 865 866 let $metakey = $archivePage.dataset.metakey 867 if ($metakey) { 868 params.metaKey = $metakey 869 } 870 } 871 872 if (Query.URLArgs.state) { 873 params.state = Query.URLArgs.state.parameterValue 874 } 875 876 // Get API endpoint (= url) 877 let URL = Query.getURL(params) 878 // Fetch on the API 879 execPostFetch(URL, countPostPerPage_INT) 880 }) 881 882 document.addEventListener('keydown', function (e) { 883 if (e.key !== 'Enter') return 884 if (!$validateFilter) return 885 886 const activeEl = document.activeElement 887 888 // Let native Enter behavior work on buttons and links 889 if (['BUTTON', 'A', 'SELECT'].includes(activeEl.tagName)) return 890 if (activeEl.closest('.accordion--transcription')) return 891 892 const isInKeyword = $keywordsFilter && $keywordsFilter === activeEl 893 const filtersAreVisible = $filters && getComputedStyle($filters).display !== 'none' 894 895 if (filtersAreVisible || isInKeyword) { 896 e.preventDefault() 897 $validateFilter.click() 898 } 899 }) 900 901 !!$resetFilter && 902 $resetFilter.addEventListener('click', function () { 903 904 let initParams = new URLSearchParams(window.location.search) 905 let view = initParams.get('view') 906 // Remove all the arguments in the URL 907 Object.keys(Query.URLArgs).forEach(function (arg) { 908 delete Query.URLArgs[arg] 909 }) 910 911 delete Query.URLArgs.category 912 913 // Get selected input 914 915 let $selectedInputs = $filters.querySelectorAll('.selected') 916 let $selectedForgottenInputs = document.querySelectorAll('.filter__input.selected') 917 let $checkedInputs = $filters.querySelectorAll('input:checked') 918 919 $selectedInputs.forEach((input) => { 920 input.classList.remove('selected') 921 input.value = '' 922 }) 923 $selectedForgottenInputs.forEach((input) => { 924 input.classList.remove('selected') 925 input.value = '' 926 }) 927 928 $checkedInputs.forEach((input) => { 929 input.checked = false 930 }) 931 932 if ($categoryFilter) { 933 $categoryFilter.querySelector('#filter_category').setAttribute('placeholder', 'Catégorie') 934 $categoryFilter.querySelector('#filter_category').value = '' 935 } 936 937 if ($subCategorieFilter) { 938 $subCategorieFilter.dataset.disabled = 'disabled' 939 $subCategoriesFilterContainer.dataset.ids = '' 940 } 941 if ($toggleSubCategoriesChoices) { 942 $subCategoriesCount.innerHTML = '0 sélectionnée' 943 $subCategoriesFilterContainer.innerHTML = '' 944 $toggleSubCategoriesChoices.dataset.selected = 'true' 945 $toggleSubCategoriesChoices.innerHTML = 'Tout sélectionner' 946 } 947 948 if (window.cpt && window.cpt === 'consultations') { 949 Query.URLArgs.state = {} 950 Query.URLArgs.state.parameterValue = $archivePage.dataset.state 951 } 952 953 if (view) { 954 Query.URLArgs.view = {} 955 Query.URLArgs.view.parameterValue = view 956 } 957 958 959 // Get the first number of posts (before fetching 960 // on API) 961 let countPostPerPage_HTML = $countPostPerPage.innerHTML 962 countPostPerPage_INT = parseInt(countPostPerPage_HTML) 963 964 // Init the params to build the API endpoint (= url) 965 let $orderby = $archivePage.dataset.orderby 966 let $order = $archivePage.dataset.order 967 const params = { 968 pages: 1, 969 cpt: cpt, 970 numberPosts: postsPerPage, 971 orderBy: $orderby, 972 order: $order, 973 post_status: ['publish'], 974 } 975 let $metakey = $archivePage.dataset.metakey 976 if ($metakey) { 977 params.metaKey = $metakey 978 } 979 980 if (Query.URLArgs.state) { 981 params.state = Query.URLArgs.state.parameterValue 982 } 983 984 985 window.categoryID = '' 986 987 // Si une catégorie est forcée côté back, on la restaure après le reset 988 if ($archivePage.dataset.forcedCategory) { 989 window.categoryID = Number($archivePage.dataset.forcedCategory) 990 Query.URLArgs.category = {} 991 Query.URLArgs.category.parameterValue = [window.categoryID] 992 params.category = window.categoryID 993 994 // Si catégorie parente forcée : réinitialiser les sous-catégories 995 if ($subCategorieFilter && $subCategorieFilter.dataset.forcedParent === '1') { 996 window.taxonomy = cptTaxonomyMap[window.cpt] || window.cpt + '_category' 997 displaySubCategories() 998 } 999 } 1000 1001 // Show all custom filters since no category is selected 1002 updateCustomFiltersVisibility(null) 1003 1004 // Inclure les subCategories de l'URL dans la query initiale si présents 1005 // (cas d'une page d'archive avec catégorie parente forcée et subCategories dans l'URL) 1006 if (Query.URLArgs.subCategories) { 1007 params.subCategories = Query.URLArgs.subCategories.parameterValue 1008 } 1009 1010 // Get API endpoint (= url) 1011 let URL = Query.getURL(params) 1012 // Fetch on the API 1013 execPostFetch(URL, countPostPerPage_INT) 1014 1015 $validateFilter.classList.add('empty-selection') 1016 $resetFilter.classList.add('empty-selection') 1017 }) 1018 1019 } 1020 1021 /** 1022 * FILTERS not category 1023 */ 1024 1025 1026 /*** 1027 * This listener is used to 1028 * 1. Display the number of selected sub categories in the $subCategoriesCount 1029 * 2. Display the subcategories' names in the $subCategoriesFilterContainer 1030 * ***/ 1031 if (!!$monthsFilter) { 1032 1033 // Get all the month from [data-ids] 1034 let selectedMonths = $monthsFilter.dataset.ids 1035 1036 if (selectedMonths) { 1037 selectedMonths = selectedMonths.split(',') 1038 1039 if (selectedMonths && selectedMonths.length > 0) { 1040 let value = '' 1041 1042 $validateFilter.classList.remove('empty-selection') 1043 for (let i = 0; i < selectedMonths.length; i++) { 1044 1045 let month = selectedMonths[i] 1046 let $monthToSelect = $monthsFilter.querySelector(`[data-monthnumber="${month}"]`) 1047 $monthsFilterInput.classList.add('selected') 1048 $monthToSelect.checked = true 1049 1050 let $monthLabel = $monthToSelect.getAttribute('id'); 1051 1052 // If we are on the last checkbox element of the NodeList 1053 // We don't add a comma 1054 if (i === Number(selectedMonths.length - 1)) { 1055 value += `${$monthLabel}` 1056 } else { 1057 value += `${$monthLabel}, ` 1058 } 1059 } 1060 // We limit the value to 80 characters based of a Query class method 1061 $monthsFilterInput.value = Query.truncate(value, 80, '...', ',') 1062 } 1063 } 1064 1065 1066 $monthsFilter.addEventListener('click', () => { 1067 1068 // Get the list of the checked input in the UL 1069 let $monthsFilterCheckboxes = $monthsFilter.querySelectorAll('input[type="checkbox"]:checked') 1070 1071 // Init values 1072 let count = 0 1073 let value = '' 1074 1075 // We control that the number of checked element is === 0 1076 // If it's true we remove all the data register during the subCatogories choice 1077 // And restore to original condition 1078 if ($monthsFilterCheckboxes.length === 0) { 1079 1080 // Remove the argument from the URL builder 1081 delete Query.URLArgs.months 1082 1083 // Restore the original $subCategoriesInput condition 1084 $monthsFilterInput.value = '' 1085 $monthsFilterInput.classList.remove('selected') 1086 1087 // Get all elements which have .selected as class 1088 let elementSelected = $filters.querySelectorAll('.selected') 1089 // If no element fit the selector, we restore the "reset button" to its original state 1090 if (elementSelected.length === 0) { 1091 $resetFilter.classList.add('empty-selection') 1092 $validateFilter.classList.add('empty-selection') 1093 } 1094 } else { 1095 // If we have a selection of checkboxes : 1096 1097 // The reset button is enabled 1098 1099 $validateFilter.classList.remove('empty-selection') 1100 1101 // The $subCategoriesInput has class selected 1102 $monthsFilterInput.classList.add('selected') 1103 1104 // Prepare the data which are sent to the Query object 1105 // Used to build the url arguments 1106 Query.URLArgs.months = {} 1107 Query.URLArgs.months.parameterValue = [] 1108 1109 // We loop through all the selected sub categories 1110 for (let i = 0; i < $monthsFilterCheckboxes.length; i++) { 1111 // We store the checkbox value 1112 let checkbox = $monthsFilterCheckboxes[i] 1113 Query.URLArgs.months.parameterValue.push(checkbox.value) 1114 1115 // todo... Si on est là c'est qu'elle est checkée la checkbox non ? 1116 // checkbox.checked = true 1117 1118 // If we are on the last checkbox element of the NodeList 1119 // We don't add a comma 1120 if (i === Number($monthsFilterCheckboxes.length - 1)) { 1121 value += `${checkbox.value}` 1122 } else { 1123 value += `${checkbox.value}, ` 1124 } 1125 // We limit the value to 80 characters based of a Query class method 1126 $monthsFilterInput.value = Query.truncate(value, 80, '...', ',') 1127 1128 // We increment the count to display it in $subCategoriesCount 1129 count++ 1130 } 1131 } 1132 }) 1133 } 1134 1135 1136 if (!!$customFilters) {
1137 $customFilters.forEach(function ($customFilter) { 1138 // Get all the month from [data-ids] 1139 let selectedOptions = $customFilter.dataset.ids 1140 1141 if (selectedOptions) { 1142 selectedOptions = selectedOptions.split(',') 1143 1144 if (selectedOptions && selectedOptions.length > 0) { 1145 let value = '' 1146 1147 $validateFilter.classList.remove('empty-selection') 1148 for (let i = 0; i < selectedOptions.length; i++) { 1149 1150 let option = selectedOptions[i] 1151 let optionToSelect = $customFilter.querySelector(`[data-option="${option}"]`) 1152 $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').classList.add('selected') 1153 optionToSelect.checked = true 1154 1155 let optionLabel = optionToSelect.getAttribute('id'); 1156 1157 // If we are on the last checkbox element of the NodeList 1158 // We don't add a comma 1159 if (i === Number(selectedOptions.length - 1)) { 1160 value += `${optionLabel}` 1161 } else { 1162 value += `${optionLabel}, ` 1163 } 1164 } 1165 // We limit the value to 80 characters based of a Query class method 1166 $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').value = Query.truncate(value, 80, '...', ',') 1167 } 1168 } 1169 1170 1171 $customFilter.addEventListener('click', () => { 1172 1173 // Get the list of the checked input in the UL 1174 let $customFilterCheckboxes = $customFilter.querySelectorAll('input[type="checkbox"]:checked') 1175 1176 // Init values 1177 let count = 0 1178 let value = '' 1179 let param = $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').getAttribute('id') 1180 1181 // We control that the number of checked element is === 0 1182 // If it's true we remove all the data register during the subCatogories choice 1183 // And restore to original condition 1184 if ($customFilterCheckboxes.length === 0) { 1185 1186 // Remove the argument from the URL builder 1187 delete Query.URLArgs[param] 1188 1189 // Restore the original $subCategoriesInput condition 1190 $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').value = '' 1191 $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').classList.remove('selected') 1192 1193 // Get all elements which have .selected as class 1194 let elementSelected = $filters.querySelectorAll('.selected') 1195 // If no element fit the selector, we restore the "reset button" to its original state 1196 if (elementSelected.length === 0) { 1197 $resetFilter.classList.add('empty-selection') 1198 $validateFilter.classList.add('empty-selection') 1199 } 1200 } else { 1201 // If we have a selection of checkboxes : 1202 1203 // The reset button is enabled 1204 1205 $validateFilter.classList.remove('empty-selection') 1206 1207 // The $subCategoriesInput has class selected 1208 $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').classList.add('selected') 1209 1210 // Prepare the data which are sent to the Query object 1211 // Used to build the url arguments 1212 Query.URLArgs[param] = {} 1213 Query.URLArgs[param].parameterValue = [] 1214 1215 1216 // We loop through all the selected sub categories 1217 for (let i = 0; i < $customFilterCheckboxes.length; i++) { 1218 // We store the checkbox value 1219 let checkbox = $customFilterCheckboxes[i] 1220 Query.URLArgs[param].parameterValue.push(checkbox.value) 1221 1222 // todo... Si on est là c'est qu'elle est checkée la checkbox non ? 1223 // checkbox.checked = true 1224 1225 // If we are on the last checkbox element of the NodeList 1226 // We don't add a comma 1227 if (i === Number($customFilterCheckboxes.length - 1)) { 1228 value += `${checkbox.getAttribute('id')}` 1229 } else { 1230 value += `${checkbox.getAttribute('id')}, ` 1231 } 1232 // We limit the value to 80 characters based of a Query class method 1233 $customFilter.closest('.filter_custom').querySelector('.filter__input-container input').value = Query.truncate(value, 80, '...', ',') 1234 1235 // We increment the count to display it in $subCategoriesCount 1236 count++ 1237 } 1238 } 1239 }) 1240 }) 1241 1242 1243 } 1244 /*** 1245 * This listener is used to 1246 * 1. Display the number of selected sub categories in the $subCategoriesCount 1247 * 2. Display the subcategories' names in the $subCategoriesFilterContainer 1248 * ***/ 1249 if (!!$postTypeFilter) { 1250 $postTypeFilter.addEventListener('click', () => { 1251 1252 // Get the list of the checked input in the UL 1253 let $postTypeFilterCheckboxes = $postTypeFilter.querySelectorAll('input[type="checkbox"]:checked') 1254 1255 // Init values 1256 let count = 0 1257 let value = '' 1258 1259 // We control that the number of checked element is === 0 1260 // If it's true we remove all the data register during the subCatogories choice 1261 // And restore to original condition 1262 if ($postTypeFilterCheckboxes.length === 0) { 1263 1264 // Remove the argument from the URL builder 1265 delete Query.URLArgs.postType 1266 1267 // Restore the original $subCategoriesInput condition 1268 $postTypeInput.value = '' 1269 $postTypeInput.classList.remove('selected') 1270 1271 // Get all elements which have .selected as class 1272 let elementSelected = $filters.querySelectorAll('.selected') 1273 // If no element fit the selector, we restore the "reset button" to its original state 1274 if (elementSelected.length === 0) { 1275 $resetFilter.classList.add('empty-selection') 1276 $validateFilter.classList.add('empty-selection') 1277 } 1278 } else { 1279 // If we have a selection of checkboxes : 1280 1281 // The reset button is enabled 1282 1283 $validateFilter.classList.remove('empty-selection') 1284 1285 // The $subCategoriesInput has class selected 1286 $postTypeInput.classList.add('selected') 1287 1288 // Prepare the data which are sent to the Query object 1289 // Used to build the url arguments 1290 Query.URLArgs.postType = {} 1291 Query.URLArgs.postType.parameterValue = [] 1292 1293 // We loop through all the selected sub categories 1294 for (let i = 0; i < $postTypeFilterCheckboxes.length; i++) { 1295 // We store the checkbox value 1296 let checkbox = $postTypeFilterCheckboxes[i] 1297 Query.URLArgs.postType.parameterValue.push(checkbox.dataset.label) 1298 1299 // todo... Si non est là c'est qu'elle est checkée la checkbox non ? 1300 // checkbox.checked = true 1301 1302 // If we are on the last checkbox element of the NodeList 1303 // We don't add a comma 1304 if (i === Number($postTypeFilterCheckboxes.length - 1)) { 1305 value += `${checkbox.dataset.label}` 1306 } else { 1307 value += `${checkbox.dataset.label}, ` 1308 } 1309 // We limit the value to 80 characters based of a Query class method 1310 $postTypeInput.value = Query.truncate(value, 80, '...', ',') 1311 1312 // We increment the count to display it in $subCategoriesCount 1313 count++ 1314 } 1315 } 1316 }) 1317 } 1318 1319 /*** 1320 * This listener is used to 1321 * 1. Display the number of selected sub categories in the $subCategoriesCount 1322 * 2. Display the subcategories' names in the $subCategoriesFilterContainer 1323 * ***/ 1324 if (!!$yearsFilter) { 1325 // Get all the month from [data-ids] 1326 let selectedYears = $yearsFilter.dataset.ids 1327 1328 if (selectedYears) { 1329 selectedYears = selectedYears.split(',') 1330 1331 $validateFilter.classList.remove('empty-selection') 1332 1333 if (selectedYears.length > 0) { 1334 let value = '' 1335 for (let i = 0; i < selectedYears.length; i++) { 1336 1337 let years = selectedYears[i] 1338 let $yearsToSelect = $yearsFilter.querySelector(`[data-yearnumber="${years}"]`) 1339 $yearsFilterInput.classList.add('selected') 1340 $yearsToSelect.checked = true 1341 1342 let $yearsLabel = $yearsToSelect.getAttribute('id'); 1343 1344 // If we are on the last checkbox element of the NodeList 1345 // We don't add a comma 1346 if (i === Number(selectedYears.length - 1)) { 1347 value += `${$yearsLabel}` 1348 } else { 1349 value += `${$yearsLabel}, ` 1350 } 1351 } 1352 // We limit the value to 80 characters based of a Query class method 1353 $yearsFilterInput.value = Query.truncate(value, 80, '...', ',') 1354 } 1355 } 1356 $yearsFilter.addEventListener('click', () => { 1357 1358 // Get the list of the checked input in the UL 1359 let $yearsFilterCheckboxes = $yearsFilter.querySelectorAll('input[type="checkbox"]:checked') 1360 1361 // Init values 1362 let value = '' 1363 1364 // We control that the number of checked element is === 0 1365 // If it's true we remove all the data register during the subCatogories choice 1366 // And restore to original condition 1367 if ($yearsFilterCheckboxes.length === 0) { 1368 1369 // Remove the argument from the URL builder 1370 delete Query.URLArgs.years 1371 1372 // Restore the original $subCategoriesInput condition 1373 $yearsFilterInput.value = '' 1374 $yearsFilterInput.classList.remove('selected') 1375 1376 // Get all elements which have .selected as class 1377 let elementSelected = $filters.querySelectorAll('.selected') 1378 // If no element fit the selector, we restore the "reset button" to its original state 1379 if (elementSelected.length === 0) { 1380 $resetFilter.classList.add('empty-selection') 1381 $validateFilter.classList.add('empty-selection') 1382 } 1383 } else { 1384 // If we have a selection of checkboxes : 1385 1386 // The reset button is enabled 1387 1388 $validateFilter.classList.remove('empty-selection') 1389 1390 // The $subCategoriesInput has class selected 1391 $yearsFilterInput.classList.add('selected') 1392 1393 // Prepare the data which are sent to the Query object 1394 // Used to build the url arguments 1395 Query.URLArgs.years = {} 1396 Query.URLArgs.years.parameterValue = [] 1397 1398 // We loop through all the selected sub categories 1399 for (let i = 0; i < $yearsFilterCheckboxes.length; i++) { 1400 // We store the checkbox value 1401 let checkbox = $yearsFilterCheckboxes[i] 1402 Query.URLArgs.years.parameterValue.push(checkbox.value) 1403 1404 // todo... Si non est là c'est qu'elle est checkée la checkbox non ? 1405 // checkbox.checked = true 1406 1407 // If we are on the last checkbox element of the NodeList 1408 // We don't add a comma 1409 if (i === Number($yearsFilterCheckboxes.length - 1)) { 1410 value += `${checkbox.value}` 1411 } else { 1412 value += `${checkbox.value}, ` 1413 } 1414 // We limit the value to 80 characters based of a Query class method 1415 $yearsFilterInput.value = Query.truncate(value, 80, '...', ',') 1416 } 1417 } 1418 }) 1419 } 1420 1421 1422 /*** 1423 * This listener is used to 1424 * 1. Display the number of selected sub categories in the $subCategoriesCount 1425 * 2. Display the subcategories' names in the $subCategoriesFilterContainer 1426 * ***/ 1427 if (!!$inputStartDate) { 1428 let argsStartDate = { 1429 dateFormat: 'dd/mm/yy', 1430 altField: $inputStartDate, 1431 altFormat: 'yymmdd', 1432 changeYear: true, 1433 yearRange: "-100:+100", 1434 changeMonth: true, 1435 showButtonPanel: true, 1436 onSelect: function () { 1437 handleDatePicker($inputTextStartDate, 'startDate', $inputStartDate.val()) 1438 }, 1439 1440 } 1441 acf.newDatePicker($inputTextStartDate, argsStartDate) 1442 let searchQuery = window.location.search 1443 let params = new URLSearchParams(searchQuery) 1444 if (params.get('startDate')) { 1445 let startDate = params.get('startDate').substr(0, 4) + '-' + params.get('startDate').substr(4, 2) + '-' + params.get('startDate').substr(6, 2) 1446 handleDatePicker($inputTextStartDate, 'startDate', startDate) 1447 $inputTextStartDate.datepicker("setDate", new Date(startDate)) 1448 } 1449 } 1450 if (!!$inputTextEndDate) { 1451 let argsEndDate = { 1452 dateFormat: 'dd/mm/yy', 1453 altField: $inputEndDate, 1454 altFormat: 'yymmdd', 1455 changeYear: true, 1456 yearRange: "-100:+100", 1457 changeMonth: true, 1458 showButtonPanel: true, 1459 onSelect: function () { 1460 handleDatePicker($inputTextEndDate, 'endDate', $inputEndDate.val()) 1461 } 1462 } 1463 acf.newDatePicker($inputTextEndDate, argsEndDate) 1464 let searchQuery = window.location.search 1465 let params = new URLSearchParams(searchQuery) 1466 if (params.get('endDate')) { 1467 let endDate = params.get('endDate').substr(0, 4) + '-' + params.get('endDate').substr(4, 2) + '-' + params.get('endDate').substr(6, 2) 1468 handleDatePicker($inputTextEndDate, 'endDate', endDate) 1469 $inputTextEndDate.datepicker("setDate", new Date(endDate)) 1470 } 1471 } 1472 1473 function handleDatePicker($input, type, $selectedDate) { 1474 1475 1476 // Prepare the data which are sent to the Query object 1477 // Used to build the url arguments 1478 Query.URLArgs[type] = {} 1479 Query.URLArgs[type].parameterValue = [] 1480 1481 // Enable the $resetFilter 1482 1483 // In case of no selection we restore all the style to their default state 1484 if ($selectedDate === undefined) { 1485 // Remove the subcategories args in the URL 1486 delete Query.URLArgs[type] 1487 1488 let elementSelected = $filters.querySelectorAll('.selected') 1489 // If no element fit the selector, we restore the "reset button" to its original state 1490 if (elementSelected.length === 0) { 1491 $resetFilter.classList.add('empty-selection') 1492 $validateFilter.classList.add('empty-selection') 1493 } 1494 1495 $input.removeClass('selected') 1496 } else { 1497 // This one is when a valid selection is made 1498 Query.URLArgs[type].parameterValue = $selectedDate 1499 1500 $input.addClass('selected') 1501 1502 $validateFilter.classList.remove('empty-selection') 1503 } 1504 } 1505 1506 1507 if (!!$resetKeywordInput) { 1508 $resetKeywordInput.addEventListener('click', () => { 1509 1510 //
1510 Set no value && remove the selected state 1511 $keywordsFilter.value = '' 1512 $keywordsFilter.classList.remove('selected') 1513 1514 // Relancer la recherche AVANT de recalculer l'état des boutons : 1515 // le handler du bouton Filtrer réactive le bouton Réinitialiser (il retire 1516 // empty-selection sans condition). Le clic programmatique passe outre le pointer-events:none. 1517 if (!!$validateFilter) { 1518 $validateFilter.click() 1519 } 1520 1521 // Puis on rétablit l'état des boutons selon les filtres ENCORE sélectionnés : 1522 // s'il reste une catégorie (ou autre filtre), Réinitialiser doit rester actif ; 1523 // sinon on le remet à l'état inactif. 1524 let elementSelected = $filters.querySelectorAll('.selected') 1525 if (elementSelected.length === 0) { 1526 $resetFilter.classList.add('empty-selection') 1527 $validateFilter.classList.add('empty-selection') 1528 } 1529 }) 1530 } 1531 1532 /*** 1533 * This listener is used to 1534 * 1. Display or not the $resetKeywordInput 1535 * 2. enable or not the $resetFilter button 1536 * ***/ 1537 if (!!$keywordsFilter) { 1538 $keywordsFilter.addEventListener('input', () => { 1539 // We enable the $resetFilter 1540 1541 // Get the input value 1542 let keywordValue = $keywordsFilter.value 1543 1544 // Depends on the value's length we apply the styl 1545 if (keywordValue.length > 0) { 1546 $keywordsFilter.classList.add('selected') 1547 1548 $validateFilter.classList.remove('empty-selection') 1549 } else { 1550 $keywordsFilter.classList.remove('selected') 1551 1552 // Get all elements which have .selected as class 1553 let elementSelected = $filters.querySelectorAll('.selected') 1554 // If no element fit the selector, we restore the "reset button" to its original state 1555 if (elementSelected.length === 0) { 1556 $resetFilter.classList.add('empty-selection') 1557 $validateFilter.classList.add('empty-selection') 1558 } 1559 } 1560 1561 }) 1562 } 1563 1564 /*** 1565 * This listener is used to get the selected range date and handle the reset of the filter 1566 * ***/ 1567 if (!!$dateFilterContainer) { 1568 $dateFilterContainer.addEventListener('click', () => { 1569 // Enable the $resetFilter 1570 1571 1572 // Get the selected range date 1573 let $dateCheckbox = $dateFilterContainer.querySelector('input[type="radio"]:checked') 1574 1575 // In case of no selection we restore all the style to their default state 1576 if ($dateCheckbox === null) { 1577 // Restore the input to its original state 1578 $dateInput.classList.remove('selected') 1579 1580 // Get all elements which have .selected as class 1581 let elementSelected = $filters.querySelectorAll('.selected') 1582 // If no element fit the selector, we restore the "reset button" to its original state 1583 if (elementSelected.length === 0) { 1584 $resetFilter.classList.add('empty-selection') 1585 $validateFilter.classList.add('empty-selection') 1586 } 1587 // The date filter is a list of radio, we need to have a default selection 1588 // That resets the state of the filter 1589 } else if ($dateCheckbox.value === 'no_date') { 1590 $dateInput.classList.remove('selected') 1591 $dateInput.value = 'Date de publication' 1592 1593 // Get all elements which have .selected as class 1594 let elementSelected = $filters.querySelectorAll('.selected') 1595 // If no element fit the selector, we restore the "reset button" to its original state 1596 if (elementSelected.length === 0) { 1597 $resetFilter.classList.add('empty-selection') 1598 $validateFilter.classList.add('empty-selection') 1599 } 1600 } else { 1601 // This one is when a valid selection is made 1602 $dateInput.classList.add('selected') 1603 $dateInput.value = $dateCheckbox.dataset.label ?? $dateCheckbox.getAttribute('data-placeholder') 1604 1605 $validateFilter.classList.remove('empty-selection') 1606 } 1607 1608 }) 1609 } 1610 1611 if (!!$statusFilterContainer) { 1612 $statusFilterContainer.addEventListener('click', () => { 1613 // Enable the $resetFilter 1614 1615 1616 // Get the selected range date 1617 let $statusCheckbox = $statusFilterContainer.querySelector('input[type="radio"]:checked') 1618 1619 // In case of no selection we restore all the style to their default state 1620 if ($statusCheckbox === null) { 1621 // Restore the input to its original state 1622 $statusInput.classList.remove('selected') 1623 1624 // Get all elements which have .selected as class 1625 let elementSelected = $filters.querySelectorAll('.selected') 1626 // If no element fit the selector, we restore the "reset button" to its original state 1627 if (elementSelected.length === 0) { 1628 $resetFilter.classList.add('empty-selection') 1629 } 1630 // The status filter is a list of radio, we need to have a default selection 1631 // That resets the state of the filter 1632 } else { 1633 // This one is when a valid selection is made 1634 $statusInput.classList.add('selected') 1635 $statusInput.value = $statusCheckbox.dataset.label ?? $statusCheckbox.getAttribute('placeholder') 1636 $validateFilter.classList.remove('empty-selection') 1637 } 1638 1639 }) 1640 } 1641 1642 function execPostFetch(URL, countPostPerPage_INT) { 1643 Query.fetchAPI(URL, 'GET').then( 1644 data => { 1645 1646 // Store the pagination_infos' elements inside variables 1647 let postsPerPage = data.pagination_infos.postsPerPage 1648 let foundPosts = data.pagination_infos.foundPosts 1649 let pages = data.pagination_infos.pages 1650 let postCount = data.pagination_infos.postCount 1651 1652 // Get the count of all the post in the Categorie 1653 $countTotal.innerHTML = foundPosts 1654 1655 // Init the Query.URLArgs object with the sub-category entry 1656 if (pages > 1) { 1657 Query.URLArgs.pages = {} 1658 Query.URLArgs.pages.parameterValue = [pages] 1659 } else { 1660 delete Query.URLArgs.pages 1661 } 1662 // Init the Query.URLArgs object with the date entry 1663 if (window.categoryID !== 'all') { 1664 Query.URLArgs.category = {} 1665 Query.URLArgs.category.parameterValue = [window.categoryID] 1666 } else { 1667 delete Query.URLArgs.category 1668 } 1669 1670 1671 // Push args in URL 1672 Query.pushSearchArgsInUrl() 1673 // Append posts 1674 Query.appendPosts(data.posts, $listingContainer, false) 1675 1676 // Get the value of canPaginate function (true/false) 1677 let canPaginate = Query.canPaginate(postsPerPage, foundPosts, pages) 1678 1679 // Delete the load more button 1680 if (loadMoreBTN) { 1681 if (canPaginate === false) { 1682 Query.fadeOut(loadMoreBTN) 1683 } else { 1684 Query.fadeIn(loadMoreBTN) 1685 } 1686 } 1687 1688 // Restore Email Address 1689 let $emailsTo = document.querySelectorAll('main a[href^="mailto:"]:not(.share-mail)'); 1690 $emailsTo.forEach(e => { 1691 e.href = e.href.replace('[^@]', '@') 1692 e.title = e.title.replace('[^@]', '@') 1693 }); 1694 1695 1696 // Get the postCount after the fetch and display it 1697 $countPostPerPage.innerHTML = Query.getCount( 1698 postCount, countPostPerPage_INT, false) 1699 }, 1700 ).catch(err => { 1701 // TODO handle error to send 1702 console.log(err) 1703 }) 1704 } 1705 1706 1707 /*** 1708 * Searchpage 1709 * ***/ 1710 // Const 1711 const body = document.querySelector('body'); 1712 const SearchInput = document.querySelector('#searchInput'); 1713 const SearchPageExist = body.classList.contains('search'); 1714 1715 if (SearchPageExist && SearchInput) { 1716 document.addEventListener('click', function (event) { 1717 let selectBoxes = document.querySelectorAll('.select-box.is-open')
1718 selectBoxes.forEach((selectBox) => { 1719 if (selectBox === event.target.closest('.select-box')) { 1720 let radios = selectBox ? selectBox.querySelectorAll('input[type=radio]') : [] 1721 !!radios && radios.forEach((radio) => { 1722 if (event.target === radio) { 1723 selectBox.classList.replace('is-open', 'is-closed') 1724 } 1725 }) 1726 } 1727 }) 1728 }) 1729 } 1730 1731 /*** 1732 * Navigation 1733 * ***/ 1734 1735 // Mise à jour du fil d'ariane avec l'URL archive depuis localStorage 1736 const $breadcrumbArchive = document.getElementById('breadcrumbArchive') 1737 if ($breadcrumbArchive) { 1738 const storedUrl = localStorage.getItem('back_to_archive') 1739 const storedTitle = localStorage.getItem('back_to_archive_title') 1740 if (storedUrl) { 1741 $breadcrumbArchive.href = storedUrl 1742 if (storedTitle) { 1743 $breadcrumbArchive.textContent = storedTitle 1744 $breadcrumbArchive.title = `Consulter la page ${storedTitle} (même onglet)` 1745 } 1746 } 1747 } 1748 1749 // Côté archive â stockage au clic sur une card via délégation 1750 // (les cards sont injectées dynamiquement donc on écoute sur document) 1751 if (document.getElementById('archivePage')) { 1752 document.addEventListener('click', function(e) { 1753 if (e.target.closest('.card__link')) { 1754 localStorage.setItem('back_to_archive', window.location.href) 1755 localStorage.setItem('back_to_archive_title', document.title) 1756 } 1757 }) 1758 } 1759 1760 // Côté post â lecture et application du localStorage sur le bouton retour 1761 const $backBtn = document.getElementById('backToArchive') 1762 if ($backBtn) { 1763 const storedUrl = localStorage.getItem('back_to_archive') 1764 if (storedUrl) { 1765 $backBtn.href = storedUrl 1766 localStorage.removeItem('back_to_archive') 1767 localStorage.removeItem('back_to_archive_title') 1768 } 1769 } 1770 1771 //============================================================================== 1772 // ------ Filter-toggle inherited from demosaisie 1773 //============================================================================== 1774 // Create jQuery slideToggle in Vanilla JS 1775 // to see filter options in archives templates 1776 1777 (function () { 1778 var block, i, j, len, len1, ref, ref1, slideToggler, trigger, 1779 indexOf = [].indexOf; 1780 1781 slideToggler = class slideToggler { 1782 constructor(el1) { 1783 this.getHeight = this.getHeight.bind(this); 1784 this.toggle = this.toggle.bind(this); 1785 this.el = el1; 1786 if (!this.el) { 1787 return; 1788 } 1789 window.addEventListener('resize', this.getHeight); 1790 } 1791 1792 getHeight() { 1793 var clone; 1794 clone = this.el.cloneNode(true); 1795 clone.style.cssText = 'visibility: hidden; display: block; margin: -999px 0'; 1796 this.height = (this.el.parentNode.appendChild(clone)).clientHeight; 1797 this.el.parentNode.removeChild(clone); 1798 return this.height; 1799 } 1800 1801 toggle(time) { 1802 var currHeight, disp, el, end, init, repeat, start; 1803 this.getHeight(); 1804 time || (time = this.height / 3 + 150); 1805 currHeight = this.el.clientHeight * (getComputedStyle(this.el).display !== 'none'); 1806 [start, end] = currHeight > this.height / 2 ? [this.height, 0] : [0, this.height]; 1807 disp = end - start; 1808 el = this.el; 1809 this.el.classList[end === 0 ? 'remove' : 'add']('is-open'); 1810 this.el.style.cssText = "overflow: hidden; display: block;"; 1811 init = (new Date).getTime(); 1812 repeat = function () { 1813 var instance, ref, repeatLoop, step; 1814 instance = (new Date).getTime() - init; 1815 step = start + disp * instance / time; 1816 if (instance <= time) { 1817 el.style.height = step + 'px'; // if Math.floor(step) in [start..end] 1818 } else { 1819 el.style.cssText = `display: ${(end === 0 ? 'none' : 'block')}`; 1820 } 1821 repeatLoop = requestAnimationFrame(repeat); 1822 if (ref = Math.floor(step), indexOf.call((function () { 1823 var results = []; 1824 for (var i = start; start <= end ? i <= end : i >= end; start <= end ? i++ : i--) { 1825 results.push(i); 1826 } 1827 return results; 1828 }).apply(this), ref) < 0) { 1829 return cancelAnimationFrame(repeatLoop); 1830 } 1831 }; 1832 return repeat(); 1833 } 1834 1835 }; 1836 1837 // Options Noyau 1838 let filtersCloseDefault = posts_filters_params.filters_close_default; 1839 1840 // if on tablet/mobile OR Search page Results : is closed 1841 if ((window.innerWidth < 960) || (SearchPageExist && SearchInput) || filtersCloseDefault) { 1842 1843 ref = document.querySelectorAll('.filter__options'); 1844 for (i = 0, len = ref.length; i < len; i++) { 1845 block = ref[i]; 1846 block.style.cssText = "display: none;"; 1847 block.toggler = new slideToggler(block); 1848 } 1849 1850 ref1 = document.querySelectorAll('.filter__toggler'); 1851 for (j = 0, len1 = ref1.length; j < len1; j++) { 1852 trigger = ref1[j]; 1853 trigger.classList.add('is-closed'); 1854 trigger.addEventListener('click', function () { 1855 var ref2; 1856 return (ref2 = this.parentNode.parentNode.querySelector('.filter__options').toggler) != null ? ref2.toggle(
1856) : void 0; 1857 }); 1858 } 1859 } else { 1860 1861 ref = document.querySelectorAll('.filter__options'); 1862 for (i = 0, len = ref.length; i < len; i++) { 1863 block = ref[i]; 1864 block.style.cssText = "display: block;"; 1865 block.toggler = new slideToggler(block); 1866 } 1867 1868 ref1 = document.querySelectorAll('.filter__toggler'); 1869 for (j = 0, len1 = ref1.length; j < len1; j++) { 1870 trigger = ref1[j]; 1871 trigger.classList.add('is-open'); 1872 trigger.addEventListener('click', function () { 1873 var ref2; 1874 return (ref2 = this.parentNode.parentNode.querySelector('.filter__options').toggler) != null ? ref2.toggle() : void 0; 1875 }); 1876 } 1877 } 1878 1879 }).call(this); 1880 1881 // Change toggler on click 1882 const filterToggler = document.querySelector(".filter__toggler"); 1883 1884 function classToggle() { 1885 filterToggler.classList.toggle('is-closed'); 1886 filterToggler.classList.toggle('is-open'); 1887 } 1888 1889 !!filterToggler && filterToggler.addEventListener('click', classToggle); 1890 1891 1892})
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.