/** _____________________________________________________________________________ * | | * | === WARNING: GLOBAL GADGET FILE === | * | Changes to this page affect many users. | * | Please discuss changes on the talk page or on ] before editing. | * |_____________________________________________________________________________| * * Imported from revision 185704269 as of January 20, 2008 18:40 from * ], itself a modified version of * ]. * Metadata assessment script * Finds the WP 1.0/WikiProject assessment of every article you go to, then * displays that information in the article header. See (new script homepage * pending). * @author Outriggr - created the script and used to maintain it * @author Pyrospirit - used to maintain and update the script * @author Nihiltres - Overhauled the script, current maintainer */ window.assessment = (function () { var assessmentObj = { props: {}, methods: {} }, //internal shortcuts ap = assessmentObj.props, am = assessmentObj.methods; /** * The main function of the script. If the checkArticle() function can find * the assessment, it parses and displays that assessment for the page. * Otherwise, it tries to retrieve an assessment via AJAX. */ assessmentObj.init = function () { if (!$("#siteSub").length || //incompatible skin mw.config.get("wgNamespaceNumber") !== 0 || //non-mainspace page (mw.config.get("wgAction") !== "view" && mw.config.get("wgAction") !== "purge") || //non-read action mw.util.getParamValue("printable") || //printable page mw.config.get("wgArticleId") === 0 || //nonexistent page mw.config.get("wgIsMainPage") === true //Main Page ) { return; //Don't run the script under any of these conditions. } ap.foundAssessment = am.checkArticle(); //checks for types visible from article page if (!ap.foundAssessment.exists) { // no type visible on article, proceed to check the talk page $.ajax({ url: mw.config.get("wgScript") + "?title=Talk:" + mw.util.wikiUrlencode(mw.config.get("wgPageName")) + "&action=raw§ion=0", async: true, dataType: "text", success: function (responseText) { ap.text = responseText; ap.foundAssessment = am.getAssessment(ap.text); ap.updata = am.renderAssessment(ap.foundAssessment); am.update(); } }); } else { ap.updata = am.renderAssessment(ap.foundAssessment); am.update(); } }; /** * Checks for various objects on the article page that indicate a certain * assessment, such as a disambiguation page notice. If this function can * find the assessment, AJAX is not needed for this page. * @returns {Object} checkResult - the assessment found */ am.checkArticle = function () { var checkResult = { extra: , exists: false }, checksList = [ , , , /* , */ //no talk page ]; $.each(checksList, function (i, e) { if (e) { checkResult.rating = e; checkResult.exists = true; return false; } }); return checkResult; }; /** * Searches the provided wikicode for the rating part of an assessment and * returns it as a string. * Note that higher assessments take priority, and less-used assessments * such as "list", "current", or "future" are used only if nothing else can * be found. * @param {String} text - some wikitext to be searched for assessment info */ am.getRating = function (text) { var rating = "none", standardChecks = [ , , , , , //used by WP Math , , , , // used by WP Military history & WP Highways , // used by WP Military history , // used by WP Military history , , // used by WP Plants , , ]; //evaluate the standard checks $.each(standardChecks, function (i, e) { if (text.match(e)) { rating = e; return false; } }); //and then the nonstandard ones. These override earlier ratings if applicable. if (rating === "a" && text.match(/\|\s*class\s*=\s*ga\b|\|\s*currentstatus\s*=\s*(ffa\/)?ga\b/i)) { rating = "a/ga"; // A-class articles that are also GA's } else if (text.match(/\|\s*class\s*=\s*ga\b|\|\s*currentstatus\s*=\s*(ffa\/)?ga\b|\{\{\s*ga\s*\|/i) && !text.match(/\|\s*currentstatus\s*=\s*dga\b/i)) { rating = "ga"; } return rating; }; /** * Searches the provided wikicode for data on the article's current and past * featured or good status and returns an object that contains this data * along with some miscellaneous other bits of information. * @param {String} text - some wikitext to be searched for assessment info * @return {Object} gottenAssessment - the assessment data for the page */ am.getAssessment = function (text) { var gottenAssessment = { rating: am.getRating(text), pageLink: , extra: , activeReview: null, exists: true }, actionNumber = 0, pageLinkFlag = false, peerReview, linkPattern, linkMatch, currentList, formerList; currentList = [ // Current nominations (FAC, FLC, or GAN) { reg: /\{\{\s*featuredarticlecandidates\s*(?:\s*(*))?*?\}\}/i, extraName: "fac", addArticleNameTo: "Misplaced Pages:Featured_article_candidates\/" }, { reg: /\{\{\s*featuredlistcandidates\s*(?:\s*(*))?*?\}\}/i, extraName: "flc", addArticleNameTo: "Misplaced Pages:Featured_list_candidates\/" }, { reg: /\{\{\s*ga ?nominee\s**\}\}/i, extraName: "gan", addMatchReg: /\|\s*page\s*=\s*(\d+).*\|\s*status\s*=\s*\w+\b/i, addMatchTo: "Talk:" + mw.config.get("wgPageName") + "\/GA" }, // Current reviews of a status (FAR, FLRC, or GAR) { reg: /\{\{\s*featuredarticlereview\s*(?:\s*(*))?*?\}\}/i, extraName: "far", addArticleNameTo: "Misplaced Pages:Featured_article_review\/" }, { reg: /\{\{\s*featuredlistremovalcandidates\s*(?:\s*(*))?*?\}\}/i, extraName: "flrc", addArticleNameTo: "Misplaced Pages:Featured_list_removal_candidates\/" }, { reg: /\{\{\s*gar\/link\s**\}\}/i, extraName: "gar", addMatchReg: /\|\s*GARpage\s*=\s*(\d+).*\|/i, addMatchTo: mw.config.get("wgPageName") } ]; $.each(currentList, function (i, e) { var reg = text.match(e.reg), articleName, tempMatch; if (reg) { gottenAssessment.extra.push(e.extraName); if (e.hasOwnProperty("addArticleNameTo") && reg) { articleName = am.decodeEntities($.trim(reg)); if (articleName) { gottenAssessment.pageLink = e.addArticleNameTo + articleName; } } if (e.hasOwnProperty("addMatchReg")) { tempMatch = reg.match(e.addMatchReg); if (tempMatch) { gottenAssessment.pageLink = (e.addMatchTo || "") + (tempMatch || ""); } if (e.extraName === "gar") { //Can't get around this special case easily gottenAssessment.pageLink = am.getGARLink(e.addMatchTo, tempMatch); } } return false; } }); formerList = [ // Former statuses (FFA, FFL, or DGA) { name: "ffa", reg: /\|\s*currentstatus\s*=\s*ffa\b/i, getActionNumber: true, getActionNumberReg: /\|\s*action(\d+)\s*=\s*far\b/gi }, { name: "ffa", reg: /\|\s*action(\d+)\s*=\s*far\b/gi, extraCondition: function (ec_reg) { //Checks if the last FAR entry in ArticleHistory resulted in removal. var match, ratingSearch; if (!ec_reg) { return false; } match = text.match(new RegExp( "\\|\\s*action" + ec_reg.match(/\d+/) + "result\\s*=\\s*removed\\b", "i" )); ratingSearch = (gottenAssessment.rating.search(/f/i) === -1); return (match && ratingSearch); }, getActionNumber: true }, { name: "ffa", reg: /\{\{\s*formerfa2?\b/i }, { name: "ffl", reg: /\|\s*currentstatus\s*=\s*ffl\b/i }, { name: "ffl", reg: /\{\{\s*ffl\s*/i }, { name: "dga", reg: /\|\s*currentstatus\s*=\s*dga\b/i, getActionNumber: true, getActionNumberReg: /\|\s*action(\d+)\s*=\s*gar\b/gi }, { name: "dga", reg: /\{\{\s*d(elisted)?ga\s*/i }, // Former nominations (former FAC, FLC, or GAN) { name: "ffac", reg: /\|\s*action(\d+)\s*=\s*fac\b/gi, extraCondition: function () { return (gottenAssessment.rating.search(/f/i) === -1); }, getActionNumber: true }, { name: "ffac", reg: /\|\s*currentstatus\s*=\s*ffac\b/i }, { name: "ffac", reg: /\{\{\s*fac?(failed|(\-|\()?contested\)?)\s*/i }, { name: "fflc", reg: /\|\s*action(\d+)\s*=\s*flc\b/gi, extraCondition: function () { return (gottenAssessment.rating.search(/f/i) === -1); }, getActionNumber: true }, { name: "fflc", reg: /\|\s*currentstatus\s*=\s*fflc\b/i }, { name: "fgan", reg: /\|\s*action(\d+)\s*=\s*gan\b/gi, extraCondition: function () { return (gottenAssessment.rating.search(/f|(a\/)?ga/i) === -1); }, getActionNumber: true }, { name: "fgan", reg: /\|\s*currentstatus\s*=\s*fgan\b/i }, { name: "fgan", reg: /\{\{\s*f(ailed ?)?ga\s*/i } ]; $.each(formerList, function (i, e) { var reg = text.match(e.reg), extraCondition = !e.hasOwnProperty("extraCondition") || typeof e.extraCondition !== "function" || e.extraCondition(reg), //either true (ignored) or result of function tempMatch; if (reg && extraCondition) { gottenAssessment.extra.push(e.name); if (e.getActionNumber) { tempMatch = (e.getActionNumberReg ? text.match(e.getActionNumberReg) : reg); actionNumber = tempMatch.match(/\d+/); pageLinkFlag = true; } return false; } }); // Looks for currently active peer reviews ap.showOldPeerReviews = false; //see TODO below peerReview = text.match(/\{\{\s*peer?review\s*\|\s*archive\s*=\s*(\d+)\b/i); if (peerReview) { gottenAssessment.review = "Misplaced Pages:Peer_review/" + mw.config.get("wgPageName") + "/archive" + peerReview; gottenAssessment.activeReview = true; } else if (ap.showOldPeerReviews) { $.noop(); // TODO: Add code for old peer reviews } else { gottenAssessment.review = null; } // Scans for the link associated with an action in ArticleHistory if (pageLinkFlag) { linkPattern = new RegExp("\\|\\s*action" + actionNumber + "link\\s*=\\s*(+)\\s*\\|"); linkMatch = text.match(linkPattern); gottenAssessment.pageLink = linkMatch ? am.decodeEntities(linkMatch) : null; } return gottenAssessment; }; /** * Parses an assessment object into the HTML and CSS code needed to update * the article header. If it doesn't recognize a part of the information * given, it will simply ignore it and mark as unassessed. * @param {Object} assess - assessment information for this article * @return {String} newClass - the CSS class corresponding to its assessment * @return {String} slogan - HTML giving (with a link) the main assessment * @return {String} info - HTML giving (with a link) additional information */ am.renderAssessment = function (assess) { var assessLink = mw.util.getUrl("Misplaced Pages:Content_assessment"), peerReviewText = am.addPeerReview(assess.review, assess.activeReview), pageLink = assess.pageLink || , info = am.getExtraInfo((assess.extra || ), pageLink), newClass, slogan, ratingList; if (peerReviewText) { info.push(peerReviewText); } ratingList = [ { name: "a", className: "assess-a-text", text: "An A-class<\/a> article" }, { name: "a/ga", className: "assess-a-text", text: "An A-class<\/a> article", info: "Also a good article<\/a>." }, { name: "ga", className: "assess-ga-text", text: "A good article<\/a>", url: mw.util.getUrl("Misplaced Pages:Good_articles") }, { name: "b", className: "assess-b-text", text: "A B-class<\/a> article" }, { name: "bplus", className: "assess-bplus-text", text: "A B-plus-class<\/a> article", url: mw.util.getUrl("Misplaced Pages:WikiProject_Mathematics/Wikipedia_1.0/Grading_scheme") }, { name: "c", className: "assess-c-text", text: "A C-class<\/a> article" }, { name: "start", className: "assess-start-text", text: "A start-class<\/a> article" }, { name: "stub", className: "assess-stub-text", text: "A stub-class<\/a> article" }, { name: "al", className: "assess-al-text", text: "An A-class<\/a> list", url: mw.util.getUrl("Misplaced Pages:WikiProject_Military_history/Assessment") + "#SCALE" //Could use a more general link if one is available }, { name: "bl", className: "assess-bl-text", text: "A B-class<\/a> list", url: mw.util.getUrl("Misplaced Pages:WikiProject_Military_history/Assessment") + "#SCALE" }, { name: "cl", className: "assess-cl-text", text: "A C-class<\/a> list", url: mw.util.getUrl("Misplaced Pages:WikiProject_Military_history/Assessment") + "#SCALE" }, { name: "sl", className: "assess-sl-text", text: "A stub-class<\/a> list" }, { name: "list", className: "assess-list-text", text: "A list-class<\/a> article", url: mw.util.getUrl("Misplaced Pages:Stand-alone lists") }, { name: "dab", className: "assess-dab-text", text: "A disambiguation page<\/a>", url: mw.util.getUrl("Misplaced Pages:Disambiguation") }, { name: "setindex", className: "assess-setindex-text", text: "A set index article<\/a>", url: mw.util.getUrl("Misplaced Pages:Set_index_articles") }, { name: "redir", className: "assess-redir-text", text: "A redirect page<\/a>", url: mw.util.getUrl("Help:Redirect") }, { name: "fl", className: "assess-fl-text", text: "A featured list<\/a>", url: mw.util.getUrl("Misplaced Pages:Featured_lists") }, { name: "fa", className: "assess-fa-text", text: "A featured article<\/a>", url: mw.util.getUrl("Misplaced Pages:Featured_articles") }, { name: "cur", className: "assess-cur-text", text: "A current-class<\/a> article", url: mw.util.getUrl("Portal:Current_events") }, { name: "future", className: "assess-future-text", text: "A future-class<\/a> article", url: mw.util.getUrl("Category:Future-Class_articles") } ]; $.each(ratingList, function (i, e) { if (assess.rating === e.name) { newClass = e.className; slogan = $("").html(e.text).children().attr({href: (e.url || assessLink)}).parent().html(); if (e.info) { info.push(e.info); } return false; } }); if (!newClass) { newClass = "assess-unassessed-text"; slogan = "An unassessed<\/a> article"; } return {newClass: newClass, slogan: slogan, info: info}; }; /** * Creates an info string based on the assessment info and a page link. */ am.getExtraInfo = function (extra, pageLink) { var info = , page = mw.config.get("wgPageName"), typeList; typeList = [ // Current nominations and reviews { name: "fac", html: "Currently a featured article candidate<\/a>.", url: pageLink || ("Misplaced Pages:Featured_article_candidates/" + page) }, { name: "flc", html: "Currently a featured list candidate<\/a>.", url: pageLink || ("Misplaced Pages:Featured_list_candidates/" + page) }, { name: "gan", html: "Currently a good article nominee<\/a>.", url: pageLink || "Misplaced Pages:Good_article_nominations" }, { name: "far", html: "Currently undergoing review<\/a> of its featured status.", url: pageLink || ("Misplaced Pages:Featured_article_review/" + page) }, { name: "flrc", html: "Currently a featured list removal candidate<\/a>.", url: pageLink || ("Misplaced Pages:Featured_list_removal_candidates/" + page) }, { name: "gar", html: "Currently undergoing a good article reassessment<\/a>.", url: pageLink || "Misplaced Pages:Good_article_reassessment", wrapper: "<\/span>" }, // Past statuses and nominations { name: "ffa", html: "A former<\/a> featured article.", url: pageLink || ("Misplaced Pages:Featured_article_review/" + page) }, { name: "ffl", html: "A former<\/a> featured list.", url: pageLink || ("Misplaced Pages:Featured_list_removal_candidates/" + page) }, { name: "dga", html: "A delisted<\/a> good article.", url: pageLink || "Misplaced Pages:Good_article_reassessment" }, { name: "ffac", html: "A former featured article candidate<\/a>.", url: pageLink || ("Misplaced Pages:Featured_article_candidates/" + page) }, { name: "fflc", html: "A former featured list candidate<\/a>.", url: pageLink || ("Misplaced Pages:Featured_list_candidates/" + page) }, { name: "fgan", html: "A former good article nominee<\/a>.", url: pageLink || "Misplaced Pages:Good_article_nominations" } ]; $.each(typeList, function (i, e) { if (extra.indexOf(e.name) !== -1) { info.push($("").html(e.html).children().attr({href: mw.util.getUrl(e.url)}) .parent().wrapInner(e.wrapper || null).html()); } }); return info; }; /** * Get the correct link for Good Article reassessments. These things require an * additional AJAX request to determine whether it's a community or individual * reassessment. The trick is to assume it's a community reassessment, then * switch the link once the request returns if it's actually not. * @param {String} articleName - the name of the article to use * @param {String} reviewNumber - the number of the GAR to look for */ am.getGARLink = function (articleName, reviewNumber) { var communityTitle = "Misplaced Pages:Good_article_reassessment\/" + articleName + "\/" + reviewNumber, individualTitle = "Talk:" + articleName + "\/GA" + reviewNumber, titlesList = , api = new mw.Api(); api.get({ action: "query", titles: titlesList.join("|"), prop: "info", format: "json" }).done(function (data) { var i, j, noCommunityAssessment, query = data.query, communityTitleNorm = titlesList, individualTitleNorm = titlesList, len = query.normalized.length, garLink = $("#assess-gar-link a:first"); for (j = 0; j < len; j++) { switch (query.normalized.from) { case titlesList: communityTitleNorm = query.normalized.to; break; case titlesList: individualTitleNorm = query.normalized.to; break; } } noCommunityAssessment = false; for (i = -1; i >= -2; i--) { if (query.pages && typeof query.pages.missing === "string") { if (query.pages.title === individualTitleNorm) { // No individual assessment, no need to change anything. return; } if (query.pages.title === communityTitleNorm) { // There's no community assessment, so flag it. noCommunityAssessment = true; } } } if (noCommunityAssessment && garLink.length) { // There's an individual assessment but no community assessment. Switch the link. garLink.attr("href", mw.util.getUrl(titlesList)); } }); return communityTitle; }; /** * Creates the peer review text from an info string, if a peer review was detected earlier. */ am.addPeerReview = function (peerReview, activeReview) { var reviewText = null; if (peerReview) { reviewText = $("" + (activeReview ? "Currently being" : "Previously") + " peer reviewed<\/a>.<\/span><\/div>"); reviewText.find("a").attr({href: mw.util.getUrl(peerReview)}); reviewText = reviewText.html(); //Note div wrapper above. } return reviewText; }; /** * Updates article header with new assessment information by giving it a new * class (for style information such as color) and altering the tagline below * it to state the assessment found. */ am.update = function () { var info = ap.updata.info, infoSpan = $("<\/span>"), siteSub = $("<\/span> <\/div>"); siteSub.children().html(ap.updata.slogan); if (info && info.length > 0) { infoSpan.html("."); $.each(info, function (i, e) { infoSpan.append(" ").append(e); }); siteSub.append(infoSpan); } $("h1:first").addClass(ap.updata.newClass || null); $("#siteSub").html(siteSub.html()); }; /** * Decodes all HTML entities in the string provided. */ am.decodeEntities = function (str) { var t = document.createElement("textarea"); t.innerHTML = str; return t.value; }; return assessmentObj; }()); /** * Initializes the script on page load */ $(assessment.init);