Jump to content

MediaWiki:Gadget-PageSnippets.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.
const PageSnippets = {

	init( $content ) {

		$content.find( '.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 = PageSnippets.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.display = 'flex';
			controls.style.flexWrap = 'wrap';
			controls.style.gap = '1em';
			controls.style.margin = '1em 0';
			controls.style.alignItems = '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 &&
									PageSnippets.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 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();
				} );

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

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

			container.parentNode.insertBefore( controls, container );
			update();
		} );
	},

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

			if ( !text ) {
				return [];
			}

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

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

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

mw.hook( 'wikipage.content' ).add( PageSnippets.init );
Cookies help us deliver our services. By using our services, you agree to our use of cookies.