Jump to content

User:Evad37/Watchlist-openUnread.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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.
/* Add any or all of these lines after the importScript line to set various options (the default values are shown):

	var openUnread_maxnum = "10";  // Preset value for max number of pages
	var openUnread_oldest = false; // Preset state of checkbox "oldest first". Set to  true  for checked, or  false  for unchecked
	var openUnread_showAbove = false; // If set to  true  the "Open unread pages" button appears above the above the "Watchlist options" box, instead of below it

*/
mw.loader.using( ['mediawiki.util', 'mediawiki.api'], function () {
$(document).ready( function () {
	if( mw.config.get('wgCanonicalSpecialPageName') != 'Watchlist' ) {
	// only operate in Special: namespace, on Special:Watchlist
	return;
	}

	// Set default options for any that haven't been set
	if ( window.openUnread_maxnum === undefined ) { window.openUnread_maxnum = "10"; }
	if ( window.openUnread_oldest === undefined ) { window.openUnread_oldest = true; }
	if ( window.openUnread_showAbove === undefined ) { window.openUnread_showAbove = false; }	

	//Add a form to open multiple unread pages
	var openUnread_form = '<div id="openUnread-input">'+
		'<button id="openUnread-go">Open unread pages</button> '+
		'(Options: <input type="text" name="openUnread-number" id="openUnread-number" style="width:2em;" value=' + openUnread_maxnum + ' /> pages max / '+
		'<span class="mw-input-with-label"><input name="openUnread-order" id="openUnread-order" type="checkbox">&nbsp;<label for="openUnread-order">oldest first</label></span>'+
		')</div>';
	if (openUnread_showAbove) {
		$("form#mw-watchlist-form").before(openUnread_form);
		$("#openUnread-input").css("margin-top","5px");
		$("fieldset#mw-watchlist-options").css("margin-top", "0");
	} else {
		$("form#mw-watchlist-form").after(openUnread_form + '<hr>');
		$("#openUnread-input").css("margin","5px 0");
		$("fieldset#mw-watchlist-options").css("margin-bottom", "0");
	}

	if (openUnread_oldest) {
		$("#openUnread-order").prop( "checked", "true" );
	}

		//Seen is reused for each button click to account for itmes which have already been opened
	var seen = {};
	var count = 0; // var increment on each button click iteration
	
	
	// Start processing on button click
	$("#openUnread-go").click(function() {
		// get max number from input
		var maxnum = parseInt( $('#openUnread-number').val() );
		if (isNaN(maxnum) || maxnum < 1) {
			msg = "\Error: \"" + $('#openUnread-number').val() + "\" is zero, negative, or not a number";
			mw.notify( msg, { autoHide: false, tag: "WatchlistOpenUnread", title: "Watchlist-openUnread says:" } );
			return;		// error - zero, negative, or not a number
		}
		
		count++;
		
		// get unread title links as array
		var unread = $("li.mw-changeslist-line-watched, table.mw-changeslist-line-watched")
			.find("a.mw-changeslist-title")
			.map(function() {
				return $(this).text();
			})
			.get();

		// reverse order if oldest first option selected
		if ( $('#openUnread-order').prop('checked') ) {
			unread.reverse();
		}
		
		//remove duplicates
		var unique_unread = [];
		var len = unread.length;
		var j = 0;
		for (var i = 0; i < len; i++) {
			var item = unread[i];
			if( !(seen[item] >= count) ) { // because (undefined < number) is false
				seen[item] = count;
				unique_unread[j++] = item;
			}
		}

		// reduce to the max number to open
		if (unique_unread.length > maxnum) {
			unique_unread = unique_unread.slice(0, maxnum);
		}

		// Mark each unique unread item as already seen for the next iterations
		for (var u = 0; u < len; u++) {
			seen[unique_unread[u]] = seen[unique_unread[u]]+1000;
		}

		// Callback for api errors
		apiFailedCallback = function(code, result) {
			var msg = "";
			if ( code === "http" ) {
				msg = "HTTP error: " + result.textStatus; // api_result contains the jqXHR object
			} else if ( code === "ok-but-empty" ) {
				msg = "Error: Got an empty response from the server</i></span>";
			} else {
				msg = "API error: " + code;
			}
			mw.notify( msg, { autoHide: false, tag: "WatchlistOpenUnread", title: "Watchlist-openUnread says:" } );
		};
		
		// Callback for getRevId: get old revision id for diff link
		apiCallback_getRevId = function(result) {
			var page_id = result.query.pageids[0];
			var diff_oldid = result.query.pages[page_id].revisions && result.query.pages[page_id].revisions[1] && result.query.pages[page_id].revisions[1].revid;
			var diff_title = mw.util.wikiUrlencode(result.query.pages[page_id].title);

			if (!diff_oldid) {
				window.open("https:" + mw.config.get('wgServer') + mw.config.get('wgScriptPath') +
				"/index.php?title=" + diff_title, "_blank");
				console.log("Could not find old revision for page "+ result.query.pages[page_id].title);
				return;
			}
			
			window.open("https:" + mw.config.get('wgServer') + mw.config.get('wgScriptPath') +
			"/index.php?title=" + diff_title +"&diff=cur&oldid=" + diff_oldid, "_blank");
		};
		
		// Function to get revision id of a page as of a particular timestamp
		getRevId = function(pageid, timestamp) {
			new mw.Api().get( {
				action: 'query',
				pageids: pageid,
				prop: 'revisions',
				rvprop: 'ids',
				rvstart: timestamp,
				rvlimit: '2',
				indexpageids: 1,
				rawcontinue: ''
			} ).done( apiCallback_getRevId )
			.fail( apiFailedCallback );
		};
		
		// Callback for getTimestamps: get timestamps/pageids to pass through to getRevId function
		apiCallback_getTimestamps = function(result) {
			var page_ids = result.query.pageids;
			for (var k=0; k<page_ids.length; k++) {
				var nts = result.query.pages[ page_ids[k] ].notificationtimestamp;
				getRevId(page_ids[k], nts);
			}
		};
		
		// Function to get timestamps from the api
		getTimestamps = function(pagetitles) {
			new mw.Api().get( {
				action: 'query',
				titles: pagetitles,
				prop: 'info',
				inprop: 'notificationtimestamp',
				indexpageids: 1,
				rawcontinue: ''
			} ).done( apiCallback_getTimestamps )
			.fail( apiFailedCallback );
		};
		
		// Split into lists of 50 (max number for api)
		for (var ii=0; ii<unique_unread.length; ii+=50) {
			getTimestamps(unique_unread.slice(ii, ii+49).join("|"));
		}

		// show pages as read on watchlist
		$("li.mw-changeslist-line-watched, table.mw-changeslist-line-watched")
		.find("a.mw-changeslist-title")
		.filter(":contains('" + unique_unread.join("'), :contains('") + "')")
		.closest(".mw-changeslist-line-watched")
		.removeClass("mw-changeslist-line-watched")
		.addClass("mw-changeslist-line-not-watched");
		
	});

});
});