User:BMacZero/shipcat.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at User:BMacZero/shipcat. This user script seems to have an accompanying .css page at User:BMacZero/shipcat.css. |
// wizard for creating categories for ships
//<nowiki>
var showWizard = function($, mw)
{
if (window.shipWizard)
{
window.shipWizard.show();
return;
}
var shipWizard = window.shipWizard =
{
apiUrl: mw.util.wikiScript('api'),
init: function()
{
importStylesheet('User:BMacZero/shipcat.css');
$body = $(document.body);
$container = shipWizard.$container = $('<div id="scat_container"></div>')
.appendTo($body);
$fader = shipWizard.$fader = $('<div id="scat_fade"></div>')
.appendTo($body);
$('<h2>Ship Category Wizard</h2>')
.appendTo($container);
$('<p>(<span style="color:red">*</span>) denotes a required field</p>')
.appendTo($container);
$('<br/>').appendTo($container);
$inputTable = $('<table></table>')
.appendTo($container);
//TODO: fishing license # as prefix
$prefixInput = shipWizard.$prefixInput = this.createInputElement($inputTable, 'Prefix (only if painted on ship)');
$nameInput = shipWizard.$nameInput = this.createInputElement($inputTable, 'Name', "text", true);
$typeInput = shipWizard.$typeInput = this.createSpecialInputElement($inputTable, "Type",
$('<select><option>ship</option><option>tugboat</option><option>submarine</option></select>'));
$yearCompleted = shipWizard.$yearCompleted = this.createInputElement($inputTable, 'Year Completed');
$yearLaunched = shipWizard.$yearLaunched = this.createInputElement($inputTable, 'Year Launched');
$locationBuilt = shipWizard.$locationBuilt = this.createInputElement($inputTable, 'Location Built');
$yardNumber = shipWizard.$yardNumber = this.createInputElement($inputTable, 'Yard Number');
$('<tr><td><br/></td></tr>').appendTo($inputTable);
$imo = shipWizard.$imo = this.createInputElement($inputTable, 'IMO');
$eni = shipWizard.$eni = this.createInputElement($inputTable, 'ENI');
$('<tr><td><br/></td></tr>').appendTo($inputTable);
$addThisPage = shipWizard.$addThisPage = this.createInputElement($inputTable, "Add this page to created category", "checkbox");
// this is for showing output to the user
$outputElement = shipWizard.$outputElement = $('<p></p>').appendTo($container);
$optionsP = $('<p></p>').appendTo($container);
$('<button>Create Category</button>')
.appendTo($optionsP)
.click(function(){ shipWizard.createCategory(); });
$('<span style="display:inline-block;width:20px"></span>').appendTo($optionsP);
//TODO: escape closes
$('<a href="javaScript:void(0);">close window</a>')
.appendTo($optionsP)
.click(function(){ shipWizard.hide(); });
},
createInputElement: function($tableParent, labelText, type, required)
{
if (!type) type = "text";
return this.createSpecialInputElement($tableParent, labelText, $('<input type="' + type + '">'), required);
},
createSpecialInputElement: function($tableParent, labelText, $inputElem, required)
{
if (required) labelText += '<span style="color:red">*</span>';
$tr = $('<tr></tr>')
.appendTo($tableParent);
$('<td>' + labelText + '</td>')
.appendTo($tr);
$inputCell = $('<td></td>')
.appendTo($tr);
return $($inputElem).appendTo($inputCell);
},
createCategory: function()
{
shipWizard.$outputElement.html('<span><b>Working...</b></span>');
// check that required fields are set
if (!this.$nameInput.val())
{
shipWizard.$outputElement.html('<span style="color:red"><b>Missing required field "Name".</b></span>');
return;
}
// figure displayed year
//TODO: validate data
var year = "";
if (this.$yearCompleted.val()) year = this.$yearCompleted.val();
else if (this.$yearLaunched.val()) year = this.$yearLaunched.val();
var typeText = this.$typeInput.children("option").filter(":selected").text();
var titleSuffix = " (" + typeText + ")";
if (year) titleSuffix = " (" + typeText + ", " + year + ")";
// figure title of page
var pageTitle = "Category:";
if (this.$prefixInput.val()) pageTitle += this.$prefixInput.val() + " ";
pageTitle += this.$nameInput.val() + titleSuffix;
//TODO: if category already exists, disambiguate with $locationBuilt then $yardNumber
// check that category doesn't exist
var params = this.getQueryParams(pageTitle);
this.doAPICall(params, function(result)
{
var allMissing = true;
// there should be only one, but we don't know its ID
console.log(result);
for (var id in result.query.pages)
{
allMissing = allMissing && result.query.pages[id].missing !== undefined;
//TODO: this doesn't work
shipWizard.queryTimestamp = result.query.pages[id].starttimestamp;
}
if (!allMissing)
{
shipWizard.$outputElement.html('<span style="color:red"><b>Category "' + pageTitle + '" already exists. Add more information or use that category.</b></span>');
}
else
{
shipWizard.createCategoryHelper(pageTitle, titleSuffix, year);
}
});
},
createCategoryHelper: function(pageTitle, titleSuffix, year)
{
// produce page contents
var categoryText = "";
// displaytitle
categoryText += "{{DISPLAYTITLE:Category:";
if (this.$prefixInput.val()) categoryText += this.$prefixInput.val() + " ";
categoryText += "''" + this.$nameInput.val() + "''" + titleSuffix;
categoryText += "}}\n";
// defaultsort
var normalizedName = this.$nameInput.val();
if (normalizedName.normalize) normalizedName = normalizedName.normalize('NFKD').replace(/[\u0300-\u036F]/g, '');
if (this.$prefixInput.val() || normalizedName !== this.$nameInput.val())
{
categoryText += "{{DEFAULTSORT:";
categoryText += normalizedName + titleSuffix;
categoryText += "}}\n";
}
// templates
if (this.$imo.val()) categoryText += "{{IMOcat|" + this.$imo.val() + "}}\n";
// categories
categoryText += "[[Category:Ships by name (flat list)]]\n";
if (this.$yearCompleted.val()) categoryText += "[[Category:Ships built in " + this.$yearCompleted.val() + "]]\n";
if (!year) categoryText += "[[Category:Ship categories with missing year]]\n";
//TODO: create if non-existant
if (this.$imo.val()) categoryText += "[[Category:IMO " + this.$imo.val() + "]]\n";
//TODO: create if non-existant
if (this.$eni.val()) categoryText += "[[Category:ENI " + this.$eni.val() + "]]\n";
// get an edit token if necessary
if (!this.editToken)
{
var params = {
action: 'query',
meta: 'tokens',
type: 'csrf'
};
this.doAPICall(params, function(result)
{
shipWizard.edittoken = result.query.tokens.csrftoken;
shipWizard.createCategoryFinally(pageTitle, categoryText);
});
}
else
{
this.createCategoryFinally(pageTitle, categoryText);
}
},
createCategoryFinally: function(pageTitle, pageText)
{
var params = {
action: 'edit',
title: pageTitle,
text: pageText,
summary: "Creating new ship category with the [[User:BMacZero/Ship Category Wizard|Ship Category Wizard]].",
token: this.edittoken,
createonly: true,
starttimestamp: this.queryTimestamp
};
this.doAPICall(params, function(result)
{
if (result.error)
{
shipWizard.$outputElement.html('<span style="color:red"><b>Error: ' + result.error.info + '</b></span>');
}
else
{
// add the category to this page
if (shipWizard.$addThisPage.prop('checked'))
{
shipWizard.addCategoryToCurrentPage(pageTitle);
}
else
{
shipWizard.postAllDone();
}
}
});
},
postAllDone: function()
{
shipWizard.$outputElement.html('<span style="color:green"><b>All done, refresh this page.</b></span>');
},
getQueryParams: function(pageTitle)
{
return {
action: 'query',
prop: 'info|revisions',
rvprop: 'content|timestamp',
titles: pageTitle
};
},
addCategoryToCurrentPage: function(categoryName)
{
var params = this.getQueryParams(mw.config.get('wgPageName'));
this.doAPICall(params, function(result)
{
// stolen from MediaWiki:Gadget-Cat-a-lot.js
var otext, starttimestamp, timestamp;
if (!result)
{
//Happens on unstable wifi connections..
//TODO: display error
return;
}
var pages = result.query.pages;
// there should be only one, but we don't know its ID
for (var id in pages)
{
otext = pages[id].revisions[0]['*'];
starttimestamp = pages[id].starttimestamp;
timestamp = pages[id].revisions[0].timestamp;
}
var text = otext;
text += "\n[[" + categoryName + "]]\n";
var data = {
action: 'edit',
summary: "Creating new ship category with the [[User:BMacZero/Ship Category Wizard|Ship Category Wizard]].",
title: pages[id].title,
text: text,
starttimestamp: starttimestamp,
basetimestamp: timestamp,
token: shipWizard.edittoken,
nocreate: true,
};
shipWizard.doAPICall(data, function(result)
{
if (result.error)
{
shipWizard.$outputElement.html('<span style="color:red"><b>Error: ' + result.error.info + '</b></span>');
}
else
{
shipWizard.postAllDone();
}
});
});
},
show: function()
{
shipWizard.$container.show();
shipWizard.$fader.show();
},
hide: function()
{
shipWizard.$container.hide();
shipWizard.$fader.hide();
},
// stolen from MediaWiki:Gadget-Cat-a-lot.js
doAPICall: function(params, callback)
{
params.format = 'json';
var i = 0;
var apiUrl = this.apiUrl;
var handleError = function(jqXHR, textStatus, errorThrown)
{
if (window.console && $.isFunction(window.console.error))
{
window.console.error('Error: ', jqXHR, textStatus, errorThrown);
}
if (i < 4)
{
window.setTimeout(doCall, 300);
i++;
}
else if (params.title)
{
//TODO: display error
return;
}
};
var doCall = function()
{
$.ajax({
url: apiUrl,
cache: false,
dataType: 'json',
data: params,
type: 'POST',
success: callback,
error: handleError
});
};
doCall();
},
};
// initialize when document is ready
$(function()
{
shipWizard.init();
});
};
/*jshint scripturl:true*/
$.when(mw.loader.using('mediawiki.util'), $.ready).then(function() {
var shipcatNode = mw.util.addPortletLink('p-tb', '', 'Create ship category', 't-shipcatwizard');
$(shipcatNode).on('click', function(e) {showWizard(jQuery, mediaWiki); e.preventDefault();});
});
/*jshint scripturl:false*/
//</nowiki>