MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
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 | var count = document.createElement( 'span' ); | ||
var count = filter. | var reset = document.createElement( 'button' ); | ||
var | 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: | ||
} ); | } ); | ||
reset.addEventListener( 'click', function () { | |||
selects.forEach( function ( select ) { | |||
select.value = ''; | |||
} ); | } ); | ||
} | 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 );
} );
}() );