MediaWiki:Script/Filter.js : Différence entre versions

Ligne 10 : Ligne 10 :
 
}
 
}
  
function addValueToObject(object, key, value) {
+
function editCardData(cardsData) {
   if (object[key]) {
+
   for (let cardIndex = 0; cardIndex < cardsData.length; cardIndex++) {
     object[key].push(value);
+
     const cardData = cardsData[cardIndex];
  } else {
+
    const cardName = cardData.card.querySelector("[data-name]").textContent;
     object[key] = [value];
+
 
 +
     cardData.name = toNormalForm(cardName);
 
   }
 
   }
 
}
 
}
  
function handleDropdowns(filterInformation) {
+
function observeLanguageChange(filterName, cardsData) {
   var form = filterInformation.form;
+
   if (!filterName) {
  var activeButton = null;
+
     return;
 
 
  function toggleDropdown(button, dropdownMenu) {
 
    if (button === activeButton) {
 
      hideElement(dropdownMenu);
 
      activeButton = null;
 
     } else {
 
      if (activeButton) {
 
        hideElement(activeButton.nextElementSibling);
 
      }
 
      showElement(dropdownMenu);
 
      activeButton = button;
 
    }
 
 
   }
 
   }
  
   function closeDropdowns() {
+
   const observer = new MutationObserver(function (mutation) {
    if (activeButton) {
+
     editCardData(cardsData);
      hideElement(activeButton.nextElementSibling);
 
      activeButton = null;
 
    }
 
  }
 
 
 
  form.addEventListener("click", function (event) {
 
    var target = event.target;
 
    var button = target.closest("button");
 
 
 
    if (button) {
 
      var dropdownMenu = button.nextElementSibling;
 
 
 
      toggleDropdown(button, dropdownMenu);
 
     } else if (!target.closest(".dropdown-menu")) {
 
      closeDropdowns();
 
    }
 
 
   });
 
   });
  
   document.addEventListener("mousedown", function (event) {
+
   observer.observe(filterName, { attributes: true });
    if (!form.contains(event.target)) {
 
      closeDropdowns();
 
    }
 
  });
 
 
}
 
}
  
function incrementCounter(counterElement, counterValue) {
+
function openFilter() {
   if (counterValue === 0) {
+
   const filterButton = document.getElementById("open-filter");
    showElement(counterElement);
+
  const filterDropdown = filterButton.nextElementSibling;
  }
+
 
 +
  hideElement(filterDropdown);
  
   counterElement.textContent = counterValue + 1;
+
   filterButton.addEventListener("click", handleDropdown);
}
 
  
function decrementCounter(counterElement, counterValue) {
+
  function handleDropdown() {
  if (counterValue === 1) {
+
     toggleElement(filterDropdown);
     hideElement(counterElement);
 
 
   }
 
   }
  
   counterElement.textContent = counterValue - 1;
+
   document.addEventListener("mousedown", function (event) {
 +
    if (
 +
      !filterButton.contains(event.target) &&
 +
      !filterDropdown.contains(event.target)
 +
    ) {
 +
      hideElement(filterDropdown);
 +
    }
 +
  });
 
}
 
}
  
function filterItems(filterInformation, cardInformation) {
+
function fillData(filter, filterData) {
   function showCounter() {
+
   const { filter: category, value } = filter.dataset;
    var checkbox = filterInformation.checkbox;
 
  
    for (var filterName in checkbox) {
+
  if (filter.type === "checkbox") {
      var values = checkbox[filterName].values;
+
    const span = filter.parentElement.querySelector("span.counter");
 +
    const filterInfo = { value: 0, span };
 +
    const { checkbox } = filterData;
  
      for (var filterValue in values) {
+
    checkbox[category] = checkbox[category] || {};
        var span = values[filterValue].span;
+
    checkbox[category][value] = filterInfo;
 
+
  } else if (filter.type === "number") {
        span.textContent = " (" + values[filterValue].value + ")";
+
    const { range } = filterData;
        values[filterValue].value = 0;
+
    if (range.hasOwnProperty(category)) {
       }
+
       return;
 
     }
 
     }
 +
    const init = { min: Number(filter.min), max: Number(filter.max) };
 +
    range[category] = { init: init };
 
   }
 
   }
 +
}
  
  function addCount(cardParameters, checkboxNames, parameter) {
+
function extractInitData(card, cardData) {
    cardParameters[parameter].split(" ").forEach(function (cardValue) {
+
  const cardNameElement = card.querySelector("[data-name]");
      checkboxNames[parameter].values[cardValue].value += 1;
 
    });
 
  }
 
  
   function isObjectValuesInRangeFilter(parameters, rangeFilter) {
+
   cardData.card = card;
    return Object.keys(rangeFilter).every(function (property) {
+
  cardData.name = toNormalForm(cardNameElement.textContent);
      var propertyValue = parameters[property];
+
  cardData.trueName = cardNameElement.firstChild.title;
      return (
+
}
        rangeFilter[property].min <= propertyValue &&
 
        rangeFilter[property].max >= propertyValue
 
      );
 
    });
 
  }
 
  
  function filterByName(parameters, filterName) {
+
function extractLevelData(card, cardData) {
    if (filterName) {
+
  const levelElement = card.querySelector("[data-level]");
      return parameters.name.indexOf(filterName) !== -1;
+
  const [level, rank] = levelElement.textContent.slice(1, -1).split(", ");
    }
 
    return true;
 
  }
 
  
   function isObjectValuesInFilter(parameters, filter) {
+
   cardData["level"] = Number(level);
    return Object.keys(filter).every(function (property) {
+
  cardData["rank"] = removeAccent(rank);
      return parameters[property].split(" ").some(function (value) {
+
}
        return filter[property].indexOf(value) !== -1;
 
      });
 
    });
 
  }
 
  
  function isObjectValuesInFilters(
+
function extractElementData(card, cardData) {
    parameters,
+
   const elementChild = card.querySelector("[data-elem]").children;
    filter,
+
   let elementValue = "";
    rangeFilter,
+
   if (elementChild.length) {
    filterName
 
  ) {
 
    return (
 
      isObjectValuesInFilter(parameters, filter) &&
 
      filterByName(parameters, filterName) &&
 
      isObjectValuesInRangeFilter(parameters, rangeFilter)
 
    );
 
  }
 
 
 
   var filter = filterInformation.filters.filter;
 
  var rangeFilter = filterInformation.filters.rangeFilter;
 
  var filterName = filterInformation.filters.filterName;
 
  var checkboxNames = filterInformation.checkbox;
 
  var listToFilter = cardInformation.listToFilter.children;
 
   var cardData = cardInformation.data;
 
 
 
   if (filterInformation.reverse) {
 
    var parent = cardInformation.listToFilter;
 
 
     for (
 
     for (
       var reverseIndex = 1;
+
       let elementIndex = 0;
       reverseIndex < listToFilter.length;
+
       elementIndex < elementChild.length;
       reverseIndex++
+
       elementIndex++
 
     ) {
 
     ) {
       parent.insertBefore(listToFilter[reverseIndex], parent.firstChild);
+
       elementValue += elementChild[elementIndex].title + " ";
 
     }
 
     }
    cardInformation.data.reverse();
 
    filterInformation.reverse = false;
 
 
   }
 
   }
 +
  elementValue = elementValue.trim() || "Aucun";
 +
  cardData.elem = removeAccent(elementValue);
 +
}
  
  for (var cardIndex = 0; cardIndex < listToFilter.length; cardIndex++) {
+
function extractTypeData(card, cardData) {
    var card = listToFilter[cardIndex];
+
  const typeElement = card.querySelector("[data-type]");
    var cardParameters = cardData[cardIndex];
+
  cardData.type = removeAccent(typeElement.textContent.split(" ")[0]);
    if (
 
      isObjectValuesInFilters(cardParameters, filter, rangeFilter, filterName)
 
    ) {
 
      showElement(card);
 
      for (var parameter in checkboxNames) {
 
        addCount(cardParameters, checkboxNames, parameter);
 
      }
 
    } else {
 
      hideElement(card);
 
    }
 
  }
 
  showCounter();
 
 
}
 
}
  
function updateFilterObject(filterInformation, cardInformation) {
+
function extractDamageData(card, cardData) {
   function updateFilter(event, filterByName = false) {
+
   const damageElement = card.querySelector("[data-damage]");
    function handleNumberType(target) {
+
  cardData.damage = removeAccent(damageElement.textContent.replace(" + ", " "));
      var [filterName, extremum] = target.id.split("-");
+
}
      var currentValue = Number(target.value);
 
      var counterElement = filterInformation.range[filterName].counter;
 
      var counterValue = Number(counterElement.textContent);
 
      var initialRange = filterInformation.range[filterName].init;
 
      var rangeFilter = filterInformation.filters.rangeFilter;
 
  
      if (rangeFilter[filterName]) {
+
function extractLocData(card, cardData) {
        rangeFilter[filterName][extremum] = currentValue;
+
  const locElement = card.querySelector("[data-loc]");
      } else {
+
  cardData.loc = locElement.dataset.loc;
        incrementCounter(counterElement, counterValue);
+
}
        rangeFilter[filterName] = {
 
          min: initialRange.min,
 
          max: initialRange.max,
 
        };
 
        rangeFilter[filterName][extremum] = currentValue;
 
      }
 
      if (
 
        rangeFilter[filterName].max === initialRange.max &&
 
        rangeFilter[filterName].min === initialRange.min
 
      ) {
 
        decrementCounter(counterElement, counterValue);
 
        delete rangeFilter[filterName];
 
      }
 
    }
 
  
    function handleCheckbox(target) {
+
function getCardsData(cardsContainer, filterData, dataExtractionMapping) {
      var filterName = target.id.split("-")[0];
+
  const cards = cardsContainer.children;
      var filter = filterInformation.filters.filter;
+
  const activeExtractors = [extractInitData];
      var filterValue = target.dataset.filter;
 
      var counterElement = filterInformation.checkbox[filterName].counter;
 
      var counterValue = Number(counterElement.textContent);
 
  
      if (target.checked) {
+
  for (const [key, extractorFunction] of Object.entries(
        incrementCounter(counterElement, counterValue);
+
    dataExtractionMapping
        addValueToObject(filter, filterName, filterValue);
+
  )) {
      } else {
+
    if (
        decrementCounter(counterElement, counterValue);
+
      filterData.range.hasOwnProperty(key) ||
        var index = filter[filterName].indexOf(filterValue);
+
      filterData.checkbox.hasOwnProperty(key)
        if (index !== -1) {
+
    ) {
          if (filter[filterName].length === 1) {
+
      activeExtractors.push(extractorFunction);
            delete filter[filterName];
 
          } else {
 
            filter[filterName].splice(index, 1);
 
          }
 
        }
 
      }
 
 
     }
 
     }
 
    var target = event.target;
 
 
    if (filterByName) {
 
      filterInformation.filters.filterName = toNormalForm(target.value);
 
    } else {
 
      var type = target.type;
 
 
      if (type === "number") {
 
        handleNumberType(target);
 
      } else if (type === "checkbox") {
 
        if (target.id === "filter-reverse") {
 
          filterInformation.reverse = true;
 
        } else {
 
          handleCheckbox(target);
 
        }
 
      }
 
    }
 
    filterItems(filterInformation, cardInformation);
 
 
   }
 
   }
  
   var form = filterInformation.form;
+
   const cardsData = [];
  var debounceTimer;
 
  
   form.addEventListener("submit", function (event) {
+
   for (let cardIndex = 0; cardIndex < cards.length; cardIndex++) {
     event.preventDefault();
+
     const card = cards[cardIndex];
  });
+
    const cardData = {};
  
  form.addEventListener("change", function (event) {
+
     for (const extractor of activeExtractors) {
    updateFilter(event);
+
       extractor(card, cardData);
  });
 
 
 
  form.addEventListener("input", function (event) {
 
     if (event.target.id === "filter-name") {
 
       clearTimeout(debounceTimer);
 
      debounceTimer = setTimeout(function () {
 
        updateFilter(event, true);
 
      }, 500);
 
 
     }
 
     }
  });
 
}
 
  
function filterInitialization() {
+
     cardsData.push(cardData);
  function createSpan() {
 
     var span = document.createElement("span");
 
    span.style.color = "#9F9F9F";
 
    span.style.fontSize = "12px";
 
    return span;
 
 
   }
 
   }
  
   function handlefilterParameters(filterParameters, param, filterName) {
+
   return cardsData;
    if (param === "levels") {
+
}
      addValueToObject(filterParameters, "levels", filterName);
 
    } else if (param.startsWith("replace_")) {
 
      var replace = param.split("replace_")[1].replace("_", " ");
 
 
 
      if (!filterParameters["replace"]) {
 
        filterParameters["replace"] = {};
 
      }
 
      filterParameters["replace"][filterName] = { value: replace };
 
    } else if (param === "elem") {
 
      filterParameters["elem"] = filterName;
 
    }
 
  }
 
  
   var form = document.getElementById("filter-form");
+
function filterInitialization(filterForm) {
  var filters = { filterName: "", filter: {}, rangeFilter: {} };
+
   const filterData = {
  var filterInformation = {
+
    form: filterForm,
    form: form,
+
    filters: { filterName: "", filter: {}, rangeFilter: {} },
    filters: filters,
 
 
     range: {},
 
     range: {},
 
     checkbox: {},
 
     checkbox: {},
 
     reverse: false,
 
     reverse: false,
 
   };
 
   };
   var allButton = form.querySelectorAll("button");
+
   const filters = filterForm.querySelectorAll("[data-filter]");
  var filterParameters = {};
 
  
   allButton.forEach(function (button) {
+
   filters.forEach((filter) => fillData(filter, filterData));
    var buttonSibling = button.nextElementSibling;
 
  
    if (!buttonSibling) return;
+
  return filterData;
 +
}
  
    var filterName = buttonSibling.id;
+
function displayCounterValue(checkbox) {
    var counter = buttonSibling.nextElementSibling;
+
  for (let filterCategory in checkbox) {
     var param = buttonSibling.dataset.param;
+
     const category = checkbox[filterCategory];
  
     if (!filterName || !counter || !param) return;
+
     for (let filterValue in category) {
 +
      const valueData = category[filterValue];
  
    var infoType = filterName.endsWith("-range") ? "range" : "checkbox";
+
      valueData.span.textContent = " (" + valueData.value + ")";
    var filterName = filterName.replace("-range", "");
+
      valueData.value = 0;
     var filterObj = (filterInformation[infoType][filterName] = {
+
     }
      counter: counter,
+
  }
    });
+
}
  
    handlefilterParameters(filterParameters, param, filterName);
+
function updateCounter(cardData, checkbox, filterCategory) {
 
+
  cardData[filterCategory].split(" ").forEach((cardValue) => {
    if (infoType === "checkbox") {
+
     checkbox[filterCategory][cardValue].value += 1;
      filterObj.values = {};
 
      var allInput = buttonSibling.querySelectorAll("input");
 
      allInput.forEach(function (input) {
 
        var filterValue = input.dataset.filter;
 
 
 
        if (!filterValue) return;
 
 
 
        var span = createSpan();
 
        input.parentElement.appendChild(span);
 
        filterObj.values[filterValue] = { value: 0, span: span };
 
      });
 
     } else if (infoType === "range") {
 
      filterObj.init = {};
 
      filterObj.init.min = Number(buttonSibling.children[0].firstChild.min);
 
      filterObj.init.max = Number(buttonSibling.children[0].firstChild.max);
 
    }
 
 
   });
 
   });
 +
}
  
   return [filterInformation, filterParameters];
+
function isObjectValuesInRangeFilter(parameters, rangeFilter) {
 +
   return Object.entries(rangeFilter).every(
 +
    ([property, { min, max }]) =>
 +
      parameters[property] >= min && parameters[property] <= max
 +
  );
 
}
 
}
  
function getCardInformation(filterParameters) {
+
function filterByName(parameters, filterName) {
   function createDataSelector(name) {
+
   if (filterName) {
     return "[data-" + name + "]";
+
     return parameters.name.includes(filterName);
 
   }
 
   }
 +
  return true;
 +
}
 +
 +
function isObjectValuesInFilter(parameters, filter) {
 +
  return Object.entries(filter).every(([property, values]) =>
 +
    parameters[property].split(" ").some((value) => values.includes(value))
 +
  );
 +
}
  
  var listToFilter = document.getElementById("list-to-filter");
+
function isObjectValuesInFilters(parameters, filter, rangeFilter, filterName) {
   var listToFilterChildren = listToFilter.children;
+
   return (
  var allCardInformation = [];
+
    isObjectValuesInFilter(parameters, filter) &&
  var filterLevelsNames = filterParameters["levels"];
+
    filterByName(parameters, filterName) &&
   var filterWithReplace = filterParameters["replace"];
+
    isObjectValuesInRangeFilter(parameters, rangeFilter)
  var filterElementName = filterParameters["elem"];
+
   );
 +
}
  
  if (filterLevelsNames) {
+
function filterCards(cardsContainer, filterData, cardsData) {
    var [level0, level1] = filterLevelsNames;
+
  const { filters, checkbox } = filterData;
    var levelsSelector = createDataSelector(level0);
+
  const { filter, rangeFilter, filterName } = filters;
  }
 
  
   if (filterWithReplace) {
+
   if (filterData.reverse) {
     for (var replaceName in filterWithReplace) {
+
     for (
       filterWithReplace[replaceName].selector = createDataSelector(replaceName);
+
      let reverseIndex = 1;
 +
      reverseIndex < cardsData.length;
 +
      reverseIndex++
 +
    ) {
 +
       cardsContainer.insertBefore(
 +
        cardsData[reverseIndex].card,
 +
        cardsContainer.firstChild
 +
      );
 
     }
 
     }
 +
    cardsData.reverse();
 +
    filterData.reverse = false;
 
   }
 
   }
  
   if (filterElementName) {
+
   for (let cardIndex = 0; cardIndex < cardsData.length; cardIndex++) {
     var elementSelector = createDataSelector(filterElementName);
+
    const cardData = cardsData[cardIndex];
 +
 
 +
    if (isObjectValuesInFilters(cardData, filter, rangeFilter, filterName)) {
 +
      showElement(cardData.card);
 +
      for (let filterCategory in checkbox) {
 +
        updateCounter(cardData, checkbox, filterCategory);
 +
      }
 +
     } else {
 +
      hideElement(cardData.card);
 +
    }
 
   }
 
   }
  
   for (
+
   displayCounterValue(checkbox);
    var cardIndex = 0;
+
}
    cardIndex < listToFilterChildren.length;
 
    cardIndex++
 
  ) {
 
    var card = listToFilterChildren[cardIndex];
 
    var cardInformation = {};
 
    var cardNameElement = card.querySelector("[data-name]");
 
    cardInformation.name = toNormalForm(cardNameElement.textContent);
 
    cardInformation.trueName = cardNameElement.firstChild.title;
 
  
    if (filterLevelsNames) {
+
function handleCheckbox(target, filter) {
      var levelsElement = card.querySelector(levelsSelector);
+
  const { filter: category, value } = target.dataset;
      var [levelValue0, levelValue1] = levelsElement.textContent
 
        .slice(1, -1)
 
        .split(", ");
 
      cardInformation[level0] = Number(levelValue0);
 
      cardInformation[level1] = removeAccent(levelValue1);
 
    }
 
  
    if (filterElementName) {
+
  if (target.checked) {
      var elementChild = card.querySelector(elementSelector).children;
+
    filter[category] = filter[category] || [];
      var elementValue = "";
+
    filter[category].push(value);
      if (elementChild.length) {
+
  } else {
        for (
+
    const index = filter[category].indexOf(value);
          var elementIndex = 0;
+
    if (index !== -1) {
          elementIndex < elementChild.length;
+
       filter[category].splice(index, 1);
          elementIndex++
 
        ) {
 
          elementValue += elementChild[elementIndex].title + " ";
 
        }
 
      }
 
      elementValue = elementValue.trim() || "Aucun";
 
       cardInformation[filterElementName] = removeAccent(elementValue);
 
 
     }
 
     }
 
+
     if (!filter[category].length) {
     if (filterWithReplace) {
+
      delete filter[category];
      for (var replaceName in filterWithReplace) {
 
        var replaceInformation = filterWithReplace[replaceName];
 
        var replaceValue = card
 
          .querySelector(replaceInformation.selector)
 
          .textContent.replace(replaceInformation.value, "");
 
        cardInformation[replaceName] = removeAccent(replaceValue);
 
      }
 
 
     }
 
     }
 
    allCardInformation.push(cardInformation);
 
 
   }
 
   }
  allCardInformation = { listToFilter: listToFilter, data: allCardInformation };
 
 
  return allCardInformation;
 
 
}
 
}
  
function editCardInformation(cardInformation) {
+
function handleNumberType(target, rangeFilter, range) {
   var listToFilterChildren = cardInformation.listToFilter.children;
+
   const { filter: category, value: extremum } = target.dataset;
 +
  const currentValue = Number(target.value);
 +
  const initialRange = range[category].init;
  
   for (
+
   if (rangeFilter[category]) {
     var cardIndex = 0;
+
     rangeFilter[category][extremum] = currentValue;
     cardIndex < listToFilterChildren.length;
+
  } else {
     cardIndex++
+
     rangeFilter[category] = {
 +
      min: initialRange.min,
 +
      max: initialRange.max,
 +
    };
 +
     rangeFilter[category][extremum] = currentValue;
 +
  }
 +
  if (
 +
    rangeFilter[category].max === initialRange.max &&
 +
    rangeFilter[category].min === initialRange.min
 
   ) {
 
   ) {
     var card = listToFilterChildren[cardIndex];
+
     delete rangeFilter[category];
    var cardName = card.querySelector("[data-name]").textContent;
 
    cardInformation.data[cardIndex].name = toNormalForm(cardName);
 
 
   }
 
   }
 
}
 
}
  
function observeLanguageChange(cardInformation) {
+
function handleFormEvents(cardsContainer, filterForm, filterData, cardsData) {
   var filterName = document.getElementById("filter-name");
+
   const { filters, range } = filterData;
 +
  let debounceTimer;
  
   if (!filterName) {
+
   filterForm.addEventListener("submit", function (event) {
     return;
+
     event.preventDefault();
   }
+
   });
 +
 
 +
  filterForm.addEventListener("change", updateFilter);
  
   var observer = new MutationObserver(function (mutation) {
+
   filterForm.addEventListener("input", function (event) {
     editCardInformation(cardInformation);
+
     clearTimeout(debounceTimer);
 +
    debounceTimer = setTimeout(() => {
 +
      if (event.target.id === "filter-name") {
 +
        updateFilter(event, true);
 +
      }
 +
    }, 500);
 
   });
 
   });
  
   observer.observe(filterName, { attributes: true });
+
   function updateFilter(event, filterByName = false) {
 +
    const target = event.target;
 +
    const targetType = target.type;
 +
 
 +
    if (filterByName) {
 +
      filters.filterName = toNormalForm(target.value);
 +
    } else if (targetType === "checkbox") {
 +
      handleCheckbox(target, filters.filter);
 +
    } else if (targetType === "number") {
 +
      handleNumberType(target, filters.rangeFilter, range);
 +
    }
 +
 
 +
    filterCards(cardsContainer, filterData, cardsData);
 +
  }
 
}
 
}
  
function filterWithUrl(filterInformation) {
+
function processUrlParameter(filterName, filterData, key, value) {
   function processParameter(key, value, filters) {
+
   const { filters } = filterData;
    if (key === "name") {
+
 
      var filterName = document.getElementById("filter-name");
+
  if (key === "name") {
      filterName.value = toNormalForm(value);
+
    filterName.value = toNormalForm(value);
      filters.filterName = value;
+
    filters.filterName = value;
    } else if (Object.keys(filterInformation.checkbox).indexOf(key) !== -1) {
+
  } else if (Object.keys(filterData.checkbox).indexOf(key) !== -1) {
      var checkboxElement = document.getElementById(key + "-" + value);
+
    const checkboxElement = document.getElementById(key + "-" + value);
      if (!checkboxElement) return;
+
 
      var counterElement = filterInformation.checkbox[key].counter;
+
    if (!checkboxElement) return;
      var counterValue = Number(counterElement.textContent);
+
 
      incrementCounter(counterElement, counterValue);
+
    checkboxElement.checked = true;
      checkboxElement.checked = true;
+
    filters.filter[key] = filters.filter[key] || [];
      addValueToObject(filters.filter, key, value);
+
    filters.filter[key].push(value);
    } else if (key === "reverse") {
+
  } else if (key === "reverse") {
      if (value === "1") {
+
    if (value === "1") {
        filterInformation.reverse = true;
+
      filterData.reverse = true;
        var reverseElement = document.getElementById("filter-reverse");
+
      const reverseElement = document.getElementById("filter-reverse");
        if (reverseElement) {
+
      if (reverseElement) {
          reverseElement.checked = true;
+
        reverseElement.checked = true;
        }
 
 
       }
 
       }
     } else {
+
     }
      var splitKey = key.split("-")[0];
+
  } else {
      if (Object.keys(filterInformation.range).indexOf(splitKey) !== -1) {
+
    const [splitKey, extremum] = key.split("-");
        var rangeElement = document.getElementById(key);
+
 
        if (!rangeElement) return;
+
    if (Object.keys(filterData.range).indexOf(splitKey) !== -1) {
        rangeElement.value = value;
+
      const rangeElement = document.getElementById(key);
        var rangeInformation = filterInformation.range[splitKey];
+
 
        incrementCounter(rangeInformation.counter, 0);
+
      if (!rangeElement) return;
        var extremum = key.split("-")[1];
+
 
        var rangeFilter = filters.rangeFilter;
+
      rangeElement.value = value;
        if (rangeFilter[splitKey]) {
+
 
          rangeFilter[splitKey][extremum] = value;
+
      const rangeData = filterData.range[splitKey];
        } else {
+
      const rangeFilter = filters.rangeFilter;
          rangeFilter[splitKey] = {
+
 
            min: rangeInformation.init.min,
+
      if (rangeFilter[splitKey]) {
            max: rangeInformation.init.max,
+
        rangeFilter[splitKey][extremum] = value;
          };
+
      } else {
          rangeFilter[splitKey][extremum] = value;
+
        rangeFilter[splitKey] = {
        }
+
          min: rangeData.init.min,
 +
          max: rangeData.init.max,
 +
        };
 +
        rangeFilter[splitKey][extremum] = value;
 
       }
 
       }
 
     }
 
     }
 
   }
 
   }
 +
}
  
   var url = new URL(window.location.href);
+
function filterWithUrl(filterName, filterData) {
   var urlHash = url.hash;
+
   const url = new URL(window.location.href);
   var useParams = true;
+
   const { hash, search } = url;
  var filters = filterInformation.filters;
+
   let useParams = true;
  
   if (urlHash) {
+
   if (hash) {
     var start = ".3F";
+
     const start = ".3F";
     var equal = ".3D";
+
     const equal = ".3D";
     var and = ".26";
+
     const and = ".26";
     var startParametersIndex = urlHash.indexOf(start);
+
     const startParametersIndex = hash.indexOf(start);
  
 
     if (startParametersIndex !== -1) {
 
     if (startParametersIndex !== -1) {
       useParams = false;
+
       const parameters = hash.slice(startParametersIndex + start.length);
      var parameters = urlHash.slice(startParametersIndex + start.length);
 
  
 
       parameters.split(and).forEach(function (keyValue) {
 
       parameters.split(and).forEach(function (keyValue) {
         var [key, value] = keyValue.split(equal);
+
         const [key, value] = keyValue.split(equal);
         processParameter(key, value, filters);
+
         processUrlParameter(filterName, filterData, key, value);
 
       });
 
       });
 +
 +
      useParams = false;
 
     }
 
     }
 
   }
 
   }
  
 
   if (useParams) {
 
   if (useParams) {
     var URLparams = new URLSearchParams(url.search);
+
     const URLparams = new URLSearchParams(search);
  
     for (var [key, value] of URLparams.entries()) {
+
     for (const [key, value] of URLparams.entries()) {
       processParameter(key, value, filters);
+
       processUrlParameter(filterName, filterData, key, value);
 
     }
 
     }
 
   }
 
   }
 
}
 
}
  
(function () {
+
function main_filter() {
   var [filterInformation, filterParameters] = filterInitialization();
+
   const filterForm = document.getElementById("filter-form");
   var cardInformation = getCardInformation(filterParameters);
+
  const filterName = document.getElementById("filter-name");
 +
  const cardsContainer = document.getElementById("cards-container");
 +
 
 +
  const dataExtractionMapping = {
 +
    level: extractLevelData,
 +
    elem: extractElementData,
 +
    type: extractTypeData,
 +
    damage: extractDamageData,
 +
    loc: extractLocData
 +
  };
 +
 
 +
  const filterData = filterInitialization(filterForm);
 +
   const cardsData = getCardsData(
 +
    cardsContainer,
 +
    filterData,
 +
    dataExtractionMapping
 +
  );
 +
 
 +
  observeLanguageChange(filterName, cardsData);
 +
  openFilter();
 +
  filterWithUrl(filterName, filterData);
 +
  filterCards(cardsContainer, filterData, cardsData);
 +
  handleFormEvents(cardsContainer, filterForm, filterData, cardsData);
 +
}
  
  observeLanguageChange(cardInformation);
+
main_filter();
  handleDropdowns(filterInformation);
 
  filterWithUrl(filterInformation);
 
  filterItems(filterInformation, cardInformation);
 
  updateFilterObject(filterInformation, cardInformation);
 
})();
 

Version du 11 décembre 2024 à 08:32

function removeAccent(str) {
  return str
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase();
}

function toNormalForm(str) {
  return removeAccent(str).replace(/[^a-zA-Z0-9 ]/g, "");
}

function editCardData(cardsData) {
  for (let cardIndex = 0; cardIndex < cardsData.length; cardIndex++) {
    const cardData = cardsData[cardIndex];
    const cardName = cardData.card.querySelector("[data-name]").textContent;

    cardData.name = toNormalForm(cardName);
  }
}

function observeLanguageChange(filterName, cardsData) {
  if (!filterName) {
    return;
  }

  const observer = new MutationObserver(function (mutation) {
    editCardData(cardsData);
  });

  observer.observe(filterName, { attributes: true });
}

function openFilter() {
  const filterButton = document.getElementById("open-filter");
  const filterDropdown = filterButton.nextElementSibling;

  hideElement(filterDropdown);

  filterButton.addEventListener("click", handleDropdown);

  function handleDropdown() {
    toggleElement(filterDropdown);
  }

  document.addEventListener("mousedown", function (event) {
    if (
      !filterButton.contains(event.target) &&
      !filterDropdown.contains(event.target)
    ) {
      hideElement(filterDropdown);
    }
  });
}

function fillData(filter, filterData) {
  const { filter: category, value } = filter.dataset;

  if (filter.type === "checkbox") {
    const span = filter.parentElement.querySelector("span.counter");
    const filterInfo = { value: 0, span };
    const { checkbox } = filterData;

    checkbox[category] = checkbox[category] || {};
    checkbox[category][value] = filterInfo;
  } else if (filter.type === "number") {
    const { range } = filterData;
    if (range.hasOwnProperty(category)) {
      return;
    }
    const init = { min: Number(filter.min), max: Number(filter.max) };
    range[category] = { init: init };
  }
}

function extractInitData(card, cardData) {
  const cardNameElement = card.querySelector("[data-name]");

  cardData.card = card;
  cardData.name = toNormalForm(cardNameElement.textContent);
  cardData.trueName = cardNameElement.firstChild.title;
}

function extractLevelData(card, cardData) {
  const levelElement = card.querySelector("[data-level]");
  const [level, rank] = levelElement.textContent.slice(1, -1).split(", ");

  cardData["level"] = Number(level);
  cardData["rank"] = removeAccent(rank);
}

function extractElementData(card, cardData) {
  const elementChild = card.querySelector("[data-elem]").children;
  let elementValue = "";
  if (elementChild.length) {
    for (
      let elementIndex = 0;
      elementIndex < elementChild.length;
      elementIndex++
    ) {
      elementValue += elementChild[elementIndex].title + " ";
    }
  }
  elementValue = elementValue.trim() || "Aucun";
  cardData.elem = removeAccent(elementValue);
}

function extractTypeData(card, cardData) {
  const typeElement = card.querySelector("[data-type]");
  cardData.type = removeAccent(typeElement.textContent.split(" ")[0]);
}

function extractDamageData(card, cardData) {
  const damageElement = card.querySelector("[data-damage]");
  cardData.damage = removeAccent(damageElement.textContent.replace(" + ", " "));
}

function extractLocData(card, cardData) {
  const locElement = card.querySelector("[data-loc]");
  cardData.loc = locElement.dataset.loc;
}

function getCardsData(cardsContainer, filterData, dataExtractionMapping) {
  const cards = cardsContainer.children;
  const activeExtractors = [extractInitData];

  for (const [key, extractorFunction] of Object.entries(
    dataExtractionMapping
  )) {
    if (
      filterData.range.hasOwnProperty(key) ||
      filterData.checkbox.hasOwnProperty(key)
    ) {
      activeExtractors.push(extractorFunction);
    }
  }

  const cardsData = [];

  for (let cardIndex = 0; cardIndex < cards.length; cardIndex++) {
    const card = cards[cardIndex];
    const cardData = {};

    for (const extractor of activeExtractors) {
      extractor(card, cardData);
    }

    cardsData.push(cardData);
  }

  return cardsData;
}

function filterInitialization(filterForm) {
  const filterData = {
    form: filterForm,
    filters: { filterName: "", filter: {}, rangeFilter: {} },
    range: {},
    checkbox: {},
    reverse: false,
  };
  const filters = filterForm.querySelectorAll("[data-filter]");

  filters.forEach((filter) => fillData(filter, filterData));

  return filterData;
}

function displayCounterValue(checkbox) {
  for (let filterCategory in checkbox) {
    const category = checkbox[filterCategory];

    for (let filterValue in category) {
      const valueData = category[filterValue];

      valueData.span.textContent = " (" + valueData.value + ")";
      valueData.value = 0;
    }
  }
}

function updateCounter(cardData, checkbox, filterCategory) {
  cardData[filterCategory].split(" ").forEach((cardValue) => {
    checkbox[filterCategory][cardValue].value += 1;
  });
}

function isObjectValuesInRangeFilter(parameters, rangeFilter) {
  return Object.entries(rangeFilter).every(
    ([property, { min, max }]) =>
      parameters[property] >= min && parameters[property] <= max
  );
}

function filterByName(parameters, filterName) {
  if (filterName) {
    return parameters.name.includes(filterName);
  }
  return true;
}

function isObjectValuesInFilter(parameters, filter) {
  return Object.entries(filter).every(([property, values]) =>
    parameters[property].split(" ").some((value) => values.includes(value))
  );
}

function isObjectValuesInFilters(parameters, filter, rangeFilter, filterName) {
  return (
    isObjectValuesInFilter(parameters, filter) &&
    filterByName(parameters, filterName) &&
    isObjectValuesInRangeFilter(parameters, rangeFilter)
  );
}

function filterCards(cardsContainer, filterData, cardsData) {
  const { filters, checkbox } = filterData;
  const { filter, rangeFilter, filterName } = filters;

  if (filterData.reverse) {
    for (
      let reverseIndex = 1;
      reverseIndex < cardsData.length;
      reverseIndex++
    ) {
      cardsContainer.insertBefore(
        cardsData[reverseIndex].card,
        cardsContainer.firstChild
      );
    }
    cardsData.reverse();
    filterData.reverse = false;
  }

  for (let cardIndex = 0; cardIndex < cardsData.length; cardIndex++) {
    const cardData = cardsData[cardIndex];

    if (isObjectValuesInFilters(cardData, filter, rangeFilter, filterName)) {
      showElement(cardData.card);
      for (let filterCategory in checkbox) {
        updateCounter(cardData, checkbox, filterCategory);
      }
    } else {
      hideElement(cardData.card);
    }
  }

  displayCounterValue(checkbox);
}

function handleCheckbox(target, filter) {
  const { filter: category, value } = target.dataset;

  if (target.checked) {
    filter[category] = filter[category] || [];
    filter[category].push(value);
  } else {
    const index = filter[category].indexOf(value);
    if (index !== -1) {
      filter[category].splice(index, 1);
    }
    if (!filter[category].length) {
      delete filter[category];
    }
  }
}

function handleNumberType(target, rangeFilter, range) {
  const { filter: category, value: extremum } = target.dataset;
  const currentValue = Number(target.value);
  const initialRange = range[category].init;

  if (rangeFilter[category]) {
    rangeFilter[category][extremum] = currentValue;
  } else {
    rangeFilter[category] = {
      min: initialRange.min,
      max: initialRange.max,
    };
    rangeFilter[category][extremum] = currentValue;
  }
  if (
    rangeFilter[category].max === initialRange.max &&
    rangeFilter[category].min === initialRange.min
  ) {
    delete rangeFilter[category];
  }
}

function handleFormEvents(cardsContainer, filterForm, filterData, cardsData) {
  const { filters, range } = filterData;
  let debounceTimer;

  filterForm.addEventListener("submit", function (event) {
    event.preventDefault();
  });

  filterForm.addEventListener("change", updateFilter);

  filterForm.addEventListener("input", function (event) {
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => {
      if (event.target.id === "filter-name") {
        updateFilter(event, true);
      }
    }, 500);
  });

  function updateFilter(event, filterByName = false) {
    const target = event.target;
    const targetType = target.type;

    if (filterByName) {
      filters.filterName = toNormalForm(target.value);
    } else if (targetType === "checkbox") {
      handleCheckbox(target, filters.filter);
    } else if (targetType === "number") {
      handleNumberType(target, filters.rangeFilter, range);
    }

    filterCards(cardsContainer, filterData, cardsData);
  }
}

function processUrlParameter(filterName, filterData, key, value) {
  const { filters } = filterData;

  if (key === "name") {
    filterName.value = toNormalForm(value);
    filters.filterName = value;
  } else if (Object.keys(filterData.checkbox).indexOf(key) !== -1) {
    const checkboxElement = document.getElementById(key + "-" + value);

    if (!checkboxElement) return;

    checkboxElement.checked = true;
    filters.filter[key] = filters.filter[key] || [];
    filters.filter[key].push(value);
  } else if (key === "reverse") {
    if (value === "1") {
      filterData.reverse = true;
      const reverseElement = document.getElementById("filter-reverse");
      if (reverseElement) {
        reverseElement.checked = true;
      }
    }
  } else {
    const [splitKey, extremum] = key.split("-");

    if (Object.keys(filterData.range).indexOf(splitKey) !== -1) {
      const rangeElement = document.getElementById(key);

      if (!rangeElement) return;

      rangeElement.value = value;

      const rangeData = filterData.range[splitKey];
      const rangeFilter = filters.rangeFilter;

      if (rangeFilter[splitKey]) {
        rangeFilter[splitKey][extremum] = value;
      } else {
        rangeFilter[splitKey] = {
          min: rangeData.init.min,
          max: rangeData.init.max,
        };
        rangeFilter[splitKey][extremum] = value;
      }
    }
  }
}

function filterWithUrl(filterName, filterData) {
  const url = new URL(window.location.href);
  const { hash, search } = url;
  let useParams = true;

  if (hash) {
    const start = ".3F";
    const equal = ".3D";
    const and = ".26";
    const startParametersIndex = hash.indexOf(start);

    if (startParametersIndex !== -1) {
      const parameters = hash.slice(startParametersIndex + start.length);

      parameters.split(and).forEach(function (keyValue) {
        const [key, value] = keyValue.split(equal);
        processUrlParameter(filterName, filterData, key, value);
      });

      useParams = false;
    }
  }

  if (useParams) {
    const URLparams = new URLSearchParams(search);

    for (const [key, value] of URLparams.entries()) {
      processUrlParameter(filterName, filterData, key, value);
    }
  }
}

function main_filter() {
  const filterForm = document.getElementById("filter-form");
  const filterName = document.getElementById("filter-name");
  const cardsContainer = document.getElementById("cards-container");

  const dataExtractionMapping = {
    level: extractLevelData,
    elem: extractElementData,
    type: extractTypeData,
    damage: extractDamageData,
    loc: extractLocData
  };

  const filterData = filterInitialization(filterForm);
  const cardsData = getCardsData(
    cardsContainer,
    filterData,
    dataExtractionMapping
  );

  observeLanguageChange(filterName, cardsData);
  openFilter();
  filterWithUrl(filterName, filterData);
  filterCards(cardsContainer, filterData, cardsData);
  handleFormEvents(cardsContainer, filterForm, filterData, cardsData);
}

main_filter();