Need To Add Custom Filters

Welcome to the Community, @user14376 :wave:

Glad to say that this is already on the Wishlist! I’ve moved your comment to the thread, where we’ll keep you updated :slightly_smiling_face:

Could you just specify which additional filters you’d like to have?

1 Like

Hi guys, just to clarify my request, if you can let us choose what filters - it would be amazing!!! Personally, I need at least: Price Range, Individual / Group, # of people in the session (in my case, from 1 to 100+), Location (city, country), Language, and Event Macro Host Name + if you can let us filter by a Tag - it would be awesome! I’m happy to jump on a call and elaborate on this!
Regards, Veronika

1 Like

Thanks for sharing the details, Veronika!

We’ll have it in mind :slightly_smiling_face:

A post was split to a new topic: Issue with the filter names

Found a workaround to add a tag filter. I’ts a bit messy but usable… Just need to paste the Javascript below after the embedded code of the calendar widget and adapt the css “select” and “option” classes to match :

<script type="text/javascript"> document.addEventListener("DOMContentLoaded", function() {
    setTimeout(function() {
        // Creat filter element
        var select = document.createElement('select');
        select.id = "tagFilter";
        select.classList.add('jsx-695107531');
		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
        var defaultOption = document.createElement('option');
        defaultOption.value = "tag";
        defaultOption.text = "Artiste.s"; //Change filter name here
        select.appendChild(defaultOption);
        
        // Get all tags on the page
        var tags = new Set();
        document.querySelectorAll('.eapp-events-calendar-tags-item').forEach(function(tagElement) {
            var tagText = tagElement.innerText.trim();
            tags.add(tagText);
        });

        // Add tags to the filter list
        tags.forEach(function(tag) {
            var option = document.createElement('option');
            option.value = tag;
            option.text = tag;
            select.appendChild(option);
        });

        // Place the filter after the other ones
        var filterContainer = document.querySelector('.eapp-events-calendar-controls-component');
        if (filterContainer) {
            filterContainer.appendChild(select);
        } else {
            console.error("No container found.");
        }

        // Add event listener when filter selected
		select.addEventListener('change', function() {
			var selectedTag = select.value.toLowerCase();

			// Met à jour le texte du filtre sélectionné
			if (selectedTag != 'tag') {
				select.options[0].text = "All"; // Change the first option when a filter is selected
			} else {
				select.options[0].text = "Artiste.s"; // Change the filter name here
			}

			// Get all events on the page
			var events = document.querySelectorAll('.eapp-events-calendar-list-item-component');

			events.forEach(function(event) {
				// Look if event has selected tag
				var eventTags = event.querySelectorAll('.eapp-events-calendar-tags-item');
				var match = Array.from(eventTags).some(function(tag) {
					return tag.textContent.toLowerCase() === selectedTag;
				});

				// Show/Hide the events
				if (match || selectedTag == 'tag') {
					event.style.display = 'flex';
				} else {
					event.style.display = 'none';
				}
			});
		});
    }, 1000); // Whait 1 second for page loading
});
</script>
2 Likes

Hey, Thank you! Am I supposed to insert the code or are you still logged into my Shopify account?

Kind regards
Camilla Dalgaard

1 Like

Can you show us a ss of what this looks like to the user?

1 Like

Not perfect but usable

Programme du 90ème (choeurlaleonardine.ch)

2 Likes

Hey there, guys :wave:

@Diony_Betrisey, thanks so much for sharing your solution with us!

Our developers have reviewed the code and confirmed that it works, but with a couple of conditions:

  • It’s only compatible with Grid/List layouts
  • It won’t support any additional filters beyond this custom one

Additionally, the code needs a few tweaks to function perfectly. I’ve already passed it along to our developers, and I’ll be sure to share the finalized version here soon :slightly_smiling_face:

2 Likes

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!

1 Like

This is great - I installed the JS on my grid layout, but doesn’t seem to be popping up any new filters.

I added a few tags to test out (wasn’t using them before), but nothing is appearing.

6c6f22e1-033b-47cd-8ea3-0906acf8c9e4

1 Like

Hi @Matthew7 :wave:

Custom JS operates only upon widget installation, not in preview mode. So, if you check your website, the Tag filter is displayed there :slightly_smiling_face:

Max, this is fantastic and a big game-changer from a functionality point of view. (Thank-you to @Diony_Betrisey and to the devs).

Perhaps similar to @Matthew7 above I too am having difficulty. I can confirm I have installed and the tags filter is appearing on the website, however none of the ‘Tag’ options are displaying the the dropdown.

Any help would be greatly appreciated. Cheers.

I have discovered the problem, unfortunately this seems resticted to only those events that have already loaded on the page, rather than all future events within the calendar. Is this something that is changeable? (Thanks again)

Since this approach is based on the information displayed on the page, it’s not possible to show events or event tags that are not present. It’s more of a workaround than a real functionality. Fixing this would require a completely different solution, which I think isn’t feasible for a standard user I think.

1 Like

Important to keep the “const default_filter_value” value in lower case, dont work with “All” for example.

1 Like

Thankyou, yes, I suspected this may be the case.

(I was secretly hoping yourself or Max may have a way to redirect this to to run against the Plugin’s event list / data set rather than scanning the website; i.e. how the standard filter option already works) :smiley: but also apprecaite the challenges around that. (Ideal solution).

That being said, as a workaround, I can expand the number of “events displaying” on the page, however this still only seems to work (from a tags filter perspective) on the ‘Grid’ display, rather than the ‘List’ display options (and onyl when grouping by ‘none’ rather than by ‘day’.

Apologies, getting a bit techinical I appreciate, but certainly appreciate any help you can offer, as this is phenominal functionality if I can get it working more broadly :slight_smile: Thanks again.

2 Likes

Hi there, @Sam_Kirby :wave:

I’ve talked to the devs and there are 2 possible solutions:

  • add the rest of the tags to the dropdown only after clicking on the Load More button

  • manually add all the needed triggers to the code, If you decide to create new tags, they also should be added to the code.

Please let me know if you like one of the possible workaround. Our devs will be happy to adjust the script for you :slightly_smiling_face:

1 Like

Hi Max,

Sounds fantastic; looking at the above, I believe option Two would suit best.

Thanks again for all your help,
Sam

1 Like