Jump to content

User:Pyrospirit/metadata/projectbanners.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/**
 * Optional component for metadata script ([[User:Pyrospirit/metadata.js]]).
 * This script creates a table at the top of the page, hidden by default, that
 * contains each WikiProject's assessment and importance rating of the article.
 * The table can be toggled on and off with the [show]/[hide] link to the right
 * of the main assessment in the siteSub.
 */
if(typeof assessment !== 'undefined') {
assessment.banners = {
    done: false, // flag to make sure it only runs once
    runProjectBanners: function runProjectBanners () {
        if (this.done) return;

        this.assessments = this.getProjectBanners(assessment.text);
        if (this.assessments.length == 0) return; // no projects found
        var listDisplay = this.createAssessmentList(this.assessments),
            button = this.makeToggle('assessment.banners.toggleBox'),
            contentSub = document.getElementById('contentSub'),
            siteSub = document.getElementById('siteSub');
        // Add the table, initially hidden
        document.getElementById('bodyContent').insertBefore(listDisplay, contentSub);
        // Add the toggle button
        siteSub.insertBefore(button, siteSub.firstChild);

        // Move coordinates element over by 30px if present to prevent overlap
        var coords = document.getElementById('coordinates');
        if (coords) {
            coords.style.right = '60px';
        }

        this.done = true;
    },
    /**
     * Creates the HTML code for displaying an assessment list.
     */
    createAssessmentList: function createAssessmentList (assessments) {
        var tbody = document.createElement('tbody');
        var tr, tdName, tdRating, tdImportance, link; // the table elements in each row
        var rating, importance;
        var assess;
    
        var nameHeader = document.createElement('th');
        nameHeader.setAttribute('width', '200');
        nameHeader.innerHTML = 'WikiProject';
        var ratingHeader = document.createElement('th');
        ratingHeader.setAttribute('width', '80');
        ratingHeader.innerHTML = 'Assessment';
        var importanceHeader = document.createElement('th');
        importanceHeader.setAttribute('width', '75');
        importanceHeader.innerHTML = 'Importance';
        var header = document.createElement('tr');
        header.appendChild(nameHeader);
        header.appendChild(ratingHeader);
        header.appendChild(importanceHeader);
        tbody.appendChild(header);
    
        for (var i = 0; i < assessments.length; i++) {
            assess = assessments[i]
            rating = this.setCaps(assess.rating, false, 2);
            importance = this.setCaps(assess.importance, false, 2);
            tr = document.createElement('tr');
            tdName = document.createElement('td');
            link = document.createElement('a');
            link.setAttribute('href', mw.config.get('wgArticlePath').replace('$1', '')
                + (assess.name.search(/\:/) == -1 ? 'Template:' : '') + assess.name);
            link.innerHTML = assess.name;
            tdName.appendChild(link);
            tdRating = document.createElement('td');
            tdRating.innerHTML = rating ? rating : '&ndash;';
            if (rating) tdRating.setAttribute('class', 'assess-' + rating.toLowerCase());
            tdImportance = document.createElement('td');
            tdImportance.innerHTML = importance ? importance : '&ndash;';
            if (importance) tdImportance.setAttribute('class', 'assess-importance-' + importance.toLowerCase());
            tr.appendChild(tdName);
            tr.appendChild(tdRating);
            tr.appendChild(tdImportance);
            tbody.appendChild(tr);
        }
        var table = document.createElement('table');
        table.setAttribute('id', 'assess-box-content');
        table.setAttribute('class', 'wikitable');
        table.setAttribute('cellpadding', '2');
        table.style.display = 'none';
        table.style.textAlign = 'center';
        table.appendChild(tbody);
        return table;
    },
    /**
     * Makes a toggle button for the assessment box.
     * @param {String} method - the method name
     * @param {String} text - the starting text of the button
     * @return {String} toggle - the toggle button
     */
    makeToggle: function makeToggle (method) {
        var button = document.createElement('a');
        var href = 'javascript:void(' + method + '());';
        button.setAttribute('id', 'assess-box-toggle');
        button.setAttribute('href', href);
        button.setAttribute('title', 'Show assessment box');
        button.innerHTML = 'show'; // starting text for the button
        var toggle = document.createElement('span');
        toggle.setAttribute('class', 'assess-box');
        toggle.setAttribute('style', 'float: right;');
        toggle.appendChild(button);
        toggle.innerHTML = '[' + toggle.innerHTML + ']'; // add surrounding brackets
        return toggle;
    },
    /**
     * Toggles show/hide for the assessment box content.
     */
    toggleBox: function toggleBox () {
        var toggle = document.getElementById('assess-box-toggle');
        var content = document.getElementById('assess-box-content');
        if (content.style.display != 'none') {
            content.style.display = 'none';
            toggle.setAttribute('title', 'Show assessment box');
            toggle.innerHTML = 'show';
        } else {
            content.style.display = '';
            toggle.setAttribute('title', 'Hide assessment box');
            toggle.innerHTML = 'hide';
        }
    },
    /**
     * Standardizes the capitalization used for the assessment table.
     */
    setCaps: function setCaps (input, default_, maxcaps) {
        return (input
            ? (input.toString().length > maxcaps
                ? input.toString().charAt(0).toUpperCase()
                    + input.toString().substring(1).toLowerCase()
                : input.toString().toUpperCase())
            : default_);
    },
    /**
     * Creates a list of WikiProject assessments from text containing the
     * WikiProject banners.
     * @param {String} text - the text to be read
     * @return {Array} banners - an array of objects, each containing one
     *         project's assessment
     */
    getProjectBanners: function getProjectBanners (text) {
        var templates = this.findProjects(text);
        var banners = [];
        var parseOutput;
        for (var i = 0; i < templates.length; i++) {
            banners.push({});
            banners[i].name = this.templateName(templates[i][0]);
            parseOutput = this.parseTemplate(templates[i]);
            banners[i].rating = parseOutput.rating;
            banners[i].importance = parseOutput.importance;
        }
        return banners;
    },
    /**
     * Finds the WikiProject templates in the provided text and returns
     * them, split into arrays.
     * Note that this function uses some concepts and content, particularly the
     * regular expression, from [[User:Outriggr/metadatatest.js]] (which has since
     * been deleted).
     * @param {String} text - the text from which templates will be found
     * @return {Array} templates - the templates' text, split by parameter
     */
    findProjects: function findProjects (text) {
        var templates = [];
        // re matches most WikiProject banner templates
        var re = /\{\{\s*(wikiproject[ _]\w[^\{\}]*|\w+[^\|\{\}]*?\s*\|(?:[^\{\}]*\|)?\s*(?:class|importance|priority)\s*=\s*\w?[^\{\}]*)\}\}/i;
        var match; // the current match object
        var tl; // the current template found
        while ((match = text.match(re))) {
            tl = match[1];
            tl = tl.split('|');
            templates.push(tl);
            text = text.replace(match[0], ''); // prevent templates from being found more than once
        }
        return templates;
    },
    /**
     * Takes a template array and finds its class and importance parameters.
     * @param {Array} template - a single template, split by parameter
     * @return {Object} rating, importance - contains the template's class= and
     *         and importance/priority= parameters
     */
    parseTemplate: function parseTemplate (template) {
        var classParam = '';
        var importance = '';
        var match;
        for (var i = 0; i < template.length; i++) {
            match = template[i].match(/^\s*class\s*=\s*(\w+)/i);
            if (match)
                classParam = match[1].toLowerCase();
            match = template[i].match(/^\s*(?:priority|importance)\s*=\s*(\w+)/i);
            if (match)
                importance = match[1].toLowerCase();
            if (classParam && importance)
                break;
        }
        return {rating: classParam, importance: importance};
    },
    /**
     * Used to determine the name of a template. This prevents two uses of the
     * same template from being interpreted differently due to minor formatting
     * differences.
     * @param {String} rawName - the template contents before the first parameter
     * @return {String} name - the name of the template
     */
    templateName: function templateName (rawName) {
        var name = rawName.toString();
        var match = name.match(/^\s*(?:[Tt]emplate\:)?(\w[\w \-\(\)\&\/\:\.\']+\w)\s*$/);
        if (!match) return ""; // invalid template name
        name = match[1].replace('_', ' ');
        name = name[0].toUpperCase() + name.substring(1); // capitalize first letter
        return name;
    }
};

// Hook the project banners function onto the request

if(assessment.addHook) {
  assessment.addHook("onCompletedRequest", function () {
    assessment.banners.runProjectBanners.call(assessment.banners);
  });
}
} else {
 mw.log.error('Problem with load order of scripts. `assessment` not found.'); // perhaps use mw.notify here if this is a problem?
}