Need To Add Custom Filters

Hey everyone @Diony_Betrisey, @user14644, @Camilla_Dalgaard :wave:

Here is the revised code (custom Tag filter) from our devs, that should be added to the Custom JS section on the Settings tab of your widget’s settings:

//Change filter name here
const DEFAULT_FILTER_LABEL = "TAGS";
const DEFAULT_FILTER_VALUE = "all";

const waitForElement = (selector, root = document) => new Promise(res => {
  let i = 0;

  const check = () => {
    const component = root.querySelector(selector);

    if (component) {
      res(component);
    } else if (i !== 50) {
      setTimeout(check, 100);
      i++;
    }
  };

  check();
});

waitForElement(".eapp-events-calendar-events-calendar-component").then((widget) => {
  const select = document.createElement('select');
  select.id = "es-custom-filter";
  select.classList.add('eapp-events-calendar-controls-item');
  select.classList.add('eapp-events-calendar-filter');
  select.classList.add('eapp-events-calendar-filter-current');
  
  // Add default option to the filter
  const defaultOption = document.createElement('option');
  defaultOption.value = DEFAULT_FILTER_VALUE;
  defaultOption.text = DEFAULT_FILTER_LABEL;
  select.appendChild(defaultOption);
  
  // Get all tags on the page
  const tags = [...widget.querySelectorAll('.eapp-events-calendar-tags-item')];
  
  // Add tags to the filter list
  const addedTags = [];
  const addTags = (tag) => {
      const trimmedTag = tag.innerText?.trim();
      if (!trimmedTag || addedTags.includes(trimmedTag)) {
        return;
      }
    
      const option = document.createElement('option');
      option.value = trimmedTag;
      option.text = trimmedTag;
      select.appendChild(option);
      
      addedTags.push(trimmedTag);
  };
  tags.forEach(addTags);
  
  // Place the filter after the other ones
  let filterContainer = widget.querySelector('.eapp-events-calendar-controls-component');
  if (!filterContainer) {
      let header = widget.querySelector(".eapp-events-calendar-events-calendar-header");
      if (!header) {
        header = document.createElement("div");
        header.classList.add("eapp-events-calendar-events-calendar-header");
        widget.prepend(header);
      }
      
      filterContainer = document.createElement("div");
      filterContainer.classList.add("eapp-events-calendar-controls-component");
      header.append(filterContainer);
  }
  filterContainer.appendChild(select);
  
  const filterEvents = (event) => {
    const selectedTag = select.value.toLowerCase();
  
    // Look if event has selected tag
    const eventTags = [...event.querySelectorAll(".eapp-events-calendar-tags-item")];
    const match = eventTags.some((tag) => tag.textContent?.toLowerCase() === selectedTag);
    
    // Show/Hide the events
    if (match || selectedTag === DEFAULT_FILTER_VALUE) {
    	event.style.display = 'flex';
    	
    	return;
    }
    
    event.style.display = 'none';
  };
  
  // Add event listener when filter selected
  const eventsContainer = widget.querySelector(".eapp-events-calendar-list-events, .eapp-events-calendar-grid-component");
  const callback = (mutationList) => mutationList.forEach(({ type, addedNodes }) => {
    if (type !== 'childList' || !addedNodes.length) {
      return;
    }

    addedNodes.forEach(filterEvents);
  });
  const observer = new MutationObserver(callback);
  
  const refilter = () => {
    observer.disconnect();
    
    const selectedTag = select.value.toLowerCase();
    
    // Met à jour le texte du filtre sélectionné
    if (selectedTag !== DEFAULT_FILTER_VALUE) {
      select.options[0].text = "All"; // Change the first option when a filter is selected
    } else {
      select.options[0].text = DEFAULT_FILTER_LABEL;
    }
    
    // Get all events on the page
    let events = [...widget.querySelectorAll("[class*='eapp-events-calendar-'][class$='-item-component']")];
    const isGrid = events?.[0].classList.contains("eapp-events-calendar-grid-item-component");
    if (isGrid) {
      events = events.map(event => event.parentNode);
    }
    events.forEach(filterEvents);
    
    observer.observe(eventsContainer, { childList: true });
  };
  select.addEventListener('change', refilter);
  document.addEventListener("click", (event) => {
    if (event.target.closest(".eapp-events-calendar-filter-item")) {
      refilter();
    }
  });
});

Note: We’ve managed to make it work in combination with other filters, but it’s usable for List and Grid layouts only.


In this video, you can see the feature in action:


Feel free to test it out :wink:

@Diony_Betrisey Once again, thanks a million for such a valuable input, that’s highly appreciated!

2 Likes