MediaWiki:Common.js: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
(Added object for translation strings; removed obsolete code for old item hoverbox)
(Just kidding. MediaWiki itself still throws an error if you use ES6 syntax. So much for embracing modernity.)
 
(23 intermediate revisions by 3 users not shown)
Line 1: Line 1:
/* global mw, $ */
/* global mw */
/* jshint strict:false, browser:true */
/* jshint strict:true, jquery:true, esversion:5, bitwise:true, curly:true, eqeqeq:true, undef:true */


( function() {
( function() {
'use strict';
'use strict';
/* DO NOT ADD CODE ABOVE THIS LINE */


/* Translation strings */
/* Translation strings */
const i18n = {
var i18n = {
     expand: 'Expand',
     expandAll: 'Expand all',
     collapse: 'Collapse'
     collapseAll: 'Collapse all',
    defaultLicense: 'Copyright unlicensed',
};
};


/* Detect browser via JS and add a class to the main element so it can be used in css */
/**
function detect_browser() {
  * Hoverbox
    var browser = 'unknown';
  * @param  config Object containing configuration
    if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
        browser = 'opera';
    } else if (typeof InstallTrigger !== 'undefined') {
        browser = 'firefox';
    } else if (/constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification))) {
        browser = 'safari';
    } else if (/*@cc_on!@*/false || !!document.documentMode) {
        browser = 'internet-explorer';
    } else if (!(/*@cc_on!@*/false || !!document.documentMode) && !!window.StyleMedia) {
        browser = 'edge';
    } else if (!!window.chrome && !!window.chrome.webstore) {
        browser = 'chrome';
    }
    $('html').addClass('browser-' + browser);
}
 
/*
  * Responsive tables
  * @param  tables Table elements to be transformed into responsive tables
  */
  */
function reponsive_table (tables) {
function hoverbox(config) {
     if ( tables.length > 0 ) {
     var defaults = {
         const expand = '<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M0 180V56c0-13.3 10.7-24 24-24h124c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H64v84c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12zM288 44v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12V56c0-13.3-10.7-24-24-24H300c-6.6 0-12 5.4-12 12zm148 276h-40c-6.6 0-12 5.4-12 12v84h-84c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24V332c0-6.6-5.4-12-12-12zM160 468v-40c0-6.6-5.4-12-12-12H64v-84c0-6.6-5.4-12-12-12H12c-6.6 0-12 5.4-12 12v124c0 13.3 10.7 24 24 24h124c6.6 0 12-5.4 12-12z"></path></svg><span>' + i18n.expand + '</span>';
         mainClass: 'hoverbox',
         const collapse = '<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M436 192H312c-13.3 0-24-10.7-24-24V44c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v84h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-276-24V44c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v84H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24zm0 300V344c0-13.3-10.7-24-24-24H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-84h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H312c-13.3 0-24 10.7-24 24v124c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"></path></svg><span>' + i18n.collapse + '</span>';
         activatorClass: 'hoverbox__activator',
         const do_toggle = function( wrap ) {
         displayClass: 'hoverbox__display',
            if ( wrap.classList.contains('is-expanded') ) {
    };
                this.innerHTML = expand;
    config = Object.assign(defaults, config);
                wrap.classList.remove('is-expanded');
    var timestamp = Date.now(),
            } else {
        $container = $('#hoverbox-displays-' + timestamp);
                this.innerHTML = collapse;
    if ( $container.length === 0 ) {
                wrap.classList.add('is-expanded');
        $container = $('<div id="hoverbox-displays-' + timestamp + '" class="hoverbox-display-container"></div>');
            }
        };
        for ( var i = 0; i < tables.length; i++ ) {
            var table = tables[i];
            var wrap = document.createElement('div');
            wrap.classList.add('c-responsive-table');
            table.before(wrap);
            var scroll = document.createElement('div');
            scroll.classList.add('c-responsive-table__scroll');
            wrap.appendChild(scroll);
            scroll.appendChild(table);
            table.classList.add('c-responsive-table__table');
            if ( scroll.offsetHeight < scroll.scrollHeight ) {
                var toolbar = document.createElement('div');
                toolbar.classList.add('c-responsive-table__toolbar');
                scroll.before(toolbar);
                var toggle = document.createElement('button');
                toggle.classList.add('c-responsive-table__toolbar-button');
                toggle.innerHTML = expand;
                toolbar.appendChild(toggle);
                toggle.addEventListener( 'click', do_toggle.bind(toggle, wrap) );
            }
        }
     }
     }
}
    $('body').append($container);
 
     var $hoverbox = $('.' + config.mainClass),
/* Item hoverbox */
         idCounter = 0;
function item_hoverbox () {
     $hoverbox.each(function() {
     var $window = $(window),
         $hover = $('.c-item-hoverbox');
     $hover.each(function() {
         var $this = $(this),
         var $this = $(this),
             $activator = $this.find('.c-item-hoverbox__activator').first(),
             $activator = $this.find('.' + config.activatorClass).first(),
             $display = $this.find('.c-item-hoverbox__display').first();
             $display = $this.find('.' + config.displayClass).first(),
        $display.css('display', 'none');
            id = $this.data('hoverbox-id') || idCounter++,
            $target = $container.find('[data-hoverbox-target="' + id + '"]');
        if ( $target.length === 0 ) {
            $container.append($display);
            $display.attr('data-hoverbox-target', id);
        } else {
            $display.remove();
            $display = $target;
        }
         $activator.hover(function() {
         $activator.hover(function() {
            $display.css('display', '');
             var viewport = {},
             var viewport = {},
                 activator = {},
                 activator = {},
Line 88: Line 50:
                 position, // position relative to the activator
                 position, // position relative to the activator
                 location; // location relative to the viewport
                 location; // location relative to the viewport
             viewport.width = $window.width();
             viewport.width = document.documentElement.clientWidth;
             viewport.height = $window.height();
             viewport.height = document.documentElement.clientHeight;
             viewport.top = $window.scrollTop();
             viewport.top = document.documentElement.scrollTop;
             viewport.left = $window.scrollLeft();
             viewport.left = document.documentElement.scrollLeft;
             viewport.bottom = viewport.top + viewport.height;
             viewport.bottom = viewport.top + viewport.height;
             viewport.right = viewport.left + viewport.width;
             viewport.right = viewport.left + viewport.width;
Line 102: Line 64:
             display.width = $display.outerWidth();
             display.width = $display.outerWidth();
             display.height = $display.outerHeight();
             display.height = $display.outerHeight();
             if ( viewport.width < display.width ) { // Don't bother showing the hoverbox at all if the viewport is too small
             if (viewport.width < display.width) { // Don't bother showing the hoverbox at all if the viewport is too small
                 return false;
                 return false;
             }
             }
             if ( activator.left > viewport.width - activator.right ) {
             if (activator.left > viewport.width - activator.right) {
                 location = 'right';
                 location = 'right';
             } else {
             } else {
                 location = 'left';
                 location = 'left';
             }
             }
             if ( activator.top - display.height > viewport.top ) {
             if (activator.top - display.height > viewport.top) {
                 position = 'above';
                 position = 'above';
                 display.top = activator.top - display.height;
                 display.top = activator.top - display.height;
                 display.left = activator.left + (activator.width / 2) - (display.width / 2);
                 display.left = activator.left + (activator.width / 2) - (display.width / 2);
             } else if ( activator.right + display.width < viewport.right ) {
             } else if (activator.right + display.width < viewport.right) {
                 position = 'right-of';
                 position = 'right-of';
                 display.top = activator.top + (activator.height / 2) - (display.height / 2);
                 display.top = activator.top + (activator.height / 2) - (display.height / 2);
                 display.left = activator.right;
                 display.left = activator.right;
             } else if ( activator.left - display.width > viewport.left ) {
             } else if (activator.left - display.width > viewport.left) {
                 position = 'left-of';
                 position = 'left-of';
                 display.top = activator.top + (activator.height / 2) - (display.height / 2);
                 display.top = activator.top + (activator.height / 2) - (display.height / 2);
Line 127: Line 89:
                 display.left = activator.left + (activator.width / 2) - (display.width / 2);
                 display.left = activator.left + (activator.width / 2) - (display.width / 2);
             }
             }
             display.top = Math.max( viewport.top, display.top );
             display.top = Math.max(viewport.top, display.top);
             display.left = Math.max( viewport.left, Math.min(viewport.right - display.width, display.left) );
             display.left = Math.max(viewport.left, Math.min(viewport.right - display.width, display.left));
             $display.addClass('is-visible is-' + position + '-activator is-' + location + '-side-of-viewport').offset(display);
             $display.addClass('is-visible is-' + position + '-activator is-' + location + '-side-of-viewport').offset(display);
         }, function() {
         }, function() {
            $display.css('display', 'none');
             $display.removeClass('is-visible is-above-activator is-below-activator is-left-of-activator is-right-of-activator is-left-side-of-viewport is-right-side-of-viewport');
             $display.removeClass('is-visible is-above-activator is-below-activator is-left-of-activator is-right-of-activator is-left-side-of-viewport is-right-side-of-viewport');
         });
         });
     });
     });
}
/*
* Veiled modifiers
*/
function veiledModifier() {
    var mainClass = 'veiled'; // Class name of veiled modifier elements
    var affixCount = 6; // Number of veiled prefixes and veiled suffixes
    var affixClass = '-m0$1'; // $1 is replaced with a random number between 1 and affixCount
    var elements = document.getElementsByClassName(mainClass);
    if ( elements.length > 0 ) {
        var last, random;
        for ( var i = 0; i < elements.length; i++ ) {
            var element = elements[i];
            if ( last === undefined ) { // Choose with a random integer between 1 and affixCount
                random = Math.floor(Math.random() * affixCount) + 1;
            } else { // Continue choosing random integers in the same range while ensuring no repeats
                random = Math.floor(Math.random() * (affixCount - 1)) + 1;
                if ( random >= last ) {
                    random = random + 1;
                }
            }
            last = random;
            element.classList.add(affixClass.replace('$1', random));
        }
    }
}
function boolean_table() {
    $('.boolean-table').find('table').find('td').each(function () {
        var text = $(this).html();
        if (text == '0') {
            $(this).html('&#x2717;');
            $(this).addClass('table-cell-xmark');
        } else if (text == '1') {
            $(this).html('&#x2713;');
            $(this).addClass('table-cell-checkmark');
        }
    });
}
/**
* Gem quality widget
* @param  widgets  Elements containing gem quality widgets
*/
function gem_quality_widget(widgets) {
    if ( widgets.length > 0 ) {
        var do_toggle = function (widget) {
            if ( ! this.classList.contains('is-selected') ) {
                var options = widget.getElementsByClassName('gemqual-widget__option');
                var stats_collection = widget.getElementsByClassName('gemqual-widget__stats');
                for ( var i = 0; i < options.length; i++ ) {
                    var option = options[i];
                    var stats = stats_collection[i];
                    if ( option.dataset.qid === this.dataset.qid ) {
                        option.classList.add('is-selected');
                        stats.classList.add('is-selected');
                    } else {
                        option.classList.remove('is-selected');
                        stats.classList.remove('is-selected');
                    }
                }
            }
        };
        for ( var i = 0; i < widgets.length; i++ ) {
            var widget = widgets[i];
            var qtypes = widget.dataset.qtypes;
            qtypes = qtypes.split(',');
            var selector = document.createElement('div');
            selector.classList.add('gemqual-widget__selector');
            for ( var k = 0; k < qtypes.length; k++ ) {
                var option = document.createElement('button');
                option.classList.add('gemqual-widget__option');
                option.setAttribute('data-qid', k+1);
                option.innerHTML = qtypes[k];
                if ( k === 0 ) {
                    option.classList.add('is-selected');
                }
                selector.append(option);
                option.addEventListener( 'click', do_toggle.bind(option, widget) );
            }
            widget.prepend(selector);
        }
    }
}
/*
* Accordion
* @param  config  Object containing configuration
*/
function accordion(config) {
    var defaults = {
        mainClass: 'accordion',
        toggleClass: 'accordion__toggle',
        openStateClass: 'is-open',
        controlsClass: 'accordion__controls',
    };
    config = Object.assign(defaults, config);
    var accordions = document.getElementsByClassName(config.mainClass);
    if ( accordions.length === 0 ) {
        return;
    }
    var doToggle = function () {
        this.parentNode.classList.toggle(config.openStateClass);
    };
    for ( var i = 0; i < accordions.length; i++ ) {
        var accordion = accordions[i];
        var headings = accordion.getElementsByClassName(config.toggleClass);
        for ( var k = 0; k < headings.length; k++ ) {
            var heading = headings[k];
            var button = document.createElement('button');
            while ( heading.firstChild ) {
                button.appendChild(heading.firstChild);
            }
            heading.appendChild(button);
            button.addEventListener( 'click', doToggle.bind(button) );
        }
    }
    var controls = document.getElementsByClassName(config.controlsClass);
    if ( controls.length > 0 ) {
        var expandAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.add(config.openStateClass);
            }
        };
        var collapseAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.remove(config.openStateClass);
            }
        };
        var findToggles = function(el) {
            if ( el === null ) {
                return false;
            }
            var toggles = el.getElementsByClassName(config.toggleClass);
            if ( toggles.length === 0 ) {
                return findToggles(el.parentElement);
            }
            return toggles;
        };
        for ( var i = 0; i < controls.length; i++ ) {
            var control = controls[i];
            var expandButton = document.createElement('button');
            expandButton.innerHTML = i18n.expandAll;
            var collapseButton = document.createElement('button');
            collapseButton.innerHTML = i18n.collapseAll;
            control.append('[', expandButton, '] [', collapseButton, ']');
            var toggles = findToggles(control);
            if ( toggles ) {
                expandButton.addEventListener( 'click', expandAll.bind(expandButton, toggles) );
                collapseButton.addEventListener( 'click', collapseAll.bind(collapseButton, toggles) );
            }
        }
    }
}
function setDefaultFileUploadLicense() {
    if ( mw.config.get('wgCanonicalSpecialPageName') === 'Upload' ) {
        mw.loader.using( 'mediawiki.special.upload', function() {
            // Wait until the next event cycle to ensure that the licensing template preview loads
            setTimeout( function() {
                var licenseField = document.getElementById('wpLicense');
                if ( licenseField ) {
                    if ( licenseField.value === '' ) {
                        licenseField.value = i18n.defaultLicense;
                        licenseField.dispatchEvent( new Event('change') );
                    }
                    licenseField.querySelector('option[title="{{}}"]').remove();
                }
            } );
        } );
    }
}
}


/* Fires when DOM is ready */
/* Fires when DOM is ready */
$(function() {
$( function() {
 
     /* For adding expand/collapse all buttons for mw-collapsible */
     /* For adding expand/collapse all buttons for mw-collapsible */
     $(".mw-collapsible-collapse-all").on("click", function () {
     $(".mw-collapsible-collapse-all").on("click", function () {
Line 147: Line 283:
     });
     });


     // Browser detect
     // Hoverbox
     detect_browser();
     hoverbox();
 
    // Item hoverbox
    hoverbox({
        mainClass: 'c-item-hoverbox',
        activatorClass: 'c-item-hoverbox__activator',
        displayClass: 'c-item-hoverbox__display',
    });
 
    // Veiled modifiers
    veiledModifier();
      
      
     // Responsive tables
     // Change 1 & 0 to checkmarks in tables  
     reponsive_table( document.getElementsByClassName('responsive-table') );
     boolean_table();
     const table_containers = document.getElementsByClassName('responsive-table-container');
 
     for (var i = 0; i < table_containers.length; i++) {
     // Set default file upload license to unknown instead of none
        reponsive_table( table_containers[i].getElementsByTagName('table') );
     setDefaultFileUploadLicense();
    }


    // Item hoverbox
} );
    item_hoverbox();
});
/* End DOM ready */
/* End DOM ready */


/* DO NOT ADD CODE BELOW THIS LINE */
/* Fires when wiki content is added. */
mw.hook('wikipage.content').add( function($wikipageContent) {
 
    // Gem quality widget in item infobox
    gem_quality_widget( document.getElementsByClassName('gemqual-widget') );
 
    // Accordions
    accordion();
 
} );
 
}() );
}() );

Latest revision as of 15:54, 9 October 2023

/* global mw */
/* jshint strict:true, jquery:true, esversion:5, bitwise:true, curly:true, eqeqeq:true, undef:true */

( function() {
'use strict';

/* Translation strings */
var i18n = {
    expandAll: 'Expand all',
    collapseAll: 'Collapse all',
    defaultLicense: 'Copyright unlicensed',
};

/**
 * Hoverbox
 * @param  config  Object containing configuration
 */
function hoverbox(config) {
    var defaults = {
        mainClass: 'hoverbox',
        activatorClass: 'hoverbox__activator',
        displayClass: 'hoverbox__display',
    };
    config = Object.assign(defaults, config);
    var timestamp = Date.now(),
        $container = $('#hoverbox-displays-' + timestamp);
    if ( $container.length === 0 ) {
        $container = $('<div id="hoverbox-displays-' + timestamp + '" class="hoverbox-display-container"></div>');
    }
    $('body').append($container);
    var $hoverbox = $('.' + config.mainClass),
        idCounter = 0;
    $hoverbox.each(function() {
        var $this = $(this),
            $activator = $this.find('.' + config.activatorClass).first(),
            $display = $this.find('.' + config.displayClass).first(),
            id = $this.data('hoverbox-id') || idCounter++,
            $target = $container.find('[data-hoverbox-target="' + id + '"]');
        if ( $target.length === 0 ) {
            $container.append($display);
            $display.attr('data-hoverbox-target', id);
        } else {
            $display.remove();
            $display = $target;
        }
        $activator.hover(function() {
            var viewport = {},
                activator = {},
                display = {},
                position, // position relative to the activator
                location; // location relative to the viewport
            viewport.width = document.documentElement.clientWidth;
            viewport.height = document.documentElement.clientHeight;
            viewport.top = document.documentElement.scrollTop;
            viewport.left = document.documentElement.scrollLeft;
            viewport.bottom = viewport.top + viewport.height;
            viewport.right = viewport.left + viewport.width;
            activator.width = $activator.outerWidth();
            activator.height = $activator.outerHeight();
            activator.top = $activator.offset().top;
            activator.left = $activator.offset().left;
            activator.bottom = activator.top + activator.height;
            activator.right = activator.left + activator.width;
            display.width = $display.outerWidth();
            display.height = $display.outerHeight();
            if (viewport.width < display.width) { // Don't bother showing the hoverbox at all if the viewport is too small
                return false;
            }
            if (activator.left > viewport.width - activator.right) {
                location = 'right';
            } else {
                location = 'left';
            }
            if (activator.top - display.height > viewport.top) {
                position = 'above';
                display.top = activator.top - display.height;
                display.left = activator.left + (activator.width / 2) - (display.width / 2);
            } else if (activator.right + display.width < viewport.right) {
                position = 'right-of';
                display.top = activator.top + (activator.height / 2) - (display.height / 2);
                display.left = activator.right;
            } else if (activator.left - display.width > viewport.left) {
                position = 'left-of';
                display.top = activator.top + (activator.height / 2) - (display.height / 2);
                display.left = activator.left - display.width;
            } else {
                position = 'below';
                display.top = activator.bottom;
                display.left = activator.left + (activator.width / 2) - (display.width / 2);
            }
            display.top = Math.max(viewport.top, display.top);
            display.left = Math.max(viewport.left, Math.min(viewport.right - display.width, display.left));
            $display.addClass('is-visible is-' + position + '-activator is-' + location + '-side-of-viewport').offset(display);
        }, function() {
            $display.removeClass('is-visible is-above-activator is-below-activator is-left-of-activator is-right-of-activator is-left-side-of-viewport is-right-side-of-viewport');
        });
    });
}

/*
 * Veiled modifiers
 */
function veiledModifier() {
    var mainClass = 'veiled'; // Class name of veiled modifier elements
    var affixCount = 6; // Number of veiled prefixes and veiled suffixes
    var affixClass = '-m0$1'; // $1 is replaced with a random number between 1 and affixCount
    var elements = document.getElementsByClassName(mainClass);
    if ( elements.length > 0 ) {
        var last, random;
        for ( var i = 0; i < elements.length; i++ ) {
            var element = elements[i];
            if ( last === undefined ) { // Choose with a random integer between 1 and affixCount
                random = Math.floor(Math.random() * affixCount) + 1;
            } else { // Continue choosing random integers in the same range while ensuring no repeats
                random = Math.floor(Math.random() * (affixCount - 1)) + 1;
                if ( random >= last ) {
                    random = random + 1;
                }
            }
            last = random;
            element.classList.add(affixClass.replace('$1', random));
        }
    }
}

function boolean_table() {
    $('.boolean-table').find('table').find('td').each(function () {
        var text = $(this).html();
        if (text == '0') {
            $(this).html('&#x2717;');
            $(this).addClass('table-cell-xmark');
        } else if (text == '1') {
            $(this).html('&#x2713;');
            $(this).addClass('table-cell-checkmark');
        }
    });
}

/**
 * Gem quality widget
 * @param  widgets  Elements containing gem quality widgets
 */
function gem_quality_widget(widgets) {
    if ( widgets.length > 0 ) {
        var do_toggle = function (widget) {
            if ( ! this.classList.contains('is-selected') ) {
                var options = widget.getElementsByClassName('gemqual-widget__option');
                var stats_collection = widget.getElementsByClassName('gemqual-widget__stats');
                for ( var i = 0; i < options.length; i++ ) {
                    var option = options[i];
                    var stats = stats_collection[i];
                    if ( option.dataset.qid === this.dataset.qid ) {
                        option.classList.add('is-selected');
                        stats.classList.add('is-selected');
                    } else {
                        option.classList.remove('is-selected');
                        stats.classList.remove('is-selected');
                    }
                }
            }
        };
        for ( var i = 0; i < widgets.length; i++ ) {
            var widget = widgets[i];
            var qtypes = widget.dataset.qtypes;
            qtypes = qtypes.split(',');
            var selector = document.createElement('div');
            selector.classList.add('gemqual-widget__selector');
            for ( var k = 0; k < qtypes.length; k++ ) {
                var option = document.createElement('button');
                option.classList.add('gemqual-widget__option');
                option.setAttribute('data-qid', k+1);
                option.innerHTML = qtypes[k];
                if ( k === 0 ) {
                    option.classList.add('is-selected');
                }
                selector.append(option);
                option.addEventListener( 'click', do_toggle.bind(option, widget) );
            }
            widget.prepend(selector);
        }
    }
}

/*
 * Accordion
 * @param  config  Object containing configuration
 */
function accordion(config) {
    var defaults = {
        mainClass: 'accordion',
        toggleClass: 'accordion__toggle',
        openStateClass: 'is-open',
        controlsClass: 'accordion__controls',
    };
    config = Object.assign(defaults, config);

    var accordions = document.getElementsByClassName(config.mainClass);
    if ( accordions.length === 0 ) {
        return;
    }
    var doToggle = function () {
        this.parentNode.classList.toggle(config.openStateClass);
    };
    for ( var i = 0; i < accordions.length; i++ ) {
        var accordion = accordions[i];
        var headings = accordion.getElementsByClassName(config.toggleClass);
        for ( var k = 0; k < headings.length; k++ ) {
            var heading = headings[k];
            var button = document.createElement('button');
            while ( heading.firstChild ) {
                button.appendChild(heading.firstChild);
            }
            heading.appendChild(button);
            button.addEventListener( 'click', doToggle.bind(button) );
        }
    }

    var controls = document.getElementsByClassName(config.controlsClass);
    if ( controls.length > 0 ) {
        var expandAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.add(config.openStateClass);
            }
        };
        var collapseAll = function (toggles) {
            for ( var i = 0; i < toggles.length; i++ ) {
                toggles[i].classList.remove(config.openStateClass);
            }
        };
        var findToggles = function(el) {
            if ( el === null ) {
                return false;
            }
            var toggles = el.getElementsByClassName(config.toggleClass);
            if ( toggles.length === 0 ) {
                return findToggles(el.parentElement);
            }
            return toggles;
        };
        for ( var i = 0; i < controls.length; i++ ) {
            var control = controls[i];
            var expandButton = document.createElement('button');
            expandButton.innerHTML = i18n.expandAll;
            var collapseButton = document.createElement('button');
            collapseButton.innerHTML = i18n.collapseAll;
            control.append('[', expandButton, '] [', collapseButton, ']');
            var toggles = findToggles(control);
            if ( toggles ) {
                expandButton.addEventListener( 'click', expandAll.bind(expandButton, toggles) );
                collapseButton.addEventListener( 'click', collapseAll.bind(collapseButton, toggles) );
            }
        }
    }
}

function setDefaultFileUploadLicense() {
    if ( mw.config.get('wgCanonicalSpecialPageName') === 'Upload' ) {
        mw.loader.using( 'mediawiki.special.upload', function() {
            // Wait until the next event cycle to ensure that the licensing template preview loads
            setTimeout( function() {
                var licenseField = document.getElementById('wpLicense');
                if ( licenseField ) {
                    if ( licenseField.value === '' ) {
                        licenseField.value = i18n.defaultLicense;
                        licenseField.dispatchEvent( new Event('change') );
                    }
                    licenseField.querySelector('option[title="{{}}"]').remove();
                }
            } );
        } );
    }
}

/* Fires when DOM is ready */
$( function() {

    /* For adding expand/collapse all buttons for mw-collapsible */
    $(".mw-collapsible-collapse-all").on("click", function () {
        $('.mw-collapsible-toggle-expanded a').trigger('click');
    });
    $(".mw-collapsible-expand-all").on("click", function () {
        $(".mw-collapsible-toggle-collapsed a").trigger('click');
    });

    // Hoverbox
    hoverbox();

    // Item hoverbox
    hoverbox({
        mainClass: 'c-item-hoverbox',
        activatorClass: 'c-item-hoverbox__activator',
        displayClass: 'c-item-hoverbox__display',
    });

    // Veiled modifiers
    veiledModifier();
    
    // Change 1 & 0 to checkmarks in tables 
    boolean_table();

    // Set default file upload license to unknown instead of none
    setDefaultFileUploadLicense();

} );
/* End DOM ready */

/* Fires when wiki content is added. */
mw.hook('wikipage.content').add( function($wikipageContent) {

    // Gem quality widget in item infobox
    gem_quality_widget( document.getElementsByClassName('gemqual-widget') );

    // Accordions
    accordion();

} );

}() );