User:Ahecht/sandbox/Scripts/potd-helper.js

//jshint maxerr:512 // mw.loader.using( [ 'mediawiki.util', 'oojs-ui' ], function {	var potdScriptLongTitle = "Picture of the Day Helper (sandbox)",		potdScriptShortTitle = "POTDHelper (sandbox)",		potdScriptLocation = "User:Ahecht/sandbox/Scripts/potd-helper.js",		potdFPCategory = 'Featured pictures';	const urlParams = new URLSearchParams(window.location.search);	const debug = urlParams.get('debug') || false;	function POTDHelper {		var config = {			fpCategory: potdFPCategory,			fpcPrefix: 'Wikipedia:Featured picture candidates/',			potdPrefix: 'Template:POTD/',			editSummaryPattern: ' scheduled for POTD on %1',			editSummarySuffix: ' (' + potdScriptShortTitle + ')',			panoWidth: 500,			defaultWidth: 350,			landscapeWidth: 300,			squareWidth: 275,			portraitWidth: 250,			tallWidth: 225,			maxWidth: 650,			suggestHeight: 350,			maxHeight: 450, aspectRatio: 0, submitMessageHeader: ' Submitting Picture of the Day: ', submitMessageFooter: '', submitMessages: [], query: { action: 'query', formatversion: '2' },			revQuery: { prop: 'revisions', rvprop: 'content', rvslots: 'main', rvlimit: '1', rvsection: '0', },			imageQuery: { prop: 'imageinfo|revisions|categories|fileusage', iiprop: 'user|dimensions', iilimit: 'max', cllimit: 'max', funamespace: '0', fulimit: 'max' },			nomQuery: { rvprop: 'user', rvdir: 'newer' },			titleQuery: { prop: 'revisions|pageimages|images', piprop: 'name', imlimit: 'max' },			edit: { action: 'edit', watchlist: 'preferences', recreate: 1 }		};		function wikiLink(message) { message = message.replace(/\[\[(.*?)\]\]/g, function(s,v) {				v = v.split("|");				var url = mw.config.get("wgServer") + mw.config.get("wgArticlePath").replace("$1", encodeURI(v[0]));				return '' + (v[1] || v[0]) + "";			} ); return message; }		function showImageMessage(label, type='error') { imageMessage.setType(type); imageMessage.setLabel(label); imageMessage.toggle(true); imageMessage.scrollElementIntoView; }

function showImageError(error) { error = "The script " + error + " Check that the image name is correct."; showImageMessage(new OO.ui.HtmlSnippet(wikiLink(error))); }		function showTitleError(error) { error = "The script " + error + " Check that the article name " + titleInput.value + " is correct."; titleMessage.setLabel(new OO.ui.HtmlSnippet(wikiLink(error))); titleMessage.toggle(true); titleMessage.scrollElementIntoView; }		function showDateError(error) { dateMessage.setLabel(new OO.ui.HtmlSnippet(wikiLink(error))); dateMessage.toggle(true); dateMessage.scrollElementIntoView; }		function showSubmitMessage(message, type) { type = type ? type : 'notice'; config.submitMessages.push(wikiLink(message)); var label = new OO.ui.HtmlSnippet( config.submitMessageHeader + config.submitMessages.join("") + config.submitMessageFooter ); submitMessage.setLabel(label); var types = ['notice', 'success', 'warning', 'error']; if (types.indexOf(type) > types.indexOf(submitMessage.type)) { submitMessage.setType(type); }			submitMessage.toggle(true); submitMessage.scrollElementIntoView; }		function fetchImageData(doneFunction = function {return;}, errorFunction = function {return;}){ var imageName = 'File:' + imageInput.value; if (imageName != "File:" && typeof config.imageData === 'undefined') { var fn = "fetchImageData("+doneFunction+","+errorFunction;				console.log('Fetching image data...');				new mw.Api.get( Object.assign( {titles: imageName}, config.query, config.revQuery, config.imageQuery ) ).fail(function(code, error) { console.warn(fn+") encountered an API error retrieving info for "+imageName+":");					console.warn(error);					showImageError("got an API error '" + code + "' when querying image " + imageName + ": " + error.error.info);					errorFunction;				}).done( function(data) {					if (data && data.query && data.query.pages && data.query.pages[0]) {						if (data.query.pages[0].missing) {							if (data.query.pages[0].known) {								errorMsg = "was unable find a local page on Wikipedia for this image (although one exists on Commons), which means it is likely not a Wikipedia Featured Picture.";							} else {								errorMsg = "was unable to find the image.";							}							showImageError(errorMsg);							console.warn(fn+") did not find a page for "+imageName+"."); console.log(data); errorFunction; } else { console.log('Caching image data...'); config.imageData = data.query.pages[0]; doneFunction; }					} else { console.warn(fn+") encountered an error parsing the API respose for "+imageName+":");						console.log(data);						showImageError("was unable to parse the API response when trying get info on the image.");						errorFunction;					}				} ); } else { console.log('Using cached image data...'); doneFunction; }		}		function fillImage(titleData, imageInput) { if (titleData.images && titleData.images.length) { var options = []; titleData.images.forEach( function(item) {return options.push({data: item.title.replace(/^File:/i, '')});} ); if (options.length) { imageInput.setOptions(options); } else { console.log("No images found on " + titleData.title); console.log(imageData); }			} else { console.warn("Images not found in API response:"); console.log(imageData); }			if (titleData.pageimage) { if (!imageInput.value.length) { imageInput.setValue(titleData.pageimage); checkSizeInput; } else { console.log("Page image " + titleData.pageimage + " found, but imageInput is not empty."); }			} else { console.warn("Page Image not found for article " + titleData.title); console.log(titleData); }		}		function fillUsage(imageData, titleInput) { if (imageData.fileusage && imageData.fileusage.length) { var options = []; imageData.fileusage.forEach( function(item) {return options.push({data: item.title});} ); if (options.length) { titleInput.setOptions(options); } else { console.log("No usage of " + imageData.title + " found."); console.log(imageData); }			} else { console.warn("Fileusage not found in API response:"); console.log(imageData); }		}		function getImageInfo { function getNominator(nom) { if (nom && nom.query && nom.query.pages && nom.query.pages[0] && nom.query.pages[0].revisions) { if (nom.query.pages[0].revisions[0] && nom.query.pages[0].revisions[0].user && nom.query.pages[0].revisions[0].user.length) { nominatorInput.setValue("User:" + nom.query.pages[0].revisions[0].user); console.log("Nominated by " + nominatorInput.value); if (nominatorInput.value == uploaderInput.value) { nominatorInput.setValue; }					} else { showImageError("was unable to parse API data on nomination page " + nomination + "."); }				} else { showImageError("was unable to find the nomination page " + nomination + "."); }			}			function getNomination(imageData) { if (imageData.revisions && imageData.revisions.length && imageData.categories && imageData.categories.length) { var cats=[]; imageData.categories.forEach( function(cat) {return cats.push(cat.title);} ); if (cats.includes('Category:' + config.fpCategory)) { if (imageData.revisions[0] && imageData.revisions[0].slots && imageData.revisions[0].slots.main && imageData.revisions[0].slots.main.content) { var content = imageData.revisions[0].slots.main.content, nominations = []; try { nominations = XRegExp.matchRecursive(content, "\\{\\{featured\\s*picture\\s*\\|", "\\}}", 'i'); } catch(error) { console.warn(error + " when parsing local file description."); console.log(content); showImageError("was unable to parse the template on " + imageInput.value + ": " + error + "."); }								if (nominations.length && nominations[0].length) { var nomination = config.fpcPrefix + nominations[0]; console.log("Nominated at " + nomination); new mw.Api.get(											Object.assign( {titles: nomination}, config.query, config.revQuery, config.nomQuery )										).fail(function(code, error) {											console.warn("API error retrieving nomination:");											console.warn(error);											showImageError("got an API error '" + code + "' when retrieving the nomination page " + nomination + ": " + error.error.info);										}).done( getNominator ); } else { showImageError("was unable to find the featured picture template in the local description. Are you sure this is a featured image on the English Wikipedia?"); }						} else { showImageError("was unable to parse API data on the image."); }					} else { showImageError("was unable to find on that image. Are you sure this is a featured image on the English Wikipedia?"); }				} else { showImageError("was unable to find a local file description. Are you sure this is a featured image on the English Wikipedia?"); }			}			function getUploader(imageData) { if (imageData.imageinfo && imageData.imageinfo.length) { info = imageData.imageinfo; info = info[info.length - 1]; if (info.user) { uploaderInput.setValue("User:" + info.user); console.log("Uploaded by " + uploaderInput.value); getNomination(imageData); } else { console.warn("Error parsing API respose for image uploader:"); console.log(data); showImageError("was unable to parse the API response when trying to determine who uploaded the image."); }				} else { console.warn("Error parsing API respose for image uploader:"); console.log(data); showImageError("was unable to parse the API response when trying to determine who uploaded the image."); }			}			imageMessage.toggle(false); fetchImageData(function {				getUploader(config.imageData);				fillUsage(config.imageData, titleInput);				checkSizeInput;			} ); }		function getCaption { function extractCaption(titleData) { var extract = ""; if (titleData.revisions && titleData.revisions[0] && titleData.revisions[0].slots &&					titleData.revisions[0].slots.main && titleData.revisions[0].slots.main.content) { var content = titleData.revisions[0].slots.main.content, xValues = []; content = content.replace(/(\[\s\n]*)*/ig, ''); try { xValues = XRegExp.matchRecursive(content, "\\[\s\n]*", 'gi', {valueNames: ['b', 'l', 'm', 'r']}); } catch(error) { console.warn(error + " when parsing linked article."); console.log(content); showTitleError("encountered an error when parsing the article's lead section: " + error + "."); }					if (xValues.length) { var startSub = 0;

for(var i = 0; i < xValues.length; i++){ var x = xValues[i]; if (x.name && x.name=='b' && (typeof x.start === 'number')) { startSub=x.start; break; }						}

extract = content.substr(startSub).split('\n\n')[0]; if (extract && extract.length) { extract = extract.replace(/(.*?)<\/ref>/g, ""); extract = extract.replace(//g, ""); re = new RegExp(/('')?(.*?)\1 /); titleMatch=extract.match(re); if (titleMatch) { if (titleMatch[2]==titleInput.value) { captionInput.setValue(extract.replace(re, "$1$2$1 ")); } else { captionInput.setValue(extract.replace(re, "$1$2$1 ")); }							} else { captionInput.setValue(""+titleInput.value+": "+extract); }						} else { showTitleError("was unable to find non-template content in lead section."); extract = ""; }					} else { showTitleError("was unable to parse the article's lead section."); }				} else if (titleData.missing) { console.warn("Could not find revisions for Title:"); console.log(titleData); showTitleError("was unable to find an article with that title."); } else { console.warn("Error parsing API respose when fetching lead section:"); console.log(titleData); showTitleError("encountered an error parsing the API response when fetching the article's lead section."); }			}			titleMessage.toggle(false); if (typeof config.titleData === 'undefined') { console.log('Fetching title data...'); new mw.Api.get(					Object.assign( {titles: titleInput.value}, config.query, config.revQuery, config.titleQuery )				).fail(function(code, error) {					console.warn("API error retrieving linked article:");					console.warn(error);					showTitleError("encountered an API error '" + code + "' when retrieving the article: " + error.error.info);				} ).done( function(data) {					if (data && data.query && data.query.pages && data.query.pages[0]) {						console.log('Caching title data...');						config.titleData = data.query.pages[0];						extractCaption(config.titleData);						fillImage(config.titleData, imageInput);					} else {						console.warn("Error parsing API respose when fetching lead section:");						console.log(data);						showTitleError("encountered an error parsing the API response when fetching the article's lead section.");					}				} ); } else { console.log('Using cached title data...'); extractCaption(config.titleData); fillImage(config.titleData, imageInput); }		}		function finishSubmit(done) { done = done ? done : false; if (done) {showSubmitMessage("Done!", 'success');} while (closeButton.isPending) {closeButton.popPending;} closeButton.toggleFramed(true).setDisabled(false); while (submitButton.isPending) {submitButton.popPending;} submitButton.toggleFramed(true); checkButtons; }		function writeUserTalk(user) { var templateText = "\n{{subst:" + "NotifyPOTD|1=" + "|2=File:" + imageInput.value + "|3=" + dateInput.value + (commentsInput.value.length ? ("|4=" + commentsInput.value) : ""), userTalk = ""; if (user == 'uploader') { userTalk = uploaderInput.value; templateText += "|action=uploaded}}"; } else if ((user == 'nominator') && (nominatorInput.value != uploaderInput.value)) { userTalk = nominatorInput.value; templateText += "|action=nominated}}"; }			if (userTalk.search(/^User:./i) == 0) { //Value starts with "User:" console.log(templateText); userTalk = userTalk.replace(/^User:/i, 'User talk:'); var params = Object.assign( {					title: userTalk,					appendtext: templateText,					summary: config.editSummary,					redirect: 1,					nocreate: 1				}, config.edit ); if (debug) { console.log(params); showSubmitMessage("Simulated message to " + userTalk + "."); if (user == 'uploader') { writeUserTalk('nominator'); } else { finishSubmit(true); }				} else { new mw.Api.postWithEditToken(params).fail( function(code, error) {						console.error("API error when creating article talk page message: ");						console.error(error);						showSubmitMessage("ERROR '" + code + "' when creating message on " + userTalk + ": " + error.error.info, 'warning');						if (user == 'uploader') {							writeUserTalk('nominator');						} else {							finishSubmit(true);						}					} ).done( function {						showSubmitMessage("Added message to " + userTalk + ".");						if (user == 'uploader') {							writeUserTalk('nominator');						} else {							finishSubmit(true);						}					} ); }			} else if (user == 'uploader') { writeUserTalk('nominator'); } else { finishSubmit(true); }		}		function writeArticleTalk{ var templateText = "\nFile:" + imageInput.value + "",				titleTalk = 'Talk:' + titleInput.value; console.log(templateText); var params = Object.assign( {				title: titleTalk,				appendtext: templateText,				summary: config.editSummary,				redirect: 1			}, config.edit ); if (debug) { console.log(params); showSubmitMessage("Simulated message to " + titleTalk + "."); writeUserTalk('uploader'); } else { new mw.Api.postWithEditToken(params).fail( function(code, error) {					console.error("API error when creating article talk page message: ");					console.error(error);					showSubmitMessage("ERROR '" + code + "' when creating message on " + titleTalk + ": " + error.error.info, 'warning');					writeUserTalk('uploader');				} ).done( function {					showSubmitMessage("Added message to " + titleTalk + ".");					writeUserTalk('uploader');				} ); }		}		function checkSize { config.wide = false; config.tall = false; if (config.imageData && config.imageData.imageinfo && config.imageData.imageinfo[0] && config.imageData.imageinfo[0].width > 0) { var imageWidth = config.imageData.imageinfo[0].width; var imageHeight = config.imageData.imageinfo[0].height || 0; config.aspectRatio = imageWidth / imageHeight; console.log("Original image dimensions: " + imageWidth + "×" + imageHeight + " (" + config.aspectRatio + ":1)."); if (!sizeInput.value.length) { width =	config.aspectRatio > 2	? config.panoWidth : config.aspectRatio > 1.1 ? config.landscapeWidth : config.aspectRatio >= 0.9 ? config.squareWidth : config.aspectRatio >= 0.5 ? config.portraitWidth : config.aspectRatio > 0 ? config.tallWidth : config.defaultWidth; } else { width = sizeInput.value; }				if (width > config.maxWidth) { console.log("Wide image detected."); config.wide = true; }				var height = width * imageHeight / imageWidth; console.log("Template image dimensions: " + width + "×" + height); if (!config.wide && height > config.maxHeight) { console.log("Tall image detected."); if (!sizeInput.value.length) { width = Math.floor(config.suggestHeight*config.aspectRatio / 10) * 10; height = width * imageHeight / imageWidth; console.log("Changing default value to: " + width + "×" + height); } else { config.tall = true; }				}				if (!sizeInput.value.length) { sizeInput.setValue(width); }			} else { console.warn("Error reading or parsing image data when trying to determine dimensions."); console.log(config.imageData); }		}		function writePOTDTemplate { var templateName = config.potdPrefix + dateInput.value; if (!texttitleInput.value.length) { texttitleInput.setValue(titleInput.value); }			if (!sizeInput.value.length) { sizeInput.setValue(config.defaultWidth); }			checkSize; if (!captionInput.value.length) { captionInput.setValue(""); }			var templateText = " " + "\n\n== See also ==" + "\n* Template:POTD/ "; console.log(templateText); var params = Object.assign( {				createonly: 1,				title: templateName,				text: templateText,				summary: 'Creating a POTD template for ' + config.editSummarySuffix			}, config.edit ); if (debug) { console.log(params); showSubmitMessage("Simulated " + templateName + "."); writeArticleTalk; } else { new mw.Api.postWithEditToken(params).fail( function(code, error) {					console.error("API error when creating template: ");					console.error(error);					showSubmitMessage("ERROR '" + code + "' when creating template " + templateName + ": " + error.error.info, 'error');					finishSubmit(true);				} ).done( function {					showSubmitMessage("Created " + templateName + ".");					writeArticleTalk;				} ); }		}		function writeLocalDesc { var params = Object.assign( {				title: 'File:' + imageInput.value,				appendtext: '\n',				summary: config.editSummary,				redirect: 1,				nocreate: 1			}, config.edit ); if (debug) { console.log(params); showSubmitMessage("Simulated message to ."); writePOTDTemplate; } else { new mw.Api.postWithEditToken(params).fail( function(code, error) {						console.error("API error when adding template to local file description: ");						console.error(error);						showSubmitMessage("ERROR '" + code + "' when adding template to : " + error.error.info, 'warning');						finishSubmit(true);					} ).done( function {						showSubmitMessage("Added message to .");						writePOTDTemplate;					} ); }		}		function checkButtons { if (!titleInput.value.length) { autofillTitleButton.setDisabled(true); } else { autofillTitleButton.setDisabled(false); }			if (!imageInput.value.length) { autofillImageButton.setDisabled(true); } else { autofillImageButton.setDisabled(false); }			if (titleInput.value.length && imageInput.value.length && dateInput.value.length && creditInput.value.length && !submitButton.isPending) { submitButton.setDisabled(false); } else { submitButton.setDisabled(true); }		}		function preCheck { var imageData = config.imageData; if (imageData.categories && imageData.categories.length){ var cats=[]; imageData.categories.forEach( function(cat) {return cats.push(cat.title);} ); if (cats.includes('Category:' + config.fpCategory)) { var templateName = config.potdPrefix + dateInput.value; new mw.Api.get(						Object.assign( {titles: templateName}, config.query )					).fail(function(code, error) {						console.warn("API error checking if POTD template exists:");						console.warn(error);						showDateError("got an API error '" + code + "' when checking if " + templateName + " exists: " + error.error.info);						finishSubmit;					}).done( function(data) {						if (data && data.query && data.query.pages && data.query.pages[0]) {							if (data.query.pages[0].missing) {								console.log(templateName + " does not yet exist.");								if (typeof config.titleData === 'undefined') {									console.log('Fetching title data...');									new mw.Api.get( Object.assign( {titles: titleInput.value}, config.query, config.revQuery, config.titleQuery ) ).fail(function(code, error) { console.warn("API error checking if article exists:"); console.warn(error); showDateError("got an API error '" + code + "' when checking if " + titleInput.value + " exists: " + error.error.info); finishSubmit; }).done( function(data) { if (data && data.query && data.query.pages && data.query.pages[0]) { if (data.query.pages[0].missing) { showTitleError("was unable to find that article."); } else { console.log('Caching title data...'); config.titleData = data.query.pages[0]; writeLocalDesc; }										} else { console.warn("Error parsing API respose for article:"); console.log(data); showTitleError("was unable to parse the API response when trying get info on " + titleInput.value + "."); finishSubmit; }									});								} else {									console.log('Using cached title data...');									if (config.titleData.missing) {										showTitleError("was unable to find that article.");									} else {										writeLocalDesc;									}								}							} else {								showDateError("A Picture of the Day template already exists at " + templateName + ".");								finishSubmit;							}						} else {							console.warn("Error parsing API respose for template:");							console.log(data);							showDateError("The script was unable to parse the API response when trying get info on the " + templateName + " template.");							finishSubmit;						}					} ); } else { showImageError("was unable to find on that image."); finishSubmit; }			} else { showImageError("was unable to find any categories on that image."); finishSubmit; }		}		function submitClick { titleMessage.toggle(false); imageMessage.toggle(false); dateMessage.toggle(false); submitMessage.toggle(false); if (uploaderInput.value != "" && uploaderInput.value.search(/^User:/i) == -1) { showImageMessage("Uploader name must begin with \"User:\"."); uploaderInput.select; } else if (nominatorInput.value != "" && nominatorInput.value.search(/^User:/i) == -1) { showImageMessage("Nominator name must begin with \"User:\"."); nominatorInput.select; } else if (creditInput.value.includes(creditDefault) || creditInput.value.includes(nameDefault)) { showImageMessage("Please enter a real image credit."); creditInput.select; } else if (secondaryCreditInput.value.includes(secondaryCreditDefault) || secondaryCreditInput.value.includes(nameDefault) ) { showImageMessage("Please enter a real secondary credit or leave it blank."); secondaryCreditInput.select; } else if (isNaN(Date.parse(dateInput.value))) { showDateError("Invalid date."); dateInput.select; } else { submitButton.setDisabled(true).pushPending.toggleFramed(false); closeButton.setDisabled(true).pushPending.toggleFramed(false); dateInput.setValue(new Date(dateInput.value).toISOString.split('T')[0]); config.editSummary = config.editSummaryPattern.replace(/%(\d+)/g, function(_, n) {return [imageInput.value, dateInput.value][n];}) + config.editSummarySuffix; fetchImageData(preCheck, finishSubmit); }		}		function filePrefill(imageInput, titleInput) { imageInput.setValue(mw.config.get('wgTitle')); fetchImageData(function {				fillUsage(config.imageData, titleInput);				if (!uploaderInput.value.length && !nominatorInput.value.length) { getImageInfo; }			} ); }		function articlePrefill(imageInput, titleInput) { titleInput.setValue(mw.config.get('wgTitle')); if (typeof config.titleData === 'undefined') { console.log('Fetching title data...'); new mw.Api.get(					Object.assign( {titles: titleInput.value}, config.query, config.revQuery, config.titleQuery )				).fail(function(code, error) {					console.warn("API error getting Page Image:");					console.warn(error);				}).done( function(data) {					if (data && data.query && data.query.pages && data.query.pages[0]) {						console.log('Caching title data...');						config.titleData = data.query.pages[0];						fillImage(config.titleData, imageInput);						if (!captionInput.value.length) { getCaption; }					} else {						console.warn("Error parsing API respose for title:");						console.log(data);					}				} ); } else { console.log('Using cached title data...'); fillImage(config.titleData, imageInput); if (!captionInput.value.length) { getCaption; } }		}		function checkSizeInput { fetchImageData(function {				checkSize;				if (config.wide) {					showImageMessage("Image will be wider than "+config.maxWidth+"px. " +(config.aspectRatio >= 1.5 						? "The wide=yes parameter will be set in the POTD template unless the size is reduced" 						: "Consider reducing the size") +" to "+config.maxWidth+" or less.", "warning");				} else if (config.tall) {					var maxSizeMsg = (config.aspectRatio ? " to "+Math.floor(config.maxHeight*config.aspectRatio)+" or less ("+Math.floor(config.suggestHeight*config.aspectRatio)+" for an image height of "+config.suggestHeight+"px)" : "");					showImageMessage("Image will be taller than "+config.maxHeight+"px. " +(config.aspectRatio < 0.67						? "The tall=yes parameter will be set in the POTD template unless the size is reduced"						: "Consider reducing the size") +maxSizeMsg+".", "warning");				} else if (typeof imageMessage.getLabel == 'string' && imageMessage.getLabel.startsWith("Image will be")) {					imageMessage.toggle(false);				}			} ); }		if (typeof POTDFieldset === 'undefined') { var creditDefault = 'Photograph/Painting/etc.', secondaryCreditDefault = 'restored/photographed/etc.', nameDefault = ''; var titleMessage = new OO.ui.MessageWidget( {type: 'error', showClose: true} ), titleInput = new OO.ui.ComboBoxInputWidget( { placeholder: 'Article the image represents', indicator: 'required', validate: 'non-empty'} ), autofillTitleButton = new OO.ui.ButtonWidget( { label: 'Autofill caption', icon: 'search', flags: ['progressive'] } ), captionInput = new OO.ui.MultilineTextInputWidget({placeholder: '\'\'\'Article title\'\'\' is...', autosize: true, }), texttitleInput = new OO.ui.TextInputWidget( { placeholder: 'Short caption. Leave blank to use Title' } ), alttextInput = new OO.ui.TextInputWidget( { placeholder: 'Leave blank to use Text Title' } ), creditInput = new OO.ui.TextInputWidget( { value: creditDefault + ' credit: ' + nameDefault, indicator: 'required', validate: function(v) {return (v != "" && !v.includes(creditDefault) && !v.includes(nameDefault));} } ), secondaryCreditInput = new OO.ui.TextInputWidget( { value: secondaryCreditDefault + ' by ' + nameDefault, validate: function(v) {return (!v.includes(secondaryCreditDefault) && !v.includes(nameDefault));} } ), sizeInput = new OO.ui.TextInputWidget( { placeholder: 'Size in pixels (defaults to '+config.defaultWidth.toString+')', type: 'number' } ), imageMessage = new OO.ui.MessageWidget( {type: 'error', showClose: true} ), imageInput = new OO.ui.ComboBoxInputWidget( { placeholder: 'File name without "File:"', indicator: 'required', validate: 'non-empty' } ), autofillImageButton = new OO.ui.ButtonWidget( { label: 'Autofill image details', icon: 'search', flags: ['progressive'] } ), uploaderInput = new OO.ui.TextInputWidget( { placeholder: 'User:', validate: function(v){return (v == "" || v.search(/^User:/i) != -1); } } ), nominatorInput = new OO.ui.TextInputWidget( { placeholder: 'User:', validate: function(v){return (v == "" || v.search(/^User:/i) != -1); } } ), dateMessage = new OO.ui.MessageWidget( {type: 'error', showClose: true} ), dateInput = new OO.ui.TextInputWidget( { placeholder: 'YYYY-MM-DD', indicator: 'required', validate: function(v) {return !isNaN(Date.parse(v));} } ), commentsInput = new OO.ui.TextInputWidget( { placeholder: '[optional]' } ), submitMessage = new OO.ui.MessageWidget( {type: 'notice', showClose: true} ), submitButton = new OO.ui.ActionWidget( { label: 'Submit'+(debug ? " (debug)" : ""), disabled: true, framed: true, flags: ['primary','progressive']} ), closeButton = new OO.ui.ActionWidget( { label: 'Close', framed: true, flags: ['primary','destructive']} ); var POTDFieldset = new OO.ui.FieldsetLayout( { label: potdScriptLongTitle, classes: [ 'container' ] } ), titleFieldset = new OO.ui.FieldsetLayout( { label: 'Linked article', classes: [ 'container' ] } ), imageFieldset = new OO.ui.FieldsetLayout( { label: 'Image information', classes: [ 'container' ] } ), templateFieldset = new OO.ui.FieldsetLayout( { label: 'Template information', classes: [ 'container' ] } ), submitFieldset = new OO.ui.FieldsetLayout( { classes: [ 'container' ] } ); titleFieldset.addItems( [				titleMessage,				new OO.ui.ActionFieldLayout(titleInput, autofillTitleButton, {align: 'top', label: 'Title'}),				new OO.ui.FieldLayout(captionInput, {align: 'top', label: 'Caption'}),				new OO.ui.FieldLayout(texttitleInput, {align: 'top', label: 'Text title'})			] ); imageFieldset.addItems( [				imageMessage,				new OO.ui.ActionFieldLayout(imageInput, autofillImageButton, {align: 'top', label: 'Image'}),				new OO.ui.FieldLayout(uploaderInput, {align: 'top', label: 'Original uploader'}),				new OO.ui.FieldLayout(nominatorInput, {align: 'top', label: 'Featured Picture nominator'}),				new OO.ui.FieldLayout(creditInput, {align: 'top', label: 'Credit (use full name, not user name, if known)'}),				new OO.ui.FieldLayout(secondaryCreditInput, {align: 'top', label: 'Secondary credit (may be blank)'}),				new OO.ui.FieldLayout(alttextInput, {align: 'top', label: 'Alt text'}),				new OO.ui.FieldLayout(sizeInput, {align: 'top', label: 'Size'})			] ); templateFieldset.addItems( [				dateMessage,				new OO.ui.FieldLayout(dateInput, {align: 'top', label: 'Date'}),				new OO.ui.FieldLayout(commentsInput, {align: 'top', label: 'Additional comments for talk page messages'}),			] ); submitFieldset.addItems( [				new OO.ui.FieldLayout(submitMessage, {}),				new OO.ui.FieldLayout(new OO.ui.ButtonGroupWidget( { items: [ submitButton, closeButton] } ))			] ); POTDFieldset.addItems( [ 				titleFieldset,				imageFieldset,				templateFieldset,				submitFieldset			] ); if (mw.config.get('wgNamespaceNumber') == 6) { filePrefill(imageInput, titleInput); } else if (mw.config.get('wgNamespaceNumber') == 0) { articlePrefill(imageInput, titleInput); }			checkButtons;

titleInput.inputFilter = function(value){return value.replace(/^\[\[/, ).replace(/\]\]$/, ).replace('_', ' ');}; imageInput.inputFilter = function(value){return value.replace(/^File:/, '').replace('_', ' ');}; creditInput.on( 'change', checkButtons ); titleInput.on( 'change', function {checkButtons;delete config.titleData;}); titleInput.on( 'enter', getCaption); dateInput.on( 'change', checkButtons); imageInput.on( 'change', function {checkButtons;delete config.imageData;fetchImageData(function{imageMessage.toggle(false);checkSizeInput;});}); imageInput.on( 'enter', getImageInfo ); autofillTitleButton.on( 'click', getCaption); autofillImageButton.on( 'click', getImageInfo); sizeInput.on ( 'change', checkSizeInput); submitButton.on( 'click', submitClick); closeButton.on( 'click', function {POTDFieldset.toggle(false);} ); submitMessage.on( 'close', function {					config.submitMessages = [];					submitMessage.setType('notice');				} ).on( 'toggle', function {					if (!submitMessage.isVisible) {						config.submitMessages = [];						submitMessage.setType('notice');					}				} );

titleMessage.toggle(false); imageMessage.toggle(false); dateMessage.toggle(false); submitMessage.toggle(false); $( POTDFieldset.$element ).insertBefore( "#mw-content-text" ); } else { POTDFieldset.toggle(true); }	}	function loadPOTDHelper { mw.loader.getScript(			'https://tools-static.wmflabs.org/cdnjs/ajax/libs/xregexp/3.2.0/xregexp-all.js'		).then( function {			console.log('XRegExp loaded.');			POTDHelper;		}, function ( e ) {			errorMessage = "Error: Cannot load XRegExp: " + e.message;			console.error( errorMessage );			mw.notify( errorMessage, {type: 'error'} );		} ); }	if ((mw.config.get('wgNamespaceNumber') == 6 && mw.config.get('wgCategories').find( function(cat) {return cat == potdFPCategory;} )) || mw.config.get('wgNamespaceNumber') == 0) { var portletLink = mw.util.addPortletLink("p-cactions", "#", potdScriptShortTitle,		"ca-potdhelper", "Make image a Picture of the Day"); $( portletLink ).click(function(e) {			e.preventDefault;			return loadPOTDHelper;		} ); } else if (mw.config.get('wgNamespaceNumber') == -1 && mw.config.get('wgTitle').toLowerCase === "potdhelper") { document.title = "Special:" + potdScriptShortTitle + ' - Wikipedia'; document.getElementsByTagName("h1")[0].textContent = "Special:" + potdScriptShortTitle; document.getElementById("mw-content-text").innerHTML=""; loadPOTDHelper; } } ); //