MediaWiki:Common.js: Różnice pomiędzy wersjami

Z Dubbingpedia
Skocz do:nawigacja, szukaj
mNie podano opisu zmian
mNie podano opisu zmian
Linia 482: Linia 482:
             initializeTable
             initializeTable
         );
         );
        initializeSections( root );
    }
    if ( typeof mw !== 'undefined' && mw.hook ) {
        mw.hook( 'wikipage.content' ).add( initialize );
    } else if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', function () {
            initialize( document );
        } );
    } else {
        initialize( document );
    }
}() );
    function isLegacyInfobox( table ) {
        var style;
        if ( table.classList.contains( 'pdk-infobox' ) ) {
            return true;
        }
        style = ( table.getAttribute( 'style' ) || '' ).toLowerCase().replace( /\s/g, '' );
        return style.indexOf( 'float:right' ) !== -1 &&
            style.indexOf( 'clear:right' ) !== -1 &&
            ( style.indexOf( 'width:300px' ) !== -1 ||
                style.indexOf( 'width:312px' ) !== -1 ||
                style.indexOf( 'width:30em' ) !== -1 );
    }
    function normalizedLabel( cell ) {
        return cell.textContent.replace( /\u00a0/g, ' ' ).replace( /\s+/g, ' ' ).trim().toLowerCase();
    }
    function initializeInfobox( table ) {
        var rows;
        var dataRows = [];
        var titleRow = null;
        var titleCell = null;
        var body;
        var toggleRow;
        var toggleCell;
        var button;
        var icon;
        var text;
        var title;
        var controlledIds;
        if ( table.dataset.pdkInfoboxReady === '1' || !isLegacyInfobox( table ) ) {
            return;
        }
        table.dataset.pdkInfoboxReady = '1';
        table.classList.add( 'pdk-infobox' );
        rows = Array.prototype.slice.call( table.rows );
        rows.forEach( function ( row ) {
            var first = row.cells[ 0 ];
            var second = row.cells[ 1 ];
            if ( row.cells.length === 1 && first && first.colSpan >= 2 ) {
                if ( first.querySelector( 'img, .mw-file-element' ) ) {
                    first.classList.add( 'pdk-infobox__media' );
                } else if ( first.textContent.trim() ) {
                    first.classList.add( 'pdk-infobox__header' );
                    if ( !titleCell ) {
                        titleCell = first;
                    }
                } else {
                    first.classList.add( 'pdk-infobox__empty-head' );
                }
                return;
            }
            if ( first && second && first.tagName === 'TH' && second.tagName === 'TD' ) {
                first.classList.add( 'pdk-infobox__label' );
                second.classList.add( 'pdk-infobox__value' );
                if ( normalizedLabel( first ) === 'tytuł' ) {
                    row.classList.add( 'pdk-infobox__title-row' );
                    second.colSpan = 2;
                    titleRow = row;
                    titleCell = second;
                } else {
                    row.classList.add( 'pdk-infobox__data-row' );
                    dataRows.push( row );
                }
            }
        } );
        body = table.tBodies[ 0 ];
        if ( body && titleRow && body.firstElementChild !== titleRow ) {
            body.insertBefore( titleRow, body.firstElementChild );
        }
        if ( !body || !dataRows.length ) {
            return;
        }
        infoboxCounter += 1;
        controlledIds = dataRows.map( function ( row, index ) {
            if ( !row.id ) {
                row.id = 'pdk-infobox-row-' + infoboxCounter + '-' + ( index + 1 );
            }
            return row.id;
        } );
        title = titleCell ? titleCell.textContent.replace( /\s+/g, ' ' ).trim() : '';
        toggleRow = document.createElement( 'tr' );
        toggleRow.className = 'pdk-infobox__toggle-row';
        toggleCell = document.createElement( 'td' );
        toggleCell.colSpan = 2;
        toggleCell.style.padding = '0';
        button = document.createElement( 'button' );
        button.type = 'button';
        button.className = 'pdk-infobox__toggle';
        button.setAttribute( 'aria-expanded', 'false' );
        button.setAttribute( 'aria-controls', controlledIds.join( ' ' ) );
        button.setAttribute(
            'aria-label',
            'Pokaż szczegóły infoboksu' + ( title ? ': ' + title : '' )
        );
        icon = document.createElement( 'span' );
        icon.className = 'pdk-infobox__toggle-icon';
        icon.setAttribute( 'aria-hidden', 'true' );
        text = document.createElement( 'span' );
        text.className = 'pdk-infobox__toggle-text';
        text.textContent = 'Pokaż szczegóły';
        button.appendChild( icon );
        button.appendChild( text );
        toggleCell.appendChild( button );
        toggleRow.appendChild( toggleCell );
        body.insertBefore( toggleRow, dataRows[ 0 ] );
        table.classList.add( 'pdk-infobox--collapsed' );
        button.addEventListener( 'click', function () {
            var expanded = button.getAttribute( 'aria-expanded' ) === 'true';
            table.classList.toggle( 'pdk-infobox--collapsed', expanded );
            button.setAttribute( 'aria-expanded', expanded ? 'false' : 'true' );
            text.textContent = expanded ? 'Pokaż szczegóły' : 'Ukryj szczegóły';
            button.setAttribute(
                'aria-label',
                ( expanded ? 'Pokaż' : 'Ukryj' ) + ' szczegóły infoboksu' +
                    ( title ? ': ' + title : '' )
            );
        } );
    }
    function initializeInfoboxes( root ) {
        var tables = [];
        if ( root.matches && root.matches( 'table' ) ) {
            tables.push( root );
        }
        Array.prototype.forEach.call( root.querySelectorAll( 'table' ), function ( table ) {
            tables.push( table );
        } );
        tables.forEach( initializeInfobox );
    }
    function initialize( content ) {
        var root = content && content[ 0 ] ? content[ 0 ] : content || document;
        Array.prototype.forEach.call(
            root.querySelectorAll( 'table.js-pdk-episodes' ),
            initializeTable
        );
        initializeInfoboxes( root );
         initializeSections( root );
         initializeSections( root );
     }
     }

Wersja z 09:56, 15 sie 2026

/* global mw */
( function () {
    'use strict';

    var COLUMN_CLASSES = {
        number: 'pdk-episodes__number',
        date: 'pdk-episodes__date',
        title: 'pdk-episodes__title',
        original: 'pdk-episodes__original'
    };
    var sectionCounter = 0;

    function buildGrid( rows ) {
        var grid = [];
        rows.forEach( function ( row, rowIndex ) {
            var column = 0;
            grid[ rowIndex ] = grid[ rowIndex ] || [];
            Array.prototype.forEach.call( row.cells, function ( cell ) {
                var rowOffset;
                var columnOffset;
                while ( grid[ rowIndex ][ column ] ) {
                    column += 1;
                }
                for ( rowOffset = 0; rowOffset < cell.rowSpan; rowOffset += 1 ) {
                    grid[ rowIndex + rowOffset ] = grid[ rowIndex + rowOffset ] || [];
                    for ( columnOffset = 0; columnOffset < cell.colSpan; columnOffset += 1 ) {
                        grid[ rowIndex + rowOffset ][ column + columnOffset ] = cell;
                    }
                }
                column += cell.colSpan;
            } );
        } );
        return grid;
    }

    function makeGroups( dataRows ) {
        var groups = [];
        var index = 0;
        while ( index < dataRows.length ) {
            var firstRow = dataRows[ index ];
            var span = 1;
            Array.prototype.forEach.call( firstRow.cells, function ( cell ) {
                span = Math.max( span, cell.rowSpan || 1 );
            } );
            var groupRows = dataRows.slice( index, index + span );
            groupRows.forEach( function ( row, rowOffset ) {
                row.classList.add( 'pdk-episodes__row' );
                if ( rowOffset > 0 ) {
                    row.classList.add( 'pdk-episodes__continuation' );
                }
            } );
            groups.push( {
                rows: groupRows,
                originalIndex: groups.length
            } );
            index += span;
        }
        return groups;
    }

    function initializeSeasonToggles( table, rows ) {
        var seasons = rows.filter( function ( row ) {
            return row.classList.contains( 'pdk-episodes__season' );
        } );
        seasons.forEach( function ( season, seasonIndex ) {
            var start = rows.indexOf( season ) + 1;
            var nextSeason = seasons[ seasonIndex + 1 ];
            var end = nextSeason ? rows.indexOf( nextSeason ) : rows.length;
            var controlledRows = rows.slice( start, end ).filter( function ( row ) {
                return row.cells.length > 0;
            } );
            var cell = season.querySelector( 'th' );
            if ( !cell || cell.querySelector( '.pdk-episodes__season-toggle' ) ) {
                return;
            }

            var seasonName = cell.textContent.trim();
            var button = document.createElement( 'button' );
            var icon = document.createElement( 'span' );
            button.type = 'button';
            button.className = 'pdk-episodes__season-toggle';
            button.setAttribute( 'aria-expanded', 'true' );
            button.setAttribute( 'aria-label', 'Zwiń: ' + seasonName );
            button.title = 'Zwiń serię';
            icon.className = 'pdk-episodes__toggle-icon';
            icon.setAttribute( 'aria-hidden', 'true' );
            button.appendChild( icon );
            button.addEventListener( 'click', function () {
                var expanded = button.getAttribute( 'aria-expanded' ) === 'true';
                controlledRows.forEach( function ( row ) {
                    row.classList.toggle( 'pdk-episodes__row--series-hidden', expanded );
                } );
                button.setAttribute( 'aria-expanded', expanded ? 'false' : 'true' );
                button.setAttribute(
                    'aria-label',
                    ( expanded ? 'Rozwiń: ' : 'Zwiń: ' ) + seasonName
                );
                button.title = expanded ? 'Rozwiń serię' : 'Zwiń serię';
            } );
            cell.appendChild( button );
        } );
    }

    function parseDate( value ) {
        var exact = value.match( /\b(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{4})\b/ );
        if ( exact ) {
            return Number( exact[ 3 ] ) * 10000 + Number( exact[ 2 ] ) * 100 + Number( exact[ 1 ] );
        }
        var month = value.match( /\b(\d{1,2})[.\/-](\d{4})\b/ );
        if ( month ) {
            return Number( month[ 2 ] ) * 10000 + Number( month[ 1 ] ) * 100;
        }
        var year = value.match( /\b(\d{4})\b/ );
        return year ? Number( year[ 1 ] ) * 10000 : null;
    }

    function textForColumn( group, column, grid, rowIndexes ) {
        var value = '';
        group.rows.some( function ( row ) {
            var rowIndex = rowIndexes.get( row );
            var cell = grid[ rowIndex ] && grid[ rowIndex ][ column ];
            var candidate = cell ? cell.textContent.trim() : '';
            if ( candidate ) {
                value = candidate;
                return true;
            }
            return false;
        } );
        return value;
    }

    function createMobileControls( table, descriptors, applySort ) {
        var sortable = descriptors.filter( function ( descriptor ) {
            return descriptor.sortType;
        } );
        if ( !sortable.length ) {
            return null;
        }

        var labels = {};
        sortable.forEach( function ( descriptor ) {
            labels[ descriptor.label ] = ( labels[ descriptor.label ] || 0 ) + 1;
        } );
        var seen = {};
        var controls = document.createElement( 'div' );
        controls.className = 'pdk-episodes__mobile-sort';

        var select = document.createElement( 'select' );
        select.setAttribute( 'aria-label', 'Sortuj listę odcinków' );
        var original = document.createElement( 'option' );
        original.value = '';
        original.textContent = 'Kolejność według serii';
        select.appendChild( original );

        sortable.forEach( function ( descriptor ) {
            seen[ descriptor.label ] = ( seen[ descriptor.label ] || 0 ) + 1;
            var option = document.createElement( 'option' );
            option.value = String( descriptor.column );
            option.textContent = labels[ descriptor.label ] > 1 ?
                descriptor.label + ' (' + seen[ descriptor.label ] + ')' : descriptor.label;
            select.appendChild( option );
        } );

        var direction = document.createElement( 'button' );
        direction.type = 'button';
        direction.disabled = true;
        direction.textContent = '↑';
        direction.title = 'Zmień kierunek sortowania';
        direction.setAttribute( 'aria-label', 'Zmień kierunek sortowania' );

        select.addEventListener( 'change', function () {
            if ( select.value === '' ) {
                direction.disabled = true;
                direction.textContent = '↑';
                applySort( null, 'original' );
                return;
            }
            direction.disabled = false;
            direction.textContent = '↑';
            applySort( Number( select.value ), 'ascending' );
        } );

        direction.addEventListener( 'click', function () {
            var next = direction.textContent === '↑' ? 'descending' : 'ascending';
            direction.textContent = next === 'ascending' ? '↑' : '↓';
            applySort( Number( select.value ), next );
        } );

        controls.appendChild( select );
        controls.appendChild( direction );
        table.parentNode.insertBefore( controls, table );

        return {
            select: select,
            direction: direction
        };
    }

    function initializeTable( table ) {
        if ( table.dataset.pdkEpisodesReady === '1' ) {
            return;
        }
        table.dataset.pdkEpisodesReady = '1';

        var rows = Array.prototype.slice.call( table.rows );
        var grid = buildGrid( rows );
        var rowIndexes = new Map();
        rows.forEach( function ( row, index ) {
            rowIndexes.set( row, index );
        } );

        var headerRow = rows.find( function ( row ) {
            return !row.classList.contains( 'pdk-episodes__season' ) &&
                row.querySelector( 'th[data-pdk-sort], th[data-pdk-column]' );
        } );
        if ( !headerRow ) {
            return;
        }
        headerRow.classList.add( 'pdk-episodes__head' );
        initializeSeasonToggles( table, rows );

        var headerIndex = rowIndexes.get( headerRow );
        var descriptors = [];
        var usedHeaders = new Set();
        ( grid[ headerIndex ] || [] ).forEach( function ( cell, column ) {
            if ( !cell || usedHeaders.has( cell ) ) {
                return;
            }
            usedHeaders.add( cell );
            descriptors.push( {
                cell: cell,
                column: column,
                sortType: cell.dataset.pdkSort || '',
                columnType: cell.dataset.pdkColumn || '',
                label: cell.textContent.trim()
            } );
        } );

        var columnCounts = {};
        descriptors.forEach( function ( descriptor ) {
            if ( descriptor.columnType ) {
                columnCounts[ descriptor.columnType ] =
                    ( columnCounts[ descriptor.columnType ] || 0 ) + 1;
            }
        } );

        var dataRows = rows.filter( function ( row ) {
            return row !== headerRow &&
                !row.classList.contains( 'pdk-episodes__season' ) &&
                row.cells.length > 0 &&
                !Array.prototype.some.call( row.cells, function ( cell ) {
                    return cell.tagName === 'TH';
                } );
        } );

        descriptors.forEach( function ( descriptor ) {
            dataRows.forEach( function ( row ) {
                var rowIndex = rowIndexes.get( row );
                var cell = grid[ rowIndex ] && grid[ rowIndex ][ descriptor.column ];
                if ( !cell || cell.tagName !== 'TD' ) {
                    return;
                }
                if ( descriptor.columnType && COLUMN_CLASSES[ descriptor.columnType ] ) {
                    cell.classList.add( COLUMN_CLASSES[ descriptor.columnType ] );
                    if ( columnCounts[ descriptor.columnType ] > 1 ) {
                        cell.classList.add( 'pdk-episodes__column--labelled' );
                    }
                }
                if ( !cell.dataset.pdkLabel ) {
                    cell.dataset.pdkLabel = descriptor.label;
                }
            } );
        } );

        var groups = makeGroups( dataRows );
        var originalRows = rows.map( function ( row ) {
            return { row: row, parent: row.parentNode };
        } );
        var collator = new Intl.Collator( 'pl', { numeric: true, sensitivity: 'base' } );
        var currentColumn = null;
        var currentDirection = 'original';
        var mobileControls;

        function restoreOriginalOrder() {
            originalRows.forEach( function ( entry ) {
                entry.parent.appendChild( entry.row );
            } );
        }

        function updateIndicators( column, direction ) {
            descriptors.forEach( function ( descriptor ) {
                descriptor.cell.removeAttribute( 'aria-sort' );
            } );
            if ( column !== null && direction !== 'original' ) {
                var active = descriptors.find( function ( descriptor ) {
                    return descriptor.column === column;
                } );
                if ( active ) {
                    active.cell.setAttribute( 'aria-sort', direction );
                }
            }
            if ( mobileControls ) {
                mobileControls.select.value = column === null ? '' : String( column );
                mobileControls.direction.disabled = column === null;
                mobileControls.direction.textContent = direction === 'descending' ? '↓' : '↑';
            }
        }

        function applySort( column, direction ) {
            currentColumn = column;
            currentDirection = direction;
            if ( column === null || direction === 'original' ) {
                restoreOriginalOrder();
                table.classList.remove( 'pdk-episodes--sorted' );
                updateIndicators( null, 'original' );
                return;
            }

            var descriptor = descriptors.find( function ( item ) {
                return item.column === column;
            } );
            if ( !descriptor ) {
                return;
            }
            var sorted = groups.slice().sort( function ( left, right ) {
                var leftText = textForColumn( left, column, grid, rowIndexes );
                var rightText = textForColumn( right, column, grid, rowIndexes );
                var leftValue = descriptor.sortType === 'date' ? parseDate( leftText ) : leftText;
                var rightValue = descriptor.sortType === 'date' ? parseDate( rightText ) : rightText;
                var leftMissing = leftValue === null || leftValue === '';
                var rightMissing = rightValue === null || rightValue === '';
                if ( leftMissing !== rightMissing ) {
                    return leftMissing ? 1 : -1;
                }
                var comparison = descriptor.sortType === 'date' ?
                    leftValue - rightValue : collator.compare( leftValue, rightValue );
                if ( comparison === 0 ) {
                    return left.originalIndex - right.originalIndex;
                }
                return direction === 'descending' ? -comparison : comparison;
            } );

            var parent = groups.length && groups[ 0 ].rows.length ?
                groups[ 0 ].rows[ 0 ].parentNode : null;
            if ( parent ) {
                sorted.forEach( function ( group ) {
                    group.rows.forEach( function ( row ) {
                        parent.appendChild( row );
                    } );
                } );
            }
            table.classList.add( 'pdk-episodes--sorted' );
            updateIndicators( column, direction );
        }

        descriptors.filter( function ( descriptor ) {
            return descriptor.sortType;
        } ).forEach( function ( descriptor ) {
            var button = document.createElement( 'button' );
            var icon = document.createElement( 'span' );
            button.type = 'button';
            button.className = 'pdk-episodes__sort';
            button.title = 'Sortuj według: ' + descriptor.label;
            button.setAttribute( 'aria-label', 'Sortuj według: ' + descriptor.label );
            icon.className = 'pdk-episodes__sort-icon';
            icon.setAttribute( 'aria-hidden', 'true' );
            button.appendChild( icon );
            button.addEventListener( 'click', function () {
                var nextDirection = 'ascending';
                if ( currentColumn === descriptor.column && currentDirection === 'ascending' ) {
                    nextDirection = 'descending';
                } else if ( currentColumn === descriptor.column && currentDirection === 'descending' ) {
                    applySort( null, 'original' );
                    return;
                }
                applySort( descriptor.column, nextDirection );
            } );
            descriptor.cell.appendChild( button );
        } );

        mobileControls = createMobileControls( table, descriptors, applySort );
    }

    function headingLevel( node ) {
        if ( node.matches( 'h2' ) || node.classList.contains( 'mw-heading2' ) ) {
            return 2;
        }
        if ( node.matches( 'h3' ) || node.classList.contains( 'mw-heading3' ) ) {
            return 3;
        }
        return 0;
    }

    function initializeSectionContainer( container ) {
        if ( container.dataset.pdkSectionsReady === '1' ) {
            return;
        }
        container.dataset.pdkSectionsReady = '1';

        var headings = Array.prototype.slice.call( container.children ).map(
            function ( node ) {
                return {
                    node: node,
                    level: headingLevel( node )
                };
            }
        ).filter( function ( heading ) {
            return heading.level > 0;
        } );

        headings.slice().reverse().forEach( function ( heading ) {
            var content = document.createElement( 'div' );
            var cursor = heading.node.nextSibling;
            sectionCounter += 1;
            content.className = 'pdk-section-content';
            content.id = 'pdk-section-content-' + sectionCounter;
            heading.node.parentNode.insertBefore( content, cursor );

            while ( cursor ) {
                var next = cursor.nextSibling;
                var nextLevel = cursor.nodeType === 1 ? headingLevel( cursor ) : 0;
                if ( nextLevel && nextLevel <= heading.level ) {
                    break;
                }
                content.appendChild( cursor );
                cursor = next;
            }

            var titleElement = heading.node.matches( 'h2, h3' ) ?
                heading.node : heading.node.querySelector( 'h2, h3' );
            if ( !titleElement ) {
                return;
            }
            var title = titleElement.textContent.trim();
            var button = document.createElement( 'button' );
            var icon = document.createElement( 'span' );
            button.type = 'button';
            button.className = 'pdk-section-toggle';
            button.setAttribute( 'aria-expanded', 'true' );
            button.setAttribute( 'aria-controls', content.id );
            button.setAttribute( 'aria-label', 'Zwiń sekcję: ' + title );
            button.title = 'Zwiń sekcję';
            icon.className = 'pdk-section-toggle__icon';
            icon.setAttribute( 'aria-hidden', 'true' );
            button.appendChild( icon );
            button.addEventListener( 'click', function () {
                var expanded = button.getAttribute( 'aria-expanded' ) === 'true';
                content.hidden = expanded;
                heading.node.classList.toggle( 'pdk-section-heading--collapsed', expanded );
                button.setAttribute( 'aria-expanded', expanded ? 'false' : 'true' );
                button.setAttribute(
                    'aria-label',
                    ( expanded ? 'Rozwiń sekcję: ' : 'Zwiń sekcję: ' ) + title
                );
                button.title = expanded ? 'Rozwiń sekcję' : 'Zwiń sekcję';
            } );
            heading.node.classList.add( 'pdk-section-heading' );
            heading.node.appendChild( button );
        } );
    }

    function initializeSections( root ) {
        var containers = [];
        if ( root.matches && root.matches( '.mw-parser-output' ) ) {
            containers.push( root );
        }
        Array.prototype.forEach.call(
            root.querySelectorAll( '.mw-parser-output' ),
            function ( container ) {
                if ( containers.indexOf( container ) === -1 ) {
                    containers.push( container );
                }
            }
        );
        containers.forEach( initializeSectionContainer );
    }

    function initialize( content ) {
        var root = content && content[ 0 ] ? content[ 0 ] : content || document;
        Array.prototype.forEach.call(
            root.querySelectorAll( 'table.js-pdk-episodes' ),
            initializeTable
        );
        initializeSections( root );
    }

    if ( typeof mw !== 'undefined' && mw.hook ) {
        mw.hook( 'wikipage.content' ).add( initialize );
    } else if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', function () {
            initialize( document );
        } );
    } else {
        initialize( document );
    }
}() );

    function isLegacyInfobox( table ) {
        var style;
        if ( table.classList.contains( 'pdk-infobox' ) ) {
            return true;
        }
        style = ( table.getAttribute( 'style' ) || '' ).toLowerCase().replace( /\s/g, '' );
        return style.indexOf( 'float:right' ) !== -1 &&
            style.indexOf( 'clear:right' ) !== -1 &&
            ( style.indexOf( 'width:300px' ) !== -1 ||
                style.indexOf( 'width:312px' ) !== -1 ||
                style.indexOf( 'width:30em' ) !== -1 );
    }

    function normalizedLabel( cell ) {
        return cell.textContent.replace( /\u00a0/g, ' ' ).replace( /\s+/g, ' ' ).trim().toLowerCase();
    }

    function initializeInfobox( table ) {
        var rows;
        var dataRows = [];
        var titleRow = null;
        var titleCell = null;
        var body;
        var toggleRow;
        var toggleCell;
        var button;
        var icon;
        var text;
        var title;
        var controlledIds;

        if ( table.dataset.pdkInfoboxReady === '1' || !isLegacyInfobox( table ) ) {
            return;
        }
        table.dataset.pdkInfoboxReady = '1';
        table.classList.add( 'pdk-infobox' );
        rows = Array.prototype.slice.call( table.rows );

        rows.forEach( function ( row ) {
            var first = row.cells[ 0 ];
            var second = row.cells[ 1 ];
            if ( row.cells.length === 1 && first && first.colSpan >= 2 ) {
                if ( first.querySelector( 'img, .mw-file-element' ) ) {
                    first.classList.add( 'pdk-infobox__media' );
                } else if ( first.textContent.trim() ) {
                    first.classList.add( 'pdk-infobox__header' );
                    if ( !titleCell ) {
                        titleCell = first;
                    }
                } else {
                    first.classList.add( 'pdk-infobox__empty-head' );
                }
                return;
            }

            if ( first && second && first.tagName === 'TH' && second.tagName === 'TD' ) {
                first.classList.add( 'pdk-infobox__label' );
                second.classList.add( 'pdk-infobox__value' );
                if ( normalizedLabel( first ) === 'tytuł' ) {
                    row.classList.add( 'pdk-infobox__title-row' );
                    second.colSpan = 2;
                    titleRow = row;
                    titleCell = second;
                } else {
                    row.classList.add( 'pdk-infobox__data-row' );
                    dataRows.push( row );
                }
            }
        } );

        body = table.tBodies[ 0 ];
        if ( body && titleRow && body.firstElementChild !== titleRow ) {
            body.insertBefore( titleRow, body.firstElementChild );
        }
        if ( !body || !dataRows.length ) {
            return;
        }

        infoboxCounter += 1;
        controlledIds = dataRows.map( function ( row, index ) {
            if ( !row.id ) {
                row.id = 'pdk-infobox-row-' + infoboxCounter + '-' + ( index + 1 );
            }
            return row.id;
        } );
        title = titleCell ? titleCell.textContent.replace( /\s+/g, ' ' ).trim() : '';

        toggleRow = document.createElement( 'tr' );
        toggleRow.className = 'pdk-infobox__toggle-row';
        toggleCell = document.createElement( 'td' );
        toggleCell.colSpan = 2;
        toggleCell.style.padding = '0';
        button = document.createElement( 'button' );
        button.type = 'button';
        button.className = 'pdk-infobox__toggle';
        button.setAttribute( 'aria-expanded', 'false' );
        button.setAttribute( 'aria-controls', controlledIds.join( ' ' ) );
        button.setAttribute(
            'aria-label',
            'Pokaż szczegóły infoboksu' + ( title ? ': ' + title : '' )
        );
        icon = document.createElement( 'span' );
        icon.className = 'pdk-infobox__toggle-icon';
        icon.setAttribute( 'aria-hidden', 'true' );
        text = document.createElement( 'span' );
        text.className = 'pdk-infobox__toggle-text';
        text.textContent = 'Pokaż szczegóły';
        button.appendChild( icon );
        button.appendChild( text );
        toggleCell.appendChild( button );
        toggleRow.appendChild( toggleCell );
        body.insertBefore( toggleRow, dataRows[ 0 ] );
        table.classList.add( 'pdk-infobox--collapsed' );

        button.addEventListener( 'click', function () {
            var expanded = button.getAttribute( 'aria-expanded' ) === 'true';
            table.classList.toggle( 'pdk-infobox--collapsed', expanded );
            button.setAttribute( 'aria-expanded', expanded ? 'false' : 'true' );
            text.textContent = expanded ? 'Pokaż szczegóły' : 'Ukryj szczegóły';
            button.setAttribute(
                'aria-label',
                ( expanded ? 'Pokaż' : 'Ukryj' ) + ' szczegóły infoboksu' +
                    ( title ? ': ' + title : '' )
            );
        } );
    }

    function initializeInfoboxes( root ) {
        var tables = [];
        if ( root.matches && root.matches( 'table' ) ) {
            tables.push( root );
        }
        Array.prototype.forEach.call( root.querySelectorAll( 'table' ), function ( table ) {
            tables.push( table );
        } );
        tables.forEach( initializeInfobox );
    }

    function initialize( content ) {
        var root = content && content[ 0 ] ? content[ 0 ] : content || document;
        Array.prototype.forEach.call(
            root.querySelectorAll( 'table.js-pdk-episodes' ),
            initializeTable
        );
        initializeInfoboxes( root );
        initializeSections( root );
    }

    if ( typeof mw !== 'undefined' && mw.hook ) {
        mw.hook( 'wikipage.content' ).add( initialize );
    } else if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', function () {
            initialize( document );
        } );
    } else {
        initialize( document );
    }
}() );