User:Pyrospirit/metadata/projectbanners.js
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 : '–';
if (rating) tdRating.setAttribute('class', 'assess-' + rating.toLowerCase());
tdImportance = document.createElement('td');
tdImportance.innerHTML = importance ? importance : '–';
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?
}