Jump to content

MediaWiki:Common.js

From Accessible Gaming Wiki
Revision as of 16:07, 7 July 2026 by Ross (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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.
/* Any JavaScript here will be loaded for all users on every page load. */

/* Platform filter for the PC and Console Games table.
   Runs AFTER MediaWiki's table sorter so the two do not conflict,
   then adds a combo box in the header under the Platform column.
   "Contains" matching means multi-platform games appear under
   every platform they support. */
( function () {
    var counter = 0;

    function setup( table ) {
        if ( table.dataset.platformFilterReady ) {
            return;
        }

        // Find the header row: the first row that contains a <th>.
        var headerRow = null;
        var allRows = table.rows;
        for ( var i = 0; i < allRows.length; i++ ) {
            if ( allRows[ i ].getElementsByTagName( 'th' ).length ) {
                headerRow = allRows[ i ];
                break;
            }
        }
        if ( !headerRow ) {
            return;
        }

        // Find the Platform column by its header text.
        var headerCells = headerRow.cells;
        var platformCol = -1;
        for ( var j = 0; j < headerCells.length; j++ ) {
            if ( /platform/i.test( headerCells[ j ].textContent ) ) {
                platformCol = j;
                break;
            }
        }
        if ( platformCol === -1 ) {
            return;
        }

        table.dataset.platformFilterReady = '1';

        // Use the thead the sorter created; create one only if absent.
        var thead = table.tHead;
        if ( !thead ) {
            thead = document.createElement( 'thead' );
            table.insertBefore( thead, table.firstChild );
        }
        if ( headerRow.parentNode !== thead ) {
            thead.appendChild( headerRow );
        }

        // Platform options. Edit this list to add or rename platforms.
        var platforms = [
            { label: 'Windows',          match: /windows/i },
            { label: 'PlayStation',      match: /playstation/i },
            { label: 'Xbox / Game Pass', match: /xbox|game ?pass/i },
            { label: 'Nintendo Switch',  match: /switch/i },
            { label: 'iOS',              match: /\bios\b/i },
            { label: 'Android',          match: /android/i },
            { label: 'Web',              match: /\bweb\b/i },
            { label: 'Linux',            match: /linux/i }
        ];

        var selectId = 'platform-filter-select-' + ( counter++ );

        // Status line, announced to screen readers on change.
        var status = document.createElement( 'div' );
        status.className = 'platform-filter-status';
        status.setAttribute( 'role', 'status' );
        status.setAttribute( 'aria-live', 'polite' );
        table.parentNode.insertBefore( status, table );

        // Build the filter row and place it in the thead, after the
        // header row. The sorter already bound its click handlers to
        // the header cells, so these extra cells do not affect sorting.
        var filterRow = thead.insertRow( -1 );

        if ( platformCol > 0 ) {
            var lead = document.createElement( 'td' );
            lead.colSpan = platformCol;
            filterRow.appendChild( lead );
        }

        var pcell = document.createElement( 'td' );

        var label = document.createElement( 'label' );
        label.setAttribute( 'for', selectId );
        label.textContent = 'Filter by platform: ';

        var select = document.createElement( 'select' );
        select.id = selectId;

        var optAll = document.createElement( 'option' );
        optAll.value = '';
        optAll.textContent = 'All platforms';
        select.appendChild( optAll );

        platforms.forEach( function ( p, idx ) {
            var opt = document.createElement( 'option' );
            opt.value = String( idx );
            opt.textContent = p.label;
            select.appendChild( opt );
        } );

        select.addEventListener( 'click', function ( e ) {
            e.stopPropagation();
        } );
        select.addEventListener( 'change', function () {
            applyFilter( this.value );
        } );

        pcell.appendChild( label );
        pcell.appendChild( select );
        filterRow.appendChild( pcell );

        var trailing = headerCells.length - platformCol - 1;
        if ( trailing > 0 ) {
            var tail = document.createElement( 'td' );
            tail.colSpan = trailing;
            filterRow.appendChild( tail );
        }

        function applyFilter( value ) {
            var body = table.tBodies[ 0 ];
            if ( !body ) {
                return;
            }
            var rows = body.rows;
            var total = rows.length;
            var shown = 0;
            var test = ( value === '' ) ? null : platforms[ Number( value ) ].match;

            for ( var r = 0; r < total; r++ ) {
                var row = rows[ r ];
                var pc = row.cells[ platformCol ];
                var textVal = pc ? pc.textContent : '';
                if ( !test || test.test( textVal ) ) {
                    row.style.display = '';
                    shown++;
                } else {
                    row.style.display = 'none';
                }
            }

            if ( !test ) {
                status.textContent = 'Showing all ' + total + ' games.';
            } else {
                status.textContent = 'Showing ' + shown + ' of ' + total +
                    ' games available on ' + platforms[ Number( value ) ].label + '.';
            }
        }

        // Initial confirmation, findable by navigating just before
        // the table even though it will not auto-announce at load.
        var body = table.tBodies[ 0 ];
        var count = body ? body.rows.length : 0;
        status.textContent = 'Platform filter ready. Showing all ' + count + ' games.';
    }

    mw.hook( 'wikipage.content' ).add( function ( $content ) {
        // Defer one tick so the table sorter finishes first, then we
        // attach to the header it built instead of racing it.
        setTimeout( function () {
            $content.find( 'table.platform-filter' ).each( function () {
                setup( this );
            } );
        }, 0 );
    } );
}() );