From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.

//jshint maxerr:512

// <nowiki>

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: '[[File:%0]] scheduled for [[WP:POTD|POTD]] on [[Template:POTD/%1|%1]]',

			editSummarySuffix: ' ([[' + potdScriptLocation + '|' + potdScriptShortTitle + ']])',

			panoWidth: 500,

			defaultWidth: 350,

			landscapeWidth: 300,

			squareWidth: 275,

			portraitWidth: 250,

			tallWidth: 225,

			maxWidth: 650,

			suggestHeight: 350,

			maxHeight: 450,

			aspectRatio: 0,

			submitMessageHeader: '<strong>Submitting Picture of the Day:</strong><ul><li>',

			submitMessageFooter: '</li></ul>',

			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'

			},

			: {

				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(v0]));

				return '<a href="'+ url + '">' + (v1 || v0]) + "</a>";

			} );

			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 [[File:" + imageInput.value + "]] 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("</li><li>") + 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.pages0]) {

						if (data.query.pages0].missing) {

							if (data.query.pages0].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.pages0];

							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.pages0 && nom.query.pages0].revisions) {

					if (nom.query.pages0].revisions0 && nom.query.pages0].revisions0].user && nom.query.pages0].revisions0].user.length) {

						nominatorInput.setValue("User:" + nom.query.pages0].revisions0].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.revisions0 && imageData.revisions0].slots && imageData.revisions0].slots.main && imageData.revisions0].slots.main.content) {

								var content = imageData.revisions0].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 {{Featured picture}} template on [[" + imageInput.value + "]]: " + error + ".");

								}

								if (nominations.length && nominations0].length) {

									var nomination = config.fpcPrefix + nominations0];

									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 [[Category:" + config.fpCategory + "]] 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 = infoinfo.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.revisions0 && titleData.revisions0].slots &&

					titleData.revisions0].slots.main && titleData.revisions0].slots.main.content) {

					var content = titleData.revisions0].slots.main.content,

						xValues = [];

					

					content = content.replace(/(\[\[File:.*\]\][\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 = xValuesi];

							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.*?>(.*?)<\/ref>/g, "");

							extract = extract.replace(/<ref.*?\/>/g, "");

							re = new RegExp(/'''('')?(.*?)\1''' /);

							titleMatch=extract.match(re);

							if (titleMatch) {

								if (titleMatch2==titleInput.value) {

									captionInput.setValue(extract.replace(re, "'''$1[[$2]]$1''' "));

								} else {

									captionInput.setValue(extract.replace(re, "'''[["+titleInput.value+"|$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.pages0]) {

						console.log('Caching title data...');

						config.titleData = data.query.pages0];

						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. );

				

				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 = "\n{{subst:" + "UpcomingPOTD" + 

				"|1=File:" + imageInput.value +

				"|2=" + dateInput.value +

				(commentsInput.value.length ? ("|3=" + commentsInput.value) : "") +

				"}}",

				titleTalk = 'Talk:' + titleInput.value;

			

			console.log(templateText);

			

			var params = Object.assign( {

				title: titleTalk,

				appendtext: templateText,

				summary: config.editSummary,

				redirect: 1

			}, config. );

			

			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.imageinfo0 && config.imageData.imageinfo0].width > 0) {

				var imageWidth = config.imageData.imageinfo0].width;

				var imageHeight = config.imageData.imageinfo0].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("'''[[<!--article-->]]'''");

			}

			var templateText = "{{POTD {{{1|{{{style|default}}}}}}" +

				"\n|image=" + imageInput.value +

				"\n|size=" + sizeInput.value +

				( (config.wide && config.aspectRatio >= 1.5) ? "\n|wide=yes" : "" ) +

				( (config.tall && config.aspectRatio < 0.67) ? "\n|tall=yes" : "" ) +

				"\n|title=[[" + titleInput.value + "]]" +

				"\n|texttitle=" + texttitleInput.value +

				( alttextInput.value.length ? ("\n|alttext=" + alttextInput.value) : "" ) +

				"\n|caption=\n\n" + captionInput.value +

				"\n\n|credit=" + creditInput.value + ( secondaryCreditInput.value.length ? ("; " + secondaryCreditInput.value) : "" ) +

				"\n}}<noinclude>[[Category:Wikipedia Picture of the day {{#time:F Y|{{SUBPAGENAME}}}}]]" + 

				"\n\n== See also ==" + 

				"\n* [[Template:POTD{{#ifeq:{{BASEPAGENAME}}|POTD protected||&#32;protected}}/{{SUBPAGENAME}}]]</noinclude>";

			

			console.log(templateText);

			

			var params = Object.assign( {

				createonly: 1,

				title: templateName,

				text: templateText,

				summary: 'Creating a [[WP:POTD|POTD]] template for [[File:' + imageInput.value + ']]' + config.editSummarySuffix

			}, config. );

			

			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{{Picture of the day|' + dateInput.value + '}}',

				summary: config.editSummary,

				redirect: 1,

				nocreate: 1

			}, config. );

			

			if (debug) {

				console.log(params);

				showSubmitMessage("Simulated message to [[File:" + imageInput.value + "]].");

				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 [[File:" + imageInput.value + "]]: " + error.error.info, 'warning');

						finishSubmit(true);

					} ).done( function() {

						showSubmitMessage("Added message to [[File:" + imageInput.value + "]].");

						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.pages0]) {

							if (data.query.pages0].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.pages0]) {

											if (data.query.pages0].missing) {

												showTitleError("was unable to find that article.");

											} else {

												console.log('Caching title data...');

												config.titleData = data.query.pages0];

												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 [[Category:" + config.fpCategory + "]] 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.pages0]) {

						console.log('Caching title data...');

						config.titleData = data.query.pages0];

						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 = '[[<!--name-->]]';

			

			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();

	}

} );

// </nowiki>
From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.

//jshint maxerr:512

// <nowiki>

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: '[[File:%0]] scheduled for [[WP:POTD|POTD]] on [[Template:POTD/%1|%1]]',

			editSummarySuffix: ' ([[' + potdScriptLocation + '|' + potdScriptShortTitle + ']])',

			panoWidth: 500,

			defaultWidth: 350,

			landscapeWidth: 300,

			squareWidth: 275,

			portraitWidth: 250,

			tallWidth: 225,

			maxWidth: 650,

			suggestHeight: 350,

			maxHeight: 450,

			aspectRatio: 0,

			submitMessageHeader: '<strong>Submitting Picture of the Day:</strong><ul><li>',

			submitMessageFooter: '</li></ul>',

			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'

			},

			: {

				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(v0]));

				return '<a href="'+ url + '">' + (v1 || v0]) + "</a>";

			} );

			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 [[File:" + imageInput.value + "]] 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("</li><li>") + 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.pages0]) {

						if (data.query.pages0].missing) {

							if (data.query.pages0].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.pages0];

							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.pages0 && nom.query.pages0].revisions) {

					if (nom.query.pages0].revisions0 && nom.query.pages0].revisions0].user && nom.query.pages0].revisions0].user.length) {

						nominatorInput.setValue("User:" + nom.query.pages0].revisions0].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.revisions0 && imageData.revisions0].slots && imageData.revisions0].slots.main && imageData.revisions0].slots.main.content) {

								var content = imageData.revisions0].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 {{Featured picture}} template on [[" + imageInput.value + "]]: " + error + ".");

								}

								if (nominations.length && nominations0].length) {

									var nomination = config.fpcPrefix + nominations0];

									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 [[Category:" + config.fpCategory + "]] 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 = infoinfo.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.revisions0 && titleData.revisions0].slots &&

					titleData.revisions0].slots.main && titleData.revisions0].slots.main.content) {

					var content = titleData.revisions0].slots.main.content,

						xValues = [];

					

					content = content.replace(/(\[\[File:.*\]\][\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 = xValuesi];

							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.*?>(.*?)<\/ref>/g, "");

							extract = extract.replace(/<ref.*?\/>/g, "");

							re = new RegExp(/'''('')?(.*?)\1''' /);

							titleMatch=extract.match(re);

							if (titleMatch) {

								if (titleMatch2==titleInput.value) {

									captionInput.setValue(extract.replace(re, "'''$1[[$2]]$1''' "));

								} else {

									captionInput.setValue(extract.replace(re, "'''[["+titleInput.value+"|$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.pages0]) {

						console.log('Caching title data...');

						config.titleData = data.query.pages0];

						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. );

				

				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 = "\n{{subst:" + "UpcomingPOTD" + 

				"|1=File:" + imageInput.value +

				"|2=" + dateInput.value +

				(commentsInput.value.length ? ("|3=" + commentsInput.value) : "") +

				"}}",

				titleTalk = 'Talk:' + titleInput.value;

			

			console.log(templateText);

			

			var params = Object.assign( {

				title: titleTalk,

				appendtext: templateText,

				summary: config.editSummary,

				redirect: 1

			}, config. );

			

			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.imageinfo0 && config.imageData.imageinfo0].width > 0) {

				var imageWidth = config.imageData.imageinfo0].width;

				var imageHeight = config.imageData.imageinfo0].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("'''[[<!--article-->]]'''");

			}

			var templateText = "{{POTD {{{1|{{{style|default}}}}}}" +

				"\n|image=" + imageInput.value +

				"\n|size=" + sizeInput.value +

				( (config.wide && config.aspectRatio >= 1.5) ? "\n|wide=yes" : "" ) +

				( (config.tall && config.aspectRatio < 0.67) ? "\n|tall=yes" : "" ) +

				"\n|title=[[" + titleInput.value + "]]" +

				"\n|texttitle=" + texttitleInput.value +

				( alttextInput.value.length ? ("\n|alttext=" + alttextInput.value) : "" ) +

				"\n|caption=\n\n" + captionInput.value +

				"\n\n|credit=" + creditInput.value + ( secondaryCreditInput.value.length ? ("; " + secondaryCreditInput.value) : "" ) +

				"\n}}<noinclude>[[Category:Wikipedia Picture of the day {{#time:F Y|{{SUBPAGENAME}}}}]]" + 

				"\n\n== See also ==" + 

				"\n* [[Template:POTD{{#ifeq:{{BASEPAGENAME}}|POTD protected||&#32;protected}}/{{SUBPAGENAME}}]]</noinclude>";

			

			console.log(templateText);

			

			var params = Object.assign( {

				createonly: 1,

				title: templateName,

				text: templateText,

				summary: 'Creating a [[WP:POTD|POTD]] template for [[File:' + imageInput.value + ']]' + config.editSummarySuffix

			}, config. );

			

			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{{Picture of the day|' + dateInput.value + '}}',

				summary: config.editSummary,

				redirect: 1,

				nocreate: 1

			}, config. );

			

			if (debug) {

				console.log(params);

				showSubmitMessage("Simulated message to [[File:" + imageInput.value + "]].");

				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 [[File:" + imageInput.value + "]]: " + error.error.info, 'warning');

						finishSubmit(true);

					} ).done( function() {

						showSubmitMessage("Added message to [[File:" + imageInput.value + "]].");

						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.pages0]) {

							if (data.query.pages0].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.pages0]) {

											if (data.query.pages0].missing) {

												showTitleError("was unable to find that article.");

											} else {

												console.log('Caching title data...');

												config.titleData = data.query.pages0];

												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 [[Category:" + config.fpCategory + "]] 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.pages0]) {

						console.log('Caching title data...');

						config.titleData = data.query.pages0];

						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 = '[[<!--name-->]]';

			

			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();

	}

} );

// </nowiki>

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook