Jump to content

User:Emilio/snippets.js

From Appropedia

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Filterable snippets */

$(function () {

	// Properties whose values are comma-separated.
	const multiValueProperties = new Set([
		'Page keywords',
		'SDG'
	]);

	function getValues(chip) {
		const property = chip.dataset.property.trim();
		const text = chip.textContent.trim();

		if (!text) return [];

		if (!multiValueProperties.has(property)) {
			return [text];
		}

		return text.split(',')
			.map(value => value.trim())
			.filter(Boolean);
	}

	$('.page-snippet-filterable').each(function () {
		const container = this;
		if (container.dataset.filtersReady) return;
		container.dataset.filtersReady = 'true';

		const snippets = Array.from(
			container.querySelectorAll('.page-snippet-inline')
		);
		if (!snippets.length) return;

		const properties = new Map();

		// Collect property names and distinct values.
		snippets.forEach(function (snippet) {
			snippet.querySelectorAll('.data-chip[data-property]')
				.forEach(function (chip) {
					const name = chip.dataset.property.trim();
					if (!name) return;

					const values = getValues(chip);
					if (!values.length) return;

					if (!properties.has(name)) {
						properties.set(name, new Set());
					}

					values.forEach(function (value) {
						properties.get(name).add(value);
					});
				});
		});

		if (!properties.size) return;

		const controls = document.createElement('div');
		controls.className = 'page-snippet-filters';
		controls.style.cssText =
			'display:flex;flex-wrap:wrap;gap:1em;margin:1em 0;align-items:end';

		const selections = new Map();

		function update() {
			let visible = 0;

			snippets.forEach(function (snippet) {
				const chips = Array.from(
					snippet.querySelectorAll('.data-chip[data-property]')
				);

				const matches = Array.from(selections).every(
					function ([property, value]) {
						if (!value) return true;

						return chips.some(function (chip) {
							return chip.dataset.property.trim() === property &&
								getValues(chip).includes(value);
						});
					}
				);

				snippet.style.display = matches ? '' : 'none';
				if (matches) visible++;
			});

			counter.textContent =
				'Showing ' + visible + ' of ' + snippets.length + ' projects';
		}

		properties.forEach(function (values, name) {
			const group = document.createElement('label');
			group.style.cssText =
				'display:flex;flex-direction:column;gap:0.25em';
			group.textContent = name;

			const select = document.createElement('select');
			select.className = 'cdx-select';

			const all = document.createElement('option');
			all.value = '';
			all.textContent = 'All ' + name;
			select.appendChild(all);

			Array.from(values)
				.sort((a, b) => a.localeCompare(b))
				.forEach(function (value) {
					const option = document.createElement('option');
					option.value = value;
					option.textContent = value;
					select.appendChild(option);
				});

			select.addEventListener('change', function () {
				selections.set(name, select.value);
				update();
			});

			group.appendChild(select);
			controls.appendChild(group);
			selections.set(name, '');
		});

		const counter = document.createElement('span');
		counter.style.opacity = '0.7';
		controls.appendChild(counter);

		container.parentNode.insertBefore(controls, container);
		update();
	});
});
Cookies help us deliver our services. By using our services, you agree to our use of cookies.