Jump to content

MediaWiki:Common.js: Difference between revisions

From Accessible Gaming Wiki
 
No edit summary
 
(One intermediate revision by the same user not shown)
Line 2: Line 2:


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


     mw.hook( 'wikipage.content' ).add( function ( $content ) {
     function setup( table ) {
         $content.find( 'table.platform-filter' ).each( function () {
         if ( table.dataset.platformFilterReady ) {
             var table = this;
             return;
             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;
             }
             }
             table.dataset.platformFilterReady = '1';
        }
        if ( !headerRow ) {
             return;
        }


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


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


            // Platform options. Edit this list to add or rename platforms.
        // Use the thead the sorter created; create one only if absent.
            // "label" appears in the dropdown; "match" is tested against
        var thead = table.tHead;
            // the text of the Platform cell (case-insensitive).
        if ( !thead ) {
             var platforms = [
             thead = document.createElement( 'thead' );
                { label: 'Windows',          match: /windows/i },
            table.insertBefore( thead, table.firstChild );
                { label: 'PlayStation',      match: /playstation/i },
        }
                { label: 'Xbox / Game Pass', match: /xbox|game ?pass/i },
        if ( headerRow.parentNode !== thead ) {
                { label: 'Nintendo Switch',  match: /switch/i },
            thead.appendChild( headerRow );
                { 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++ );
        // 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 }
        ];


            // Status line, announced to screen readers on change.
        var selectId = 'platform-filter-select-' + ( counter++ );
            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 second header row holding the combo box.
        // Status line, announced to screen readers on change.
            var filterRow = thead.insertRow( -1 );
        var status = document.createElement( 'div' );
        status.className = 'platform-filter-status';
        status.setAttribute( 'role', 'status' );
        status.setAttribute( 'aria-live', 'polite' );
        table.parentNode.insertBefore( status, table );


            if ( platformCol > 0 ) {
        // Build the filter row and place it in the thead, after the
                var lead = document.createElement( 'td' );
        // header row. The sorter already bound its click handlers to
                lead.colSpan = platformCol;
        // the header cells, so these extra cells do not affect sorting.
                filterRow.appendChild( lead );
        var filterRow = thead.insertRow( -1 );
            }


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


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


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


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


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


            // Keep dropdown clicks from reaching the sort handler.
        platforms.forEach( function ( p, idx ) {
             select.addEventListener( 'click', function ( e ) {
             var opt = document.createElement( 'option' );
                e.stopPropagation();
            opt.value = String( idx );
             } );
             opt.textContent = p.label;
             select.addEventListener( 'change', function () {
             select.appendChild( opt );
                applyFilter( this.value );
        } );
            } );


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


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


            function applyFilter( value ) {
        var trailing = headerCells.length - platformCol - 1;
                var rows = tbody.rows;
        if ( trailing > 0 ) {
                var total = rows.length;
            var tail = document.createElement( 'td' );
                var shown = 0;
            tail.colSpan = trailing;
                var test = ( value === '' ) ? null : platforms[ Number( value ) ].match;
            filterRow.appendChild( tail );
        }


                for ( var r = 0; r < total; r++ ) {
        function applyFilter( value ) {
                    var row = rows[ r ];
            var body = table.tBodies[ 0 ];
                    var pc = row.cells[ platformCol ];
            if ( !body ) {
                    var textVal = pc ? pc.textContent : '';
                return;
                    if ( !test || test.test( textVal ) ) {
            }
                        row.style.display = '';
            var rows = body.rows;
                        shown++;
            var total = rows.length;
                    } else {
            var shown = 0;
                        row.style.display = 'none';
            var test = ( value === '' ) ? null : platforms[ Number( value ) ].match;
                    }
                }


                 if ( !test ) {
            for ( var r = 0; r < total; r++ ) {
                     status.textContent = 'Showing all ' + total + ' games.';
                var row = rows[ r ];
                var pc = row.cells[ platformCol ];
                var textVal = pc ? pc.textContent : '';
                 if ( !test || test.test( textVal ) ) {
                     row.style.display = '';
                    shown++;
                 } else {
                 } else {
                     status.textContent = 'Showing ' + shown + ' of ' + total +
                     row.style.display = 'none';
                        ' games available on ' + platforms[ Number( value ) ].label + '.';
                 }
                 }
             }
             }
         } );
 
            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 );
    } );
}() );