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.

/**

 * Script for enabling temporary watchlisting of pages

 *

 */



/* jshint maxerr: 999 */



// <nowiki>



var api;



$.when(

	mw.loader.using(['mediawiki.util', 'mediawiki.user', 'mediawiki.api', 'mediawiki.Title', 'moment']), 

	$.ready

).then(function() {



	api = new mw.Api();



	// Menu interface

	if (mw.config.get('wgNamespaceNumber') >= 0) {



		// For vector skin, make a submenu within the "more" dropdown, inspired by [[meta:MoreMenu]]

		var hasMenu = false;

		if (mw.config.get('skin') === 'vector') {

			hasMenu = true;

			$(mw.util.addPortletLink('p-cactions', '#', 'T-Watch...', 'ca-twatch')).css({

				'position': 'relative'

			}).append(

				$('<ul>').addClass('menu').css({

					'display': 'none',

					'background-color': '#fff',

					'border': '1px solid #aaa'

				})

			).click(function(e) {

				e.preventDefault();

			}).on('mouseenter', function() {

				$(this).find('.menu').css({

					'left': $(this).outerWidth(),

					'top': '-1px',

					'position': 'absolute'

				}).show();

			}).on('mouseleave', function() {

				$(this).find('.menu').hide();

			});



		} else if (mw.config.get('skin') === 'monobook') {

			hasMenu = true;

			$(mw.util.addPortletLink('p-cactions', '#', 'T-Watch...', 'ca-twatch')).css({

				'position': 'relative',

				'padding-bottom': '0'

			}).append(

				$('<ul>').addClass('menu').css({

					'display': 'none',

					'z-index': '1000',

					'list-style': 'none',

					'background-color': '#fff',

					'border': '1px solid #aaa',

					'margin': '0'

				})

			).click(function(e) {

				e.preventDefault();

			}).on('mouseenter', function() {

				$(this).find('.menu').css({

					'left': '0px',

					'top': $(this).outerHeight(),

					'position': 'absolute'

				}).show();

			}).on('mouseleave', function() {

				$(this).find('.menu').hide();

			});

			mw.util.addCSS(

				'#ca-twatch .menu li { display: list-item; border: none; }' +

				'#ca-twatch .menu li a { background: none !important; }' + // !important needed for IE/firefox

				'#ca-twatch .menu li:hover { text-decoration: underline; }'

			);

		}



		var menuItems = $.isArray(window.TWatch_Durations_viewing) ?

			window.TWatch_Durations_viewing :

			'1 week', '1 month'];



		menuItems.forEach(function(duration) {

			var li = mw.util.addPortletLink(hasMenu ? 'ca-twatch' : 'p-cactions',

			'#', 'Watch – ' + duration, '', 'Watchlist this page for a duration of ' + duration);

			li.addEventListener('click', function(ev) {

				ev.preventDefault();

				var watchTill = moment().add(parseDuration(duration));

				watchPage(mw.config.get('wgPageName'), watchTill.unix() * 1000);

			});

		});

	}



	// Edit page interface

	if (mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit') {



		var $select = $('<select>').attr('id', 'watchduration').css({

			'margin-left': '5px'

		}).change(function() {

			$('#wpWatchthis')[0].checked = true;

		}).insertAfter($('#wpWatchthisWidget').parent().next());



		var options = $.isArray(window.TWatch_Durations_editing) ?

			window.TWatch_Durations_editing :

			'1 week', '2 weeks', '1 month', '2 months'];



		options.forEach(function(durtext) {

			var watchTill = moment().add(parseDuration(durtext));

			$('<option>')

				.text(durtext)

				.val(watchTill.unix() * 1000)

				.appendTo($select);

		});

		$('<option>').text('Indefinitely').val('inf').prop('selected', true).appendTo($select);



		if (window.TWatch_default_edit_watch_period) {

			$select.find('option:contains("' + window.TWatch_default_edit_watch_period + '")').prop('selected', true);

		}



		// record in pages object that the page is to be unwatched for said duration

		// watching of the page is done by mediawiki

		$('#wpSave').click(function() {

			if ($('#wpWatchthis')[0].checked) {

				var dur = $select.val();

				if (dur === 'inf') {

					return;

				}

				recordAsWatching(mw.config.get('wgPageName'), parseInt(dur));

			}

		});

	}



	// Integration with user scripts that edit pages (probably unnecessary)

	hookEventListener();



	// Special page to see list of temporarily watched pages

	if (mw.config.get('wgPageName') === 'Special:BlankPage/TempWatched' ||

		mw.config.get('wgPageName') === 'Special:BlankPage/T-Watch' ||

		mw.config.get('wgPageName') === 'Special:TempWatched') {

			buildSpecialPage();

	}



	// show 'expiring soon' alerts

	if (mw.config.get('wgCanonicalSpecialPageName') === 'Watchlist' && !window.TWatch_NoAlerts) {

		mw.hook('wikipage.content').add(addWatchlistAlerts);

	}



	// Unwatch expired pages every hour

	var nextCheckTime = mw.user.options.get('userjs-twl-nextcheck');

	if (!nextCheckTime) {  // for first-time users

		api.saveOption('userjs-twl-nextcheck', (new Date().getTime() + 1000*60*60).toString());

	}

	else if (new Date().getTime() > parseInt(nextCheckTime)) {

		removeExpiredPages();

	}



}).catch(console.error);



/**

 * @param {string} page

 * @param {number} till_time - milliseconds since epoch

 */

function watchPage(page, till_time) {

	api.watch(page).done(function() {

		recordAsWatching(page, till_time);

		var title = new mw.Title(page);

		mw.notify(

			'"' + title.toText() + '" and its ' +

			(title.isTalkPage() ? 'associated subject' : 'talk') +

			' page have been added to your watchlist till ' +

			getString(till_time, true)

		);

	}).fail(function(err) {

		mw.notify('Couldn\'t add to watchlist due to an error. Please try again.\n Error: ' +

		JSON.stringify(err));

	});

}



/**

 * @param {string} page

 * @param {number} till_time - milliseconds since epoch

 */

function recordAsWatching(page, till_time) {

	page = new mw.Title(page).getSubjectPage().toText(); // normalize talk page to subject page

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	if (!opt) {

		opt = {};

	}

	optpage = till_time; // expiry timestamp

	api.saveOption('userjs-twl-pages', JSON.stringify(opt));

}



function removeExpiredPages() {

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	if (!opt) return;

	var pagesToUnwatch = [];

	$.each(opt, function(page, expiry) {

		if (new Date().getTime() > expiry) {

			pagesToUnwatch.push(page);

		}

	});



	// kludge: if more than 50 pages, unwatch 50 for now, and leave the rest for the next hour

	if (pagesToUnwatch.length > 50) {

		pagesToUnwatch = pagesToUnwatch.slice(0, 50);

	}

	api.unwatch(pagesToUnwatch).done(function() {

		// check again for expired pages after an hour

		api.saveOption('userjs-twl-nextcheck', (new Date().getTime() + 1000*60*60).toString());



		// update pages object

		pagesToUnwatch.forEach(function(page) {

			delete optpage];

		});

		api.saveOption('userjs-twl-pages', JSON.stringify(opt));

	});

}



function addWatchlistAlerts() {

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	if (!opt) {

		return;

	}

	var threshold = moment().add(parseDuration(window.TWatch_Alert_period || '3 days'));

	$('.mw-changeslist-title').each(function() {

		var page = this.textContent;

		if (optpage && moment(optpage]).isBefore(threshold)) {

			var $container = $(this).parent().parent().parent(); // li element

			if ($container.find('.twatch-expiry-alert').length === 0) {

				var exptext = moment(optpage]).fromNow();

				$('<span>')

					.text('[expires ' + exptext + ']')

					.attr('title', 'This page will be removed from your watchlist around ' + getString(optpage], true))

					.addClass('twatch-expiry-alert')

					.css({

						'font-size': '80%',

						'padding-left': '5px',

						'color': 'brown'

					}).appendTo($container);

			}

		}

	});

}



/**

 * @param {String} str - a string specifying duration - eg. "3 weeks", "2 months"

 * @returns {moment.duration} - moment Duration object

 */

function parseDuration(str) {

	var i;

	for (i = 0; i < str.length; i++) {

		if (stri < '0' || stri > '9') {

			break;

		}

	}

	var num = parseInt(str);

	var text = str.slice(i).trim();

	var momentObject = moment.duration(num, text);

	if (!momentObject._isValid || momentObject.asMilliseconds() === 0) {

		console.error('Invalid duration string: "' + str + '"');

	}

	return momentObject;

}



function hookEventListener() {

	mw.hook('record_watch').add(function(arg) {

		if (!arg) arg = {};

		arg.page = arg.page || mw.config.get('wgPageName');

		arg.setting = arg.setting || 'preferences'; // allows input like window.ScriptNameWatchPref

		arg.duration = arg.duration || window.tempWatchlistDefaultDuration || 'inf';

		arg.action; // 'edit', 'create', 'upload', 'move', 'delete', 'rollback'



		if (arg.setting === 'watch' || arg.setting === true) {

			if (arg.duration !== 'inf')

				recordAsWatching(arg.page, arg.duration);

			api.watch(arg.page); // client script should do this ideally, but just in case...

		} else if (arg.setting === 'preferences') {  // consult user's site preferences

			var pref;

			switch (arg.action) {

				case 'create': pref = 'watchcreations'; break;

				case 'move': pref = 'watchmoves'; break;

				case 'delete': pref = 'watchdeletions'; break;

				case 'upload': pref = 'watchuploads'; break;

				case 'rollback': pref = 'watchrollbacks'; break;

				default: pref = 'watchdefault';

			}

			if (mw.user.options.get(pref) == 1) { // dunno whether its string or number

				if (arg.duration !== 'inf')

					recordAsWatching(arg.page, arg.duration);

				api.watch(arg.page);

			}

		}

	});

}



function buildSpecialPage() {

	$('#firstHeading').text('Temporarily watched pages');

	document.title = 'Temporarily watched pages';

	$('#mw-content-text').empty();



	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));



	var $ul = $('<ul>');

	$.each(opt, function(page, expiry) {

		$ul.append(

			$('<li>').html(

				'<a href="' + mw.util.getUrl(page) + '" title="' + page + '">'+ page + '</a>: ' +

				getString(expiry)

			)

		);

	});

	$('#mw-content-text').append(

		$('<p>').text('The following pages are set to be automatically unwatched after the given time in ' + getTimeZoneString() + ' time zone:'),

		$('<p>').html('This list may include any pages that you may have subsequently unwatched manually, <a id="purgeunwatchedpages">click here to purge such pages</a>.'),

		$ul

	);

	$('#purgeunwatchedpages').click(function() {



		$ul.replaceWith('Purging...');

		var arrayOfPages = Object.keys(opt); // ASSUME < 50 for now

		if (arrayOfPages.length > 50) {

			alert('You have more than 50 pages here: purge feature coming soon');

			return;

		}

		api.get({

			"action": "query",

			"format": "json",

			"prop": "info",

			"titles": arrayOfPages,

			"inprop": "watched"

		}).then(function(json) {

			Object.values(json.query.pages).forEach(function(info) {

				if (info.watched === undefined) {

					delete optinfo.title];

				}

			});

			opt = JSON.stringify(opt);

			api.saveOption('userjs-twl-pages', opt).then(function() {

				mw.user.options.set('userjs-twl-pages', opt);

				buildSpecialPage();

			});

		});





		// var arrayOfArrays = arrayChunk(arrayOfPages, 50);

		// arrayOfArrays.forEach(function(array) {

		// 	api.get({

		// 		"action": "query",

		// 		"format": "json",

		// 		"prop": "info",

		// 		"titles": array,

		// 		"inprop": "watched"

		// 	}).then(function(json) {

		// 		Object.values(json.query.pages).forEach(function(info) {

		// 			if (info.watched === undefined) {

		// 				delete opt[info.title.replace(/ /g, '_')];

		// 			}

		// 		});

		// 	});

		// });



	});

}



// HELPER FUNCTIONS:



/**

 * @param {number} date - milliseconds since epoch

 */

function getString(date, withzone) {

	return moment(date).utcOffset(getUserTimeZone()).format('HH:mm, D MMMM YYYY') +

	(withzone ? (' (' + getTimeZoneString() + ').') : '');

}



function getUserTimeZone() {

	if (window.userTimeZone) { // cache it

		return window.userTimeZone;

	}

	var pref = mw.user.options.get('timecorrection');

	if (pref.indexOf('ZoneInfo|') === 0) {

		window.userTimeZone = parseInt(pref.slice('ZoneInfo|'.length));

	} else if (pref.indexOf('Offset|') === 0) {

		window.userTimeZone = parseInt(pref.slice('Offset|'.length));

	} else if (pref === 'System|0') {

		window.userTimeZone = 0;

	} else {

		console.error('[W-Ping]: unparsable time zone: ' + pref);

	}

	return window.userTimeZone;

}



function getTimeZoneString(timecorrection) {

	timecorrection = timecorrection || getUserTimeZone();

	var negative = false;

	if (timecorrection < 0) {

		timecorrection = -timecorrection;

		negative = true;

	}

	var hourCorrection = parseInt(timecorrection/60);

	hourCorrection = (hourCorrection < 10 ? '0' : '') + hourCorrection.toString();



	var minuteCorrection = timecorrection % 60;

	minuteCorrection = (minuteCorrection < 10 ? '0' : '') + minuteCorrection.toString();



	return 'UTC' + (negative ? '–' : '+') + hourCorrection + minuteCorrection;

}



// function arrayChunk(arr, size) {

// 	var result = [];

// 	var current;

// 	for (var i = 0; i < arr.length; ++i) {

// 		if (i % size === 0) { // when 'i' is 0, this is always true, so we start by creating one.

// 			current = [];

// 			result.push(current);

// 		}

// 		current.push(arr[i]);

// 	}

// 	return result;

// }



// </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.

/**

 * Script for enabling temporary watchlisting of pages

 *

 */



/* jshint maxerr: 999 */



// <nowiki>



var api;



$.when(

	mw.loader.using(['mediawiki.util', 'mediawiki.user', 'mediawiki.api', 'mediawiki.Title', 'moment']), 

	$.ready

).then(function() {



	api = new mw.Api();



	// Menu interface

	if (mw.config.get('wgNamespaceNumber') >= 0) {



		// For vector skin, make a submenu within the "more" dropdown, inspired by [[meta:MoreMenu]]

		var hasMenu = false;

		if (mw.config.get('skin') === 'vector') {

			hasMenu = true;

			$(mw.util.addPortletLink('p-cactions', '#', 'T-Watch...', 'ca-twatch')).css({

				'position': 'relative'

			}).append(

				$('<ul>').addClass('menu').css({

					'display': 'none',

					'background-color': '#fff',

					'border': '1px solid #aaa'

				})

			).click(function(e) {

				e.preventDefault();

			}).on('mouseenter', function() {

				$(this).find('.menu').css({

					'left': $(this).outerWidth(),

					'top': '-1px',

					'position': 'absolute'

				}).show();

			}).on('mouseleave', function() {

				$(this).find('.menu').hide();

			});



		} else if (mw.config.get('skin') === 'monobook') {

			hasMenu = true;

			$(mw.util.addPortletLink('p-cactions', '#', 'T-Watch...', 'ca-twatch')).css({

				'position': 'relative',

				'padding-bottom': '0'

			}).append(

				$('<ul>').addClass('menu').css({

					'display': 'none',

					'z-index': '1000',

					'list-style': 'none',

					'background-color': '#fff',

					'border': '1px solid #aaa',

					'margin': '0'

				})

			).click(function(e) {

				e.preventDefault();

			}).on('mouseenter', function() {

				$(this).find('.menu').css({

					'left': '0px',

					'top': $(this).outerHeight(),

					'position': 'absolute'

				}).show();

			}).on('mouseleave', function() {

				$(this).find('.menu').hide();

			});

			mw.util.addCSS(

				'#ca-twatch .menu li { display: list-item; border: none; }' +

				'#ca-twatch .menu li a { background: none !important; }' + // !important needed for IE/firefox

				'#ca-twatch .menu li:hover { text-decoration: underline; }'

			);

		}



		var menuItems = $.isArray(window.TWatch_Durations_viewing) ?

			window.TWatch_Durations_viewing :

			'1 week', '1 month'];



		menuItems.forEach(function(duration) {

			var li = mw.util.addPortletLink(hasMenu ? 'ca-twatch' : 'p-cactions',

			'#', 'Watch – ' + duration, '', 'Watchlist this page for a duration of ' + duration);

			li.addEventListener('click', function(ev) {

				ev.preventDefault();

				var watchTill = moment().add(parseDuration(duration));

				watchPage(mw.config.get('wgPageName'), watchTill.unix() * 1000);

			});

		});

	}



	// Edit page interface

	if (mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit') {



		var $select = $('<select>').attr('id', 'watchduration').css({

			'margin-left': '5px'

		}).change(function() {

			$('#wpWatchthis')[0].checked = true;

		}).insertAfter($('#wpWatchthisWidget').parent().next());



		var options = $.isArray(window.TWatch_Durations_editing) ?

			window.TWatch_Durations_editing :

			'1 week', '2 weeks', '1 month', '2 months'];



		options.forEach(function(durtext) {

			var watchTill = moment().add(parseDuration(durtext));

			$('<option>')

				.text(durtext)

				.val(watchTill.unix() * 1000)

				.appendTo($select);

		});

		$('<option>').text('Indefinitely').val('inf').prop('selected', true).appendTo($select);



		if (window.TWatch_default_edit_watch_period) {

			$select.find('option:contains("' + window.TWatch_default_edit_watch_period + '")').prop('selected', true);

		}



		// record in pages object that the page is to be unwatched for said duration

		// watching of the page is done by mediawiki

		$('#wpSave').click(function() {

			if ($('#wpWatchthis')[0].checked) {

				var dur = $select.val();

				if (dur === 'inf') {

					return;

				}

				recordAsWatching(mw.config.get('wgPageName'), parseInt(dur));

			}

		});

	}



	// Integration with user scripts that edit pages (probably unnecessary)

	hookEventListener();



	// Special page to see list of temporarily watched pages

	if (mw.config.get('wgPageName') === 'Special:BlankPage/TempWatched' ||

		mw.config.get('wgPageName') === 'Special:BlankPage/T-Watch' ||

		mw.config.get('wgPageName') === 'Special:TempWatched') {

			buildSpecialPage();

	}



	// show 'expiring soon' alerts

	if (mw.config.get('wgCanonicalSpecialPageName') === 'Watchlist' && !window.TWatch_NoAlerts) {

		mw.hook('wikipage.content').add(addWatchlistAlerts);

	}



	// Unwatch expired pages every hour

	var nextCheckTime = mw.user.options.get('userjs-twl-nextcheck');

	if (!nextCheckTime) {  // for first-time users

		api.saveOption('userjs-twl-nextcheck', (new Date().getTime() + 1000*60*60).toString());

	}

	else if (new Date().getTime() > parseInt(nextCheckTime)) {

		removeExpiredPages();

	}



}).catch(console.error);



/**

 * @param {string} page

 * @param {number} till_time - milliseconds since epoch

 */

function watchPage(page, till_time) {

	api.watch(page).done(function() {

		recordAsWatching(page, till_time);

		var title = new mw.Title(page);

		mw.notify(

			'"' + title.toText() + '" and its ' +

			(title.isTalkPage() ? 'associated subject' : 'talk') +

			' page have been added to your watchlist till ' +

			getString(till_time, true)

		);

	}).fail(function(err) {

		mw.notify('Couldn\'t add to watchlist due to an error. Please try again.\n Error: ' +

		JSON.stringify(err));

	});

}



/**

 * @param {string} page

 * @param {number} till_time - milliseconds since epoch

 */

function recordAsWatching(page, till_time) {

	page = new mw.Title(page).getSubjectPage().toText(); // normalize talk page to subject page

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	if (!opt) {

		opt = {};

	}

	optpage = till_time; // expiry timestamp

	api.saveOption('userjs-twl-pages', JSON.stringify(opt));

}



function removeExpiredPages() {

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	if (!opt) return;

	var pagesToUnwatch = [];

	$.each(opt, function(page, expiry) {

		if (new Date().getTime() > expiry) {

			pagesToUnwatch.push(page);

		}

	});



	// kludge: if more than 50 pages, unwatch 50 for now, and leave the rest for the next hour

	if (pagesToUnwatch.length > 50) {

		pagesToUnwatch = pagesToUnwatch.slice(0, 50);

	}

	api.unwatch(pagesToUnwatch).done(function() {

		// check again for expired pages after an hour

		api.saveOption('userjs-twl-nextcheck', (new Date().getTime() + 1000*60*60).toString());



		// update pages object

		pagesToUnwatch.forEach(function(page) {

			delete optpage];

		});

		api.saveOption('userjs-twl-pages', JSON.stringify(opt));

	});

}



function addWatchlistAlerts() {

	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));

	if (!opt) {

		return;

	}

	var threshold = moment().add(parseDuration(window.TWatch_Alert_period || '3 days'));

	$('.mw-changeslist-title').each(function() {

		var page = this.textContent;

		if (optpage && moment(optpage]).isBefore(threshold)) {

			var $container = $(this).parent().parent().parent(); // li element

			if ($container.find('.twatch-expiry-alert').length === 0) {

				var exptext = moment(optpage]).fromNow();

				$('<span>')

					.text('[expires ' + exptext + ']')

					.attr('title', 'This page will be removed from your watchlist around ' + getString(optpage], true))

					.addClass('twatch-expiry-alert')

					.css({

						'font-size': '80%',

						'padding-left': '5px',

						'color': 'brown'

					}).appendTo($container);

			}

		}

	});

}



/**

 * @param {String} str - a string specifying duration - eg. "3 weeks", "2 months"

 * @returns {moment.duration} - moment Duration object

 */

function parseDuration(str) {

	var i;

	for (i = 0; i < str.length; i++) {

		if (stri < '0' || stri > '9') {

			break;

		}

	}

	var num = parseInt(str);

	var text = str.slice(i).trim();

	var momentObject = moment.duration(num, text);

	if (!momentObject._isValid || momentObject.asMilliseconds() === 0) {

		console.error('Invalid duration string: "' + str + '"');

	}

	return momentObject;

}



function hookEventListener() {

	mw.hook('record_watch').add(function(arg) {

		if (!arg) arg = {};

		arg.page = arg.page || mw.config.get('wgPageName');

		arg.setting = arg.setting || 'preferences'; // allows input like window.ScriptNameWatchPref

		arg.duration = arg.duration || window.tempWatchlistDefaultDuration || 'inf';

		arg.action; // 'edit', 'create', 'upload', 'move', 'delete', 'rollback'



		if (arg.setting === 'watch' || arg.setting === true) {

			if (arg.duration !== 'inf')

				recordAsWatching(arg.page, arg.duration);

			api.watch(arg.page); // client script should do this ideally, but just in case...

		} else if (arg.setting === 'preferences') {  // consult user's site preferences

			var pref;

			switch (arg.action) {

				case 'create': pref = 'watchcreations'; break;

				case 'move': pref = 'watchmoves'; break;

				case 'delete': pref = 'watchdeletions'; break;

				case 'upload': pref = 'watchuploads'; break;

				case 'rollback': pref = 'watchrollbacks'; break;

				default: pref = 'watchdefault';

			}

			if (mw.user.options.get(pref) == 1) { // dunno whether its string or number

				if (arg.duration !== 'inf')

					recordAsWatching(arg.page, arg.duration);

				api.watch(arg.page);

			}

		}

	});

}



function buildSpecialPage() {

	$('#firstHeading').text('Temporarily watched pages');

	document.title = 'Temporarily watched pages';

	$('#mw-content-text').empty();



	var opt = JSON.parse(mw.user.options.get('userjs-twl-pages'));



	var $ul = $('<ul>');

	$.each(opt, function(page, expiry) {

		$ul.append(

			$('<li>').html(

				'<a href="' + mw.util.getUrl(page) + '" title="' + page + '">'+ page + '</a>: ' +

				getString(expiry)

			)

		);

	});

	$('#mw-content-text').append(

		$('<p>').text('The following pages are set to be automatically unwatched after the given time in ' + getTimeZoneString() + ' time zone:'),

		$('<p>').html('This list may include any pages that you may have subsequently unwatched manually, <a id="purgeunwatchedpages">click here to purge such pages</a>.'),

		$ul

	);

	$('#purgeunwatchedpages').click(function() {



		$ul.replaceWith('Purging...');

		var arrayOfPages = Object.keys(opt); // ASSUME < 50 for now

		if (arrayOfPages.length > 50) {

			alert('You have more than 50 pages here: purge feature coming soon');

			return;

		}

		api.get({

			"action": "query",

			"format": "json",

			"prop": "info",

			"titles": arrayOfPages,

			"inprop": "watched"

		}).then(function(json) {

			Object.values(json.query.pages).forEach(function(info) {

				if (info.watched === undefined) {

					delete optinfo.title];

				}

			});

			opt = JSON.stringify(opt);

			api.saveOption('userjs-twl-pages', opt).then(function() {

				mw.user.options.set('userjs-twl-pages', opt);

				buildSpecialPage();

			});

		});





		// var arrayOfArrays = arrayChunk(arrayOfPages, 50);

		// arrayOfArrays.forEach(function(array) {

		// 	api.get({

		// 		"action": "query",

		// 		"format": "json",

		// 		"prop": "info",

		// 		"titles": array,

		// 		"inprop": "watched"

		// 	}).then(function(json) {

		// 		Object.values(json.query.pages).forEach(function(info) {

		// 			if (info.watched === undefined) {

		// 				delete opt[info.title.replace(/ /g, '_')];

		// 			}

		// 		});

		// 	});

		// });



	});

}



// HELPER FUNCTIONS:



/**

 * @param {number} date - milliseconds since epoch

 */

function getString(date, withzone) {

	return moment(date).utcOffset(getUserTimeZone()).format('HH:mm, D MMMM YYYY') +

	(withzone ? (' (' + getTimeZoneString() + ').') : '');

}



function getUserTimeZone() {

	if (window.userTimeZone) { // cache it

		return window.userTimeZone;

	}

	var pref = mw.user.options.get('timecorrection');

	if (pref.indexOf('ZoneInfo|') === 0) {

		window.userTimeZone = parseInt(pref.slice('ZoneInfo|'.length));

	} else if (pref.indexOf('Offset|') === 0) {

		window.userTimeZone = parseInt(pref.slice('Offset|'.length));

	} else if (pref === 'System|0') {

		window.userTimeZone = 0;

	} else {

		console.error('[W-Ping]: unparsable time zone: ' + pref);

	}

	return window.userTimeZone;

}



function getTimeZoneString(timecorrection) {

	timecorrection = timecorrection || getUserTimeZone();

	var negative = false;

	if (timecorrection < 0) {

		timecorrection = -timecorrection;

		negative = true;

	}

	var hourCorrection = parseInt(timecorrection/60);

	hourCorrection = (hourCorrection < 10 ? '0' : '') + hourCorrection.toString();



	var minuteCorrection = timecorrection % 60;

	minuteCorrection = (minuteCorrection < 10 ? '0' : '') + minuteCorrection.toString();



	return 'UTC' + (negative ? '–' : '+') + hourCorrection + minuteCorrection;

}



// function arrayChunk(arr, size) {

// 	var result = [];

// 	var current;

// 	for (var i = 0; i < arr.length; ++i) {

// 		if (i % size === 0) { // when 'i' is 0, this is always true, so we start by creating one.

// 			current = [];

// 			result.push(current);

// 		}

// 		current.push(arr[i]);

// 	}

// 	return result;

// }



// </nowiki>

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook