MediaWiki:Common.js: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
No edit summary
(Just kidding. MediaWiki itself still throws an error if you use ES6 syntax. So much for embracing modernity.)
 
(3 intermediate revisions by the same user 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 */
var i18n = {
var i18n = {
     defaultLicense: 'Copyright unlicensed'
    expandAll: 'Expand all',
    collapseAll: 'Collapse all',
     defaultLicense: 'Copyright unlicensed',
};
};


Line 16: Line 17:
  */
  */
function hoverbox(config) {
function hoverbox(config) {
     const defaults = {
     var defaults = {
         mainClass: 'hoverbox',
         mainClass: 'hoverbox',
         activatorClass: 'hoverbox__activator',
         activatorClass: 'hoverbox__activator',
         displayClass: 'hoverbox__display'
         displayClass: 'hoverbox__display',
     };
     };
     config = Object.assign(defaults, config);
     config = Object.assign(defaults, config);
Line 133: Line 134:
             $(this).addClass('table-cell-checkmark');
             $(this).addClass('table-cell-checkmark');
         }
         }
     })
     });
}
}


Line 142: Line 143:
function gem_quality_widget(widgets) {
function gem_quality_widget(widgets) {
     if ( widgets.length > 0 ) {
     if ( widgets.length > 0 ) {
         const do_toggle = function (widget) {
         var do_toggle = function (widget) {
             if ( ! this.classList.contains('is-selected') ) {
             if ( ! this.classList.contains('is-selected') ) {
                 var options = widget.getElementsByClassName('gemqual-widget__option');
                 var options = widget.getElementsByClassName('gemqual-widget__option');
Line 160: Line 161:
         };
         };
         for ( var i = 0; i < widgets.length; i++ ) {
         for ( var i = 0; i < widgets.length; i++ ) {
             var widget = widgets[i]
             var widget = widgets[i];
             var qtypes = widget.dataset.qtypes;
             var qtypes = widget.dataset.qtypes;
             qtypes = qtypes.split(',');
             qtypes = qtypes.split(',');
Line 186: Line 187:
  */
  */
function accordion(config) {
function accordion(config) {
     const defaults = {
     var defaults = {
         mainClass: 'accordion',
         mainClass: 'accordion',
         toggleClass: 'accordion__toggle'
         toggleClass: 'accordion__toggle',
        openStateClass: 'is-open',
        controlsClass: 'accordion__controls',
     };
     };
     config = Object.assign(defaults, config);
     config = Object.assign(defaults, config);
     var accordions = document.getElementsByClassName(config.mainClass);
     var accordions = document.getElementsByClassName(config.mainClass);
     if ( accordions.length === 0 ) {
     if ( accordions.length === 0 ) {
         return;
         return;
     }
     }
     const do_toggle = function () {
     var doToggle = function () {
         this.parentNode.classList.toggle('is-open');
         this.parentNode.classList.toggle(config.openStateClass);
     };
     };
     for ( var i = 0; i < accordions.length; i++ ) {
     for ( var i = 0; i < accordions.length; i++ ) {
Line 208: Line 212:
             }
             }
             heading.appendChild(button);
             heading.appendChild(button);
             button.addEventListener( 'click', do_toggle.bind(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) );
            }
         }
         }
     }
     }
Line 219: Line 260:
             setTimeout( function() {
             setTimeout( function() {
                 var licenseField = document.getElementById('wpLicense');
                 var licenseField = document.getElementById('wpLicense');
                 if ( licenseField && licenseField.value === '' ) {
                 if ( licenseField ) {
                    licenseField.value = i18n.defaultLicense;
                    if ( licenseField.value === '' ) {
                    licenseField.dispatchEvent( new Event('change') );
                        licenseField.value = i18n.defaultLicense;
                        licenseField.dispatchEvent( new Event('change') );
                    }
                    licenseField.querySelector('option[title="{{}}"]').remove();
                 }
                 }
             } );
             } );
Line 246: Line 290:
         mainClass: 'c-item-hoverbox',
         mainClass: 'c-item-hoverbox',
         activatorClass: 'c-item-hoverbox__activator',
         activatorClass: 'c-item-hoverbox__activator',
         displayClass: 'c-item-hoverbox__display'
         displayClass: 'c-item-hoverbox__display',
     });
     });


Line 272: Line 316:
} );
} );


/* DO NOT ADD CODE BELOW THIS LINE */
}() );
}() );

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();

} );

}() );