Jump to content

MediaWiki:Common.js: Difference between revisions

From Accessible Gaming Wiki
Replaced content with "if ( !thead || !thead.rows.length || !tbody ) { return; }"
Tag: Replaced
No edit summary
 
Line 1: Line 1:
if ( !thead || !thead.rows.length || !tbody ) {
/* Any JavaScript here will be loaded for all users on every page load. */
     return;
 
}
/* 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 );
    } );
}() );

Latest revision as of 16:07, 7 July 2026

/* 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 );
    } );
}() );