User:Danski454/stubsearch.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Danski454/stubsearch. |
// <nowiki>
//from a request by Insertcleverphrasehere
//based on [[User:Ais523/stubtagtab2.js]], which is in turn based on [[User:MC10/stubtagtab.js]]
//variables
var SSunfilteredArray = ["stub"];//does not contain parent
var stubTags = {"stub":{display:"{{Stub}}", parents:["stubs"], children:null, descendants:null, template:"Stub"},"stubs":{display:"Stubs", parents:null, children:[], descendants:["stub"], template:null}};//generic stub is not loaded by the normal method
var SSfilteredArray = ["stub"];
var stublists = ['Architecture', 'Commerce', 'Culture', 'Education', 'Geography', 'Government, law, and politics',
'History', 'Leisure', 'Military and weaponry', 'Organizations', 'People',
'Religion, mythology, faiths, and beliefs', 'Science', 'Sports', 'Technology', 'Transport',
'Miscellaneous'];
var stubTemplates = ["{{stub}}"];
var SSactive = false;
var SScurrent = stubTags["stubs"];
var SSoldid = null;
var SSnewid = null;
var SSpagesLoaded = 0;
var SSextraChildren = [{parent:"education stubs", children:["school stubs", "university stubs"]},
{parent:"company stubs", children:["Aeronautical company stubs", "Airline stubs", "Animation studio stubs", "Brand name products stubs", "Chemical company stubs",
"Disney stubs", "Energy company stubs", "Fashion company stubs", "Film company stubs", "Financial services company stubs", "Food company stubs", "Hotel stubs",
"Industrial company stubs", "Information technology company stubs", "Leisure company stubs", "Manufacturing company stubs", "Media company stubs",
"Motor vehicle company stubs", "Music industry company stubs", "Musical instrument company stubs", "Petroleum company stubs", "Publishing company stubs",
"Restaurant stubs", "Retail company stubs", "Service company stub", "Technological company stubs", "Telecommunications company stubs", "Toy company stubs",
"Transport company stubs", "Video game company stubs", "African company stubs", "Asian company stubs", "European company stubs", "Canadian company stubs",
"Mexican company stubs", "United States company stubs", "Australian company stubs", "South American company stubs"]},
{parent:"politics stubs", children:["Asia politics stubs", "Europe politics stubs", "Canada politics stubs", "United States politics stubs", "Mexican politics stubs",
"New Zealand politics stubs", "South America politics stubs", "Political party stubs", "Political people stubs", "Politician stubs"]},
{parent:"politician stubs", children:["African politician stubs", "Asian politician stubs", "European politician stubs", "North American politician stubs",
"Oceanian politician stubs", "South American politician stubs"]},
{parent:"history stubs", children:["American Old West stubs", "Ancient Near East stubs", "Ancient Egypt stubs", "Ancient Greece stubs", "Ancient Rome stubs",
"Byzantine Empire stubs", "Kingdom of France stubs", "Mesoamerica stubs", "Nazi Germany stubs", "Netherlands Antilles stubs", "Ottoman Empire stubs",
"Pre-Columbian era stubs", "Soviet Union stubs", "Yugoslavia stubs", "African diaspora stubs", "East Slavic history stubs", "Jewish history stubs",
"African history stubs", "Asian history stubs", "European history stubs", "Canadian history stubs", "Mexican history stubs", "United States history stubs",
"South American history stubs", "Military history stubs"]},
{parent:"people stubs", children:["Academic biography stubs", "Artist stubs", "Astronaut stubs", "Business biography stubs", "Entertainer stubs", "Explorer stubs",
"Fashion biography stubs", "Graphic designer stubs", "Journalist stubs", "Medical biography stubs", "Model stubs", "Paramilitary biography stubs", "Piracy stubs",
"Religious biography stubs", "Scientist stubs", "Writer stubs", "African people stubs", "Asian people stubs", "European people stubs", "North American people stubs",
"Caribbean people stubs", "Central American people stubs", "Oceanian people stubs", "South American people stubs", "Nobility stubs", "Royalty stubs"]},
{parent:"scientist stubs", children:["Asian scientist stubs", "African scientist stubs", "Australian scientist stubs", "European scientist stubs", "North American scientist stubs",
"South American scientist stubs"]},
{parent:"science stubs", children:["scientist stubs", "Biology stubs", "Botany stubs", "Animal stubs", "Astronomy stubs", "Chemistry stubs", "Atmospheric science stubs",
"Geology stubs", "Oceanography stubs", "Physics stubs", "Health stubs", "Anthropology stubs", "Library and information science stubs", "Sociology stubs", "Natural science stubs"]},
{parent:"chordate stubs", children:["Amphibian stubs", "Bird stubs", "Fish stubs", "Mammal stubs", "Reptile stubs"]}, //Amphibians, Birds, Fish, Mammals, and Reptiles
{parent:"protostome stubs", children:["Mollusc stubs"]},
{parent:"arthropod stubs", children:["insect stubs", "Arachnid stubs"]},
{parent:"technology stubs", children:["Computing stubs", "Software stubs", "Telecommunications stubs", "Automotive part stubs", "Automotive technology stubs", "Electronics stubs",
"Energy stubs", "Engineering stubs", "Industry stubs", "Metalworking stubs", "Robotics stubs", "Sound technology stubs", "Tool stubs", "Woodworking stubs"]},
{parent:"transport stubs", children:["Africa transport stubs", "Asia transport stubs", "Europe transport stubs", "North America transportation stubs", "Oceania transport stubs",
"South America transport stubs", "Space stubs", "Vehicle stubs", "Water transport stubs", "Aviation stubs", "Rail transport stubs", "Road stubs"]},
{parent:"military stubs", children:["African military stubs", "Argentine military stubs", "Asian military stubs", "Australian military stubs", "Canadian military stubs",
"European military stubs", "Mexican military stubs", "United States military stubs", "Military personnel stubs"]},
{parent:"organization stubs", children:["Trade union stubs", "Art organization stubs", "Automotive organization stubs", "Business organization stubs",
"Criminal organization stubs", "Education organization stubs", "Environmental organization stubs", "Film organization stubs", "Fraternity and sorority stubs",
"Freemasonry stubs", "International organization stubs", "Lesbian, gay, bisexual, transgender (LGBT) organization stubs", "Linguistics organization stubs",
"Medical organization stubs", "Music organization stubs", "Non-profit organization stubs", "Paramilitary organization stubs", "Political organisation stubs",
"Professional association stubs", "Religious organization stubs", "Scientific organization stubs", "Youth organization stubs", "African organization stubs",
"Asian organization stubs", "Australian organisation stubs", "Canadian organization stubs", "European organisation stubs", "Mexican organization stubs",
"New Zealand organisation stubs", "South American organization stubs", "United States organization stubs"]}];
//functions
function SSloadDiff(){
window.location.href = mw.config.get('wgScript') + '?diff=' + SSnewid + '&oldid=' + SSoldid;
}
function SSreduceArray(unreducedArray){
var seen = {};
return unreducedArray.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
function SSescape(text, html){
if (html){
return text
.replace('"', """)
.replace("&", "&")
.replace("'", "'")
.replace("<", "<")
.replace(">", ">");
} else {
return text
.replace('"', "\\x22")
.replace("&", "\\x26")
.replace("'", "\\x27")
.replace("<", "\\x3c")
.replace(">", "\\x3e");
}
}
function SSgenerateDescendants(start){
if (stubTags[start].descendants !== null && stubTags[start].descendants.length !== 0){//already generated descendants
return stubTags[start].descendants.concat([start]);
}
if (stubTags[start].children === null || stubTags[start].children.length === 0){//no descendants
return [start];//for the rest, we are the only descendant
}
stubTags[start].children.forEach( function (value, index, array) {
stubTags[start].descendants = stubTags[start].descendants.concat(SSgenerateDescendants(value));//add children's descendants to our own
});
stubTags[start].descendants = SSreduceArray(stubTags[start].descendants);//remove duplicates
return stubTags[start].descendants.concat([start]);
}
function SSaddchild(parent, child){
if (stubTags.hasOwnProperty(parent)){//check parent exists
if (stubTags[parent].template !== null){//check if parent is a template, if so call this on its parents
stubTags[parent].parents.forEach(function (value, index, array) { SSaddchild(value, child); });
return;
}
//check if parent already has child
if (stubTags[parent].children.indexOf(child) !== -1){
return;
}
stubTags[parent].children.push(child);//add child to parents children
} else {//create a parent
stubTags[parent] = {display:parent, parents:[], children:[child], descendants:[], template:null};
stubTags.stubs.descendants.push(parent);//add to stubs' descendants
}
if (stubTags.hasOwnProperty(child)){//check if child exists
stubTags[child].parents.push(parent);//add parent to child
} else {//create child
stubTags[child] = {display:child, parents:[parent], children:[], descendants:[], template:null};
stubTags.stubs.descendants.push(child);//add to stubs' descendants
}
}
function SSconvertToTemplate(parent, template){
if (stubTags[parent].children === null){//already a template
return;
}
stubTags[parent].template = template;//set up template and display
stubTags[parent].display = '{{'+ template +'}}';
stubTemplates.push(('{{'+ template +'}}'));
stubTags[parent].children.forEach( function (value, index, array) {//remove all children's parent reference
index = stubTags[value].parents.indexOf(parent);//don't need index
if (index > -1) {
stubTags[value].parents.splice(index, 1);
}
SSaddchild(parent, value);//try to readd this as a child of parent
});
stubTags[parent].children = null;//clear the array
}
function SSdoExtraChildren(){
$.each(SSextraChildren, function (){ //do children in array
var parent = this.parent;
this.children.forEach(function (value, index, array){
SSaddchild(parent, value.toLowerCase());
});
});
addStubType("Unlisted stubs", "cat", "stubs");//special case for unlisted stubs
}
function stubFilter(){
filterString = document.getElementById("stub-search-search").value;
//Special case: no filterString then only show direct children
if (filterString.length === 0){
SSfilteredArray = SScurrent.children;
SSrerenderList();
return;
}
var filteringArray = SSunfilteredArray; //copy unfiltered array
filterString = filterString.toLowerCase(); //force lowercase
var filterArray = filterString.split(" "); //split string
for (var filterIndex = 0; filterIndex < filterArray.length; filterIndex++) {
SSfilteredArray = [];//clear the filtered output
filterString = filterArray[filterIndex];
for (var i = 0; i < filteringArray.length; i++) {
var testString = filteringArray[i];
if (testString.indexOf(filterString) > -1){
SSfilteredArray.push(testString);
}
}
filteringArray = SSfilteredArray;
}
SSrerenderList();
}
function loadStubs(){
for (var i = 0; i < stublists.length; i++) {
var stubType = stublists[i];
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=parse&prop=text&text=' + encodeURIComponent('__NOTOC____NOEDITSECTION__\{\{Wikipedia:WikiProject Stub sorting/Stub types/' + stubType + '}}') + '&format=json',
dataType: "json",
success: stubSearchLoadSome,
error: function() {
SSpagesLoaded++;//increment loaded pages on failure so the menu auto loads
console.log("Stub search failed to load a stub list.");
}
});
}
//special case for unlisted stubs
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=parse&prop=text&text=' + encodeURIComponent('__NOTOC____NOEDITSECTION__\{\{User:Danski454/unlisted stubs}}') + '&format=json',
dataType: "json",
success: stubSearchLoadSome,
error: function() {
SSpagesLoaded++;//increment loaded pages on failure so the menu auto loads
console.log("Stub search failed to load a stub list.");
}
});
SSdoExtraChildren();
}
function stubSearchLoadSome(data) {
var parseData = $(data.parse.text["*"]);
var parent = "stubs";
if (parseData.find("h1, h2").length){
switch (parseData.find("h1, h2").first().text().toLowerCase()){
case "sports":
parent = "sports stubs";
break;
case "culture":
parent = "culture stubs";
break;
case "contents":
parent = "architecture stubs";
break;
}
} else if (parseData.find("h3").length === 0) {//special case for unlisted stubs
parent = "unlisted stubs";
}
parseData.children("ul").children('li').each( function () {
var val = $(this);//'this' must be converted to jQuery
while (val.find("small").length !== 0) {//remove small tags (copied from toggleSmall.js)
var tag = val.find("small").first();
tag.before(tag.html());
tag.remove();
}
$('dl').remove();//remove description lists
generateStubData(val, parent);
});
if (parent !== "stubs" && parent !== "unlisted stubs"){
stubTags[parent].children.shift();//remove from its own children
stubTags[parent].parents = [];//remove from its own parents
SSaddchild("stubs", parent);//make a child of stubs
}
SSpagesLoaded++;
if (SSpagesLoaded == stublists.length + 1){//one list is not listed in the array
stubFilter();
}
}
function addStubType(obj, type, parent){
var name = obj.toLowerCase();
SSaddchild(parent, name);//this creates the object
if (type === "template"){
SSconvertToTemplate(name, obj);
} else {
stubTags[name].display = obj;//set display name
}
SSunfilteredArray.push(name);
SSfilteredArray.push(name);
}
function generateStubData(data, parent){
var cat;
cat = data.children("b").first().text();//categories are in bold
if (cat !== ""){
addStubType(cat, "cat", parent);
parent = cat.toLowerCase();
}
data.children("ul").children('li').each( function () {
generateStubData($(this), parent);
});
data.children("a").each( function () {//template links are not wrapped
var tag = $(this);
if (tag[0].previousElementSibling !== null && tag[0].previousElementSibling.innerText.endsWith("as a child of {{")){//get text before element and make sure it does not say x is a child of y
return true;
}
if (tag[0].previousElementSibling !== null && tag[0].previousElementSibling.innerText.endsWith("child of {{")){//get text before element and handle next element is child of x
var next = tag.next();//get next list item
if (next.is("ul")){//if next is a list get the first item of it
next = next.children("li").first();
}
SSaddchild(tag.text().toLowerCase(), next.children('b').first().text().toLowerCase());//make next link a child of us
return true;
}
if (tag.attr("href").search(/(wiki\/|=)Template:/) === -1){//must link to a template
return true;
}
addStubType(tag.text(), "template", parent);
});
}
function SSrerenderList(){
$('#stub-search-scroll').empty();
SSfilteredArray = SSreduceArray(SSfilteredArray); //remove duplicates
SSfilteredArray.forEach(function (value, index, array) {
var tag = stubTags[value];
if (index > 0){
$('#stub-search-scroll').append("•");
}
$('#stub-search-scroll').append('<input type="button" value="'+ tag.display +'" onclick="selectStub(\''+ SSescape(value, false) +'\');" style="background:none!important;color:inherit;border:none;cursor:pointer;" class="stub-search-type" />');
});
}
function SSrenderTemplate(){
$('#stub-search-scroll').empty();
$('#stub-search-scroll').append('<span id="stub-preview">Preview loading</span>');
$.ajax({
url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + '/api.php?action=parse&prop=text&text=' + encodeURIComponent('__NOTOC____NOEDITSECTION__\{\{' + SScurrent.template + '}}') + '&format=json',
dataType: "json",
success: function (data){
$('#stub-preview').before('<input type="button" value="Add {{'+ SSescape(SScurrent.template, true) +'}} to this article" onclick="addStub();" id="stub-search-confirm" /> <input type="button" value="Replace old stub templates with {{'+ SSescape(SScurrent.template, true) +'}}" onclick="replaceStub(false);" id="stub-search-confirm-replace" /> <input type="checkbox" value="load diff" id="stub-search-load-diff" checked /> Load changes<br />');
$('#stub-preview').html($(data.parse.text["*"]));
}
});
}
function stubSearchUp(){
var stub = $('#stub-search-parent-select option:selected').val();
selectStub(stub);
}
function loadStubSearch(){
if (SSactive){
return;
}
SSactive = true;
switch ( mw.config.get('skin') ){
case 'cologneblue':
$('#mw-content-text').before('<div id="stub-search-box" style="background-color:LightBlue;height:200px;border:1px solid black;padding:15px;">Search: <input type="text" id="stub-search-search"><input id="stub-search-button" type="button" value="Search" onclick="stubFilter();" /> Current selection: <span id="stub-search-cat">Stubs</span> <input id="stub-search-up" type="button" value="Go up to" onclick="stubSearchUp();" /><select id="stub-search-parent-select"></select> <input id="stub-search-diff-button" type="button" value="Load changes" onclick="SSloadDiff();" /><br /><div style="max-height:175px;overflow:auto;" id="stub-search-scroll">Loading stub templates: Please wait</div></div>');
break;
case 'timeless':
$('#bodyContent').before('<div id="stub-search-box" style="background-color:LightBlue;height:200px;border:1px solid black;padding:15px;">Search: <input type="text" id="stub-search-search"><input id="stub-search-button" type="button" value="Search" onclick="stubFilter();" /> Current selection: <span id="stub-search-cat">Stubs</span> <input id="stub-search-up" type="button" value="Go up to" onclick="stubSearchUp();" /><select id="stub-search-parent-select"></select> <input id="stub-search-diff-button" type="button" value="Load changes" onclick="SSloadDiff();" /><br /><div style="max-height:150px;overflow:auto;" id="stub-search-scroll">Loading stub templates: Please wait</div></div>');
break;
default:
$('#bodyContent').before('<div id="stub-search-box" style="background-color:LightBlue;height:200px;border:1px solid black;padding:15px;">Search: <input type="text" id="stub-search-search"><input id="stub-search-button" type="button" value="Search" onclick="stubFilter();" /> Current selection: <span id="stub-search-cat">Stubs</span> <input id="stub-search-up" type="button" value="Go up to" onclick="stubSearchUp();" /><select id="stub-search-parent-select"></select> <input id="stub-search-diff-button" type="button" value="Load changes" onclick="SSloadDiff();" /><br /><div style="max-height:175px;overflow:auto;" id="stub-search-scroll">Loading stub templates: Please wait</div></div>');
}
$('#stub-search-up, #stub-search-parent-select, #stub-search-diff-button').hide();//up button, drop down and load diff button default to hidden
loadStubs();
}
function selectStub(name){
SSgenerateDescendants(name);//generate the descendants, if they have not already been.
SScurrent = stubTags[name];
$('#stub-search-cat').text(SScurrent.display);
document.getElementById("stub-search-search").value = "";//clear search
$('#stub-search-parent-select').empty();//clear old parents selector
if (SScurrent.parents !== null){
$('#stub-search-up, #stub-search-parent-select').show();//show parent selector and button
if (SScurrent.parents[0] === "unlisted stubs") {//special case
$('#stub-search-parent-select').append('<option value="'+ SSescape("stubs", true) +'">'+ SSescape(stubTags["stubs"].display, true) +'</option>')
}
SScurrent.parents.forEach(function (value, index, array){
$('#stub-search-parent-select').append('<option value="'+ SSescape(value, true) +'">'+ SSescape(stubTags[value].display, true) +'</option>')
});
} else {
$('#stub-search-up, #stub-search-parent-select').hide();//hide parent selector and button
}
if (SScurrent.template === null){
SSunfilteredArray = SScurrent.descendants;
stubFilter();
} else {
SSrenderTemplate();
}
}
function addStub(){
replaceStub(true);//functions merged
}
function replaceStub(keepOld){//adds a stub template, optionally keeping old ones, this is copied from [[WP:US/G]]
$.getJSON(
mw.util.wikiScript('api'),
{
format: 'json',
action: 'query',
prop: 'revisions',
rvprop: 'content',
rvlimit: 1,
titles: mw.config.get( 'wgPageName' )
}
)
.done(function ( data ) {
var page, wikitext;
try {
for ( page in data.query.pages ) {
wikitext = data.query.pages[page].revisions[0]['*'];
replaceStubWikitext( wikitext, keepOld );
}
} catch ( e ) {
console.log(1);
alert( 'Edit failed' );
}
})
.fail( function() {
console.log(2);
alert( 'Edit failed' );
});
}
function replaceStubWikitext(data, keepOld){
added_text = '\n\n\n{{'+ SScurrent.template +'}}';
stubTemplates.forEach(function (value, index, array){
var re = new RegExp(value, "gi");
if (keepOld && data.match(re) !== null){
added_text = added_text + '\n' + value;//readd stub template to bottom
}
data = data.replace(re, "");//replace stubs with nothing using unescaped regex
});
data = data.replace(/\s+$/g, "");//remove trailing whitepace, do not use m flag
data = data + added_text;
console.log(data);
var summary = 'Replaced stub templates with {{'+ SScurrent.template +'}} using [[User:Danski454/stubsearch|a tool]]';
if (keepOld){
summary = 'Added {{'+ SScurrent.template +'}} using [[User:Danski454/stubsearch|a tool]]';
}
//save data
$.ajax({
url: mw.util.wikiScript( 'api' ),
type: 'POST',
dataType: 'json',
data: {
format: 'json',
action: 'edit',
title: mw.config.get( 'wgPageName' ),
text: data,
summary: summary,
token: mw.user.tokens.get( 'csrfToken' )
}
})
.done (function( data ) {
if ( data && data.edit && data.edit.result && data.edit.result == 'Success') {
if (SSoldid === null){
if (data.edit.oldrevid !== undefined){
SSoldid = data.edit.oldrevid;
} else {
alert("Unable to determine oldid");
}
}
if ($('#stub-search-load-diff').is(':checked') && data.edit.newrevid !== undefined){
if (SSoldid !== null && data.edit.oldrevid !== undefined){
window.location.href = mw.config.get('wgScript') + '?diff=' + data.edit.newrevid + '&oldid=' + SSoldid;//load diff
} else {
alert("Unable to load diff");
}
} else {
if (keepOld){
alert( 'Successfully added {{'+ SScurrent.template +'}} to the article' );
} else {
alert( 'Successfully replaced stubs with {{'+ SScurrent.template +'}}' );
}
if (data.edit.newrevid !== undefined){
SSnewid = data.edit.newrevid;
} else {
alert("Unable to determine newid");
}
if (SSoldid !== null && SSnewid !== null && $('#stub-search-diff-button').is(':hidden')){
$('#stub-search-diff-button').show();//add a load diff button if we have not loaded the diff
}
selectStub('stubs');//reset the UI, user probably wans to add another template
}
} else {
console.log(3);
alert( 'Edit failed' );
}
})
.fail ( function() {
console.log(4);
alert( 'Edit failed' );
});
}
$(document).ready(function(){
if ( mw.config.get( 'wgNamespaceNumber' ) === 0 || mw.config.get( 'wgPageName' ) === "Wikipedia:Sandbox" ) {//usable on articles and the sandbox (for testing and practice)
var portletLink = mw.util.addPortletLink('p-cactions', '#', 'Stub search', 'ca-stub-search', 'Tag this article as a stub', '');
$(portletLink).click(loadStubSearch);
}
});
// </nowiki>