Changing Calendar Color based on Filter selected

In the case of Northvalleygames.com , we have multiple stores each with different color themes. If we could change the color of the calendar based on the store selected, if any, that would be awesome!

1 Like

Hi there, @Nemesius_Yggdrasil :wave:

Your request is with our devs now. They’ll try to customize your widget and I’ll update your here :slightly_smiling_face:

Thank you for waiting. @Nemesius_Yggdrasil :wave:

Glad to say that our devs came up with a custom solution for you.

This code should be added to the Custom CSS field on the Appearance tab of your widget’s settings:

.eapps-north-valley-games-color {
	background-color: red !important;
}

.eapps-nvg-phoenix-color {
	background-color: green !important;
}

.eapps-nvg-mesa-color {
	background-color: gray !important;
}

Note: You are very welcome to use any other colors in this code :slightly_smiling_face:


And this script should be added to the Custom JS field on the Settings tab:

const STORE_COLOR_MAP = {
	'eapps-nvg-mesa-color': 'nvg mesa',
	'eapps-nvg-phoenix-color': 'nvg phoenix',
	'eapps-north-valley-games-color':
		'north valley games - mesa, 3460 e southern ave #107, mesa, az 85204, usa',
};

const LISTEN_TYPES = {
	one: {
		select: (selector, root) => root.querySelector(selector),
		validate: (node) => !!node,
	},
	all: {
		select: (selector, root) => root.querySelectorAll(selector),
		validate: (node) => node?.length > 0,
	},
};

function listenStep(args) {
	args.node = args.select(args.selector, args.root);
	if (!args.validate(args.node)) {
		args.step++;
		if (args.step < args.limit) {
			setTimeout(() => listenStep(args), args.delay);
		} else {
			args.reject();
		}
	} else {
		args.resolve(args.node);
	}
}

async function asyncListenFor(selector, type = 'one', customArgs = {}) {
	const args = {
		root: document,
		node: undefined,
		selector,
		delay: 100,
		limit: 50,
		step: 0,
		select: LISTEN_TYPES[type].select,
		validate: LISTEN_TYPES[type].validate,
		...customArgs,
	};
	return new Promise((resolve, reject) =>
		listenStep({ ...args, resolve, reject })
	);
}

const updateClassesBasedOnFilter = (filterText, eventsEl) => {
	const classToAdd = Object.entries(STORE_COLOR_MAP).find(
		([, value]) => filterText === value.toLowerCase()
	)?.[0];

	eventsEl.forEach((event) => {
		Object.keys(STORE_COLOR_MAP).forEach((className) =>
			event.classList.remove(className)
		);
		if (classToAdd) {
			event.classList.add(classToAdd);
		}
	});
};

const observeNewElements = (container, lastFilterText) => {
	const observer = new MutationObserver(() => {
		const newEventsEl = document.querySelectorAll(
			'.eapp-events-calendar-list-item-component'
		);

		if (newEventsEl.length > 0) {
			updateClassesBasedOnFilter(lastFilterText, newEventsEl);
			observer.disconnect();
		}
	});

	observer.observe(container, {
		childList: true,
		subtree: true,
	});
};

asyncListenFor('.eapp-events-calendar-filter-currentText').then((filterEl) => {
	let lastFilterText = filterEl.textContent.toLowerCase();

	const observer = new MutationObserver(() => {
		const currentFilterText = filterEl.textContent.toLowerCase();
		if (currentFilterText === lastFilterText) return;

		lastFilterText = currentFilterText;
		const isFilterActive = currentFilterText !== 'store';
		const eventsEl = document.querySelectorAll(
			'.eapp-events-calendar-list-item-component'
		);

		if (isFilterActive) {
			updateClassesBasedOnFilter(currentFilterText, eventsEl);
		} else {
			updateClassesBasedOnFilter('', eventsEl);
		}
	});

	observer.observe(filterEl, {
		characterData: true,
		subtree: true,
		childList: true,
	});


	const loadMoreBtn = document.querySelector(
		'.eapp-events-calendar-load-more-button-container'
	);
	if (loadMoreBtn) {
		loadMoreBtn.addEventListener('click', () => {

			const eventsContainer = document.querySelector(
				'.eapp-events-calendar-list-component'
			);

			if (eventsContainer) {
				observeNewElements(eventsContainer, lastFilterText);
			}
		});
	}
});

The script works with exact names of the filters. If the names of the filters are changed, the script won’t work.

To fix it, you need to adjust the filter names in the Custom JS and Custom CSS codes:

image

image


Give it a try and let me know if you like the result :slightly_smiling_face:

1 Like