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. |
//from a request by Insertcleverphrasehere
//based on [[User:Ais523/stubtagtab2.js]], which is in turn based on [[User:MC10/stubtagtab.js]]
//variables
var unfilteredArray = ["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 filteredArray = ["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 current = stubTags["stubs"];
var pagesLoaded = 0;
//functions
function SSreduceArray(unreducedArray){
var seen = {};
return unreducedArray.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
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].dispaly = '{{'+ 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 stubFilter(){
filterString = document.getElementById("stub-search-search").value;
//Special case: no filterString then only show direct children
if (filterString.length === 0){
filteredArray = current.children;
SSrerenderList();
return;
}
var filteringArray = unfilteredArray; //copy unfiltered array
filterString = filterString.toLowerCase(); //force lowercase
var filterArray = filterString.split(" "); //split string
for (var filterIndex = 0; filterIndex < filterArray.length; filterIndex++) {
filteredArray = [];//clear the filtered output
filterString = filterArray[filterIndex];
for (var i = 0; i < filteringArray.length; i++) {
var testString = filteringArray[i];
if (testString.indexOf(filterString) > -1){
filteredArray.push(testString);
}
}
filteringArray = filteredArray;
}
SSrerenderList();
}
function loadStubs(){
for (var i = 0; i < stublists.length; i++) {
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() {
pagesLoaded++;//increment loaded pages on failure so the menu auto loads
console.log("Stub search failed to load a stub list.");
}
});
}
}
function stubSearchLoadSome(data) {
var parseData = $(data.parse.text["*"]);
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();
}
generateStubData(val, "stubs");//children of the generic stub
});
pagesLoaded++;
if (pagesLoaded == stublists.length){
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
}
unfilteredArray.push(name);
filteredArray.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].previousSibling !== null && tag[0].previousSibling.nodeValue.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].previousSibling !== null && tag[0].previousSibling.nodeValue.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();
filteredArray = SSreduceArray(filteredArray); //remove duplicates
filteredArray.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(\''+ value +'\');" style="background:none!important;color:inherit;border:none;cursor:pointer;" class="stub-search-type" />');
});
}
function SSrenderTemplate(){
$('#stub-search-scroll').empty();
$('#stub-search-scroll').append('<input type="button" value="Add {{'+ current.template +'}} to this article" onclick="addStub();" id="stub-search-confirm" /><br /><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__\{\{' + current.template + '}}') + '&format=json',
dataType: "json",
success: function (data){
$('#stub-preview').html($(data.parse.text["*"]));
}
});
}
function stubSearchUp(){
selectStub(current.parents[0]);
}
function loadStubSearch(){
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();" /><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();" /><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();" /><br /><div style="max-height:175px;overflow:auto;" id="stub-search-scroll">Loading stub templates: Please wait</div></div>');
}
$('#stub-search-up').hide();//up button defaults to hidden
loadStubs();
}
function selectStub(name){
SSgenerateDescendants(name);//generate the descendants, if they have not already been.
current = stubTags[name];
$('#stub-search-cat').text(current.display);
document.getElementById("stub-search-search").value = "";//clear search
if (current.parents !== null){
$('#stub-search-up').val("Go up to " + stubTags[current.parents[0]].display).show();//for now, show first parent
} else {
$('#stub-search-up').hide();
}
if (current.template === null){
unfilteredArray = current.descendants;
stubFilter();
} else {
SSrenderTemplate();
}
}
function addStub(){
$.ajax({
url: mw.util.wikiScript( 'api' ),
type: 'POST',
dataType: 'json',
data: {
format: 'json',
action: 'edit',
title: mw.config.get( 'wgPageName' ),
appendtext: '\n{{'+ current.template +'}}', // will replace entire page content
summary: 'Added {{'+ current.template +'}} using [[User:Danski454/stubsearch|a tool]]',
token: mw.user.tokens.get( 'editToken' )
}
})
.done (function( data ) {
if ( data && data.edit && data.edit.result && data.edit.result == 'Success' ) {
alert( 'Successfully added {{'+ current.template +'}} to the article' );
} else {
alert( 'Edit failed' );
}
})
.fail ( function() {
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);
}
});