Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Common.js: Difference between revisions

MediaWiki interface page
Add item filters and combined effects column
 
Create generated spells table
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
( function () {
( function () {
function initFilter( filter ) {
function initFilter( filter ) {
if ( filter.dataset.initialized ) {
return;
}
filter.dataset.initialized = '1';
var targetSelector = filter.getAttribute( 'data-target' );
var targetSelector = filter.getAttribute( 'data-target' );
var table = targetSelector ? document.querySelector( targetSelector ) : null;
var table = targetSelector ? document.querySelector( targetSelector ) : null;
Line 7: Line 12:
}
}


var rows = Array.prototype.slice.call( table.querySelectorAll( 'tr.item-list__row' ) );
var rows = Array.prototype.slice.call( table.querySelectorAll( 'tr.item-list__row, tr.spell-list__row' ) );
var selects = Array.prototype.slice.call( filter.querySelectorAll( 'select[data-filter]' ) );
var count = document.createElement( 'span' );
var count = filter.querySelector( '[data-filter-count]' );
var reset = document.createElement( 'button' );
var reset = filter.querySelector( '[data-filter-reset]' );
var fields = parseFields( filter.getAttribute( 'data-filter-fields' ) );
var selects = fields.map( function ( field ) {
return buildSelect( rows, field.key, field.label, field.all );
} );
 
filter.textContent = '';
selects.forEach( function ( select ) {
filter.appendChild( select.label );
} );
 
reset.type = 'button';
reset.textContent = 'Reset';
filter.appendChild( reset );
 
count.className = filter.classList.contains( 'spell-list-filter' ) ?
'spell-list-filter__count' :
'item-list-filter__count';
filter.appendChild( count );
 
function parseFields( value ) {
if ( !value ) {
return [
{ key: 'slot', label: 'Slot', all: 'All slots' },
{ key: 'construction', label: 'Construction', all: 'All levels' }
];
}
return value.split( '|' ).map( function ( spec ) {
var parts = spec.split( ':' );
return {
key: parts[ 0 ],
label: parts[ 1 ] || parts[ 0 ],
all: parts[ 2 ] || 'All'
};
} );
}
 
function buildSelect( sourceRows, key, labelText, allText ) {
var label = document.createElement( 'label' );
var select = document.createElement( 'select' );
var values = [];
var seen = {};
 
sourceRows.forEach( function ( row ) {
var value = row.dataset[ key ];
if ( value && !seen[ value ] ) {
seen[ value ] = true;
values.push( value );
}
} );
 
values.sort( function ( a, b ) {
if ( key === 'construction' || key === 'research' ) {
return Number( a ) - Number( b );
}
return a.localeCompare( b );
} );
 
select.dataset.filter = key;
select.appendChild( new Option( allText, '' ) );
values.forEach( function ( value ) {
select.appendChild( new Option( value, value ) );
} );
 
label.appendChild( document.createTextNode( labelText + ' ' ) );
label.appendChild( select );
select.label = label;
return select;
}


function applyFilters() {
function applyFilters() {
Line 34: Line 106:
} );
} );


if ( reset ) {
reset.addEventListener( 'click', function () {
reset.addEventListener( 'click', function () {
selects.forEach( function ( select ) {
selects.forEach( function ( select ) {
select.value = '';
select.value = '';
} );
applyFilters();
} );
} );
}
applyFilters();
} );


applyFilters();
applyFilters();

Latest revision as of 18:23, 15 May 2026

( function () {
	function initFilter( filter ) {
		if ( filter.dataset.initialized ) {
			return;
		}
		filter.dataset.initialized = '1';

		var targetSelector = filter.getAttribute( 'data-target' );
		var table = targetSelector ? document.querySelector( targetSelector ) : null;
		if ( !table ) {
			return;
		}

		var rows = Array.prototype.slice.call( table.querySelectorAll( 'tr.item-list__row, tr.spell-list__row' ) );
		var count = document.createElement( 'span' );
		var reset = document.createElement( 'button' );
		var fields = parseFields( filter.getAttribute( 'data-filter-fields' ) );
		var selects = fields.map( function ( field ) {
			return buildSelect( rows, field.key, field.label, field.all );
		} );

		filter.textContent = '';
		selects.forEach( function ( select ) {
			filter.appendChild( select.label );
		} );

		reset.type = 'button';
		reset.textContent = 'Reset';
		filter.appendChild( reset );

		count.className = filter.classList.contains( 'spell-list-filter' ) ?
			'spell-list-filter__count' :
			'item-list-filter__count';
		filter.appendChild( count );

		function parseFields( value ) {
			if ( !value ) {
				return [
					{ key: 'slot', label: 'Slot', all: 'All slots' },
					{ key: 'construction', label: 'Construction', all: 'All levels' }
				];
			}
			return value.split( '|' ).map( function ( spec ) {
				var parts = spec.split( ':' );
				return {
					key: parts[ 0 ],
					label: parts[ 1 ] || parts[ 0 ],
					all: parts[ 2 ] || 'All'
				};
			} );
		}

		function buildSelect( sourceRows, key, labelText, allText ) {
			var label = document.createElement( 'label' );
			var select = document.createElement( 'select' );
			var values = [];
			var seen = {};

			sourceRows.forEach( function ( row ) {
				var value = row.dataset[ key ];
				if ( value && !seen[ value ] ) {
					seen[ value ] = true;
					values.push( value );
				}
			} );

			values.sort( function ( a, b ) {
				if ( key === 'construction' || key === 'research' ) {
					return Number( a ) - Number( b );
				}
				return a.localeCompare( b );
			} );

			select.dataset.filter = key;
			select.appendChild( new Option( allText, '' ) );
			values.forEach( function ( value ) {
				select.appendChild( new Option( value, value ) );
			} );

			label.appendChild( document.createTextNode( labelText + ' ' ) );
			label.appendChild( select );
			select.label = label;
			return select;
		}

		function applyFilters() {
			var visible = 0;
			rows.forEach( function ( row ) {
				var keep = selects.every( function ( select ) {
					var value = select.value;
					var key = select.getAttribute( 'data-filter' );
					return !value || row.dataset[ key ] === value;
				} );
				row.hidden = !keep;
				if ( keep ) {
					visible += 1;
				}
			} );
			if ( count ) {
				count.textContent = visible + ' items';
			}
		}

		selects.forEach( function ( select ) {
			select.addEventListener( 'change', applyFilters );
		} );

		reset.addEventListener( 'click', function () {
			selects.forEach( function ( select ) {
				select.value = '';
			} );
			applyFilters();
		} );

		applyFilters();
	}

	mw.hook( 'wikipage.content' ).add( function ( $content ) {
		var content = $content && $content[ 0 ] ? $content[ 0 ] : document;
		Array.prototype.forEach.call( content.querySelectorAll( '.domwiki-filter' ), initFilter );
	} );
}() );