Jump to content

User:MusikAnimal/customWatchlists.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by MusikAnimal (talk | contribs) at 02:42, 1 December 2014. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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.
(function() {
	$("head").append(importStylesheet("User:MusikAnimal/customWatchlists.css"));
	
	var getCustomWatchlists = function() {
		return Promise.resolve($.get("/wiki/User:"+wgUserName+"/watchlists?action=raw"));
	};
	
	var formatDate = function(dateObj) {
		var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
		return (dateObj.getHours()+100).toString().slice(-2)+":"+(dateObj.getMinutes()+100).toString().slice(-2)+", "+(dateObj.getUTCDate()+100).toString().slice(-2)+" "+monthNames[dateObj.getUTCMonth()]+" "+dateObj.getUTCFullYear();
	};
	
	var generateListItem = function(data) {
		var pageUrl = "/w/index.php?title="+data.title;
		var lengthDiff = data.newlen - data.oldlen;
		var editDate = new Date(data.timestamp);
		var diffClass = lengthDiff >= 0 ? "mw-plusminus-pos" : "mw-plusminus-neg";
		return "<li class='mw-line-even mw-changeslist-line-not-watched'>" +
			"("+
				"<a href='"+pageUrl+"&diff=prev&oldid="+data.revid+"' class='nonimage'>diff</a>&nbsp;| " +
				"<a href='"+pageUrl+"&action=history' class='nonimage'>hist</a>" +
			")&nbsp;" +
			"<span class='mw-changeslist-separator'>. .</span>&nbsp;" +
			"<span class='mw-changeslist-date'>"+formatDate(editDate)+"</span>&nbsp;" +
			"<span class='mw-title'><a href='/wiki/"+encodeURI(data.title).replace(/'/g, "%27")+"' class='mw-changeslist-title nonimage'>"+data.title+"</a></span>&nbsp;" +
			"<span class='mw-changeslist-separator'>. .</span>&nbsp;" +
			"<span dir='ltr' class='"+diffClass+"'>("+(lengthDiff > 0 ? "+" : "")+lengthDiff+")</span> " +
			"<span class='mw-changeslist-separator'>. .</span>&nbsp;" +
			"<a href='/wiki/User:"+data.user+"' class='mw-userlink nonimage'>"+data.user+"</a> " +
			"(<a href='/wiki/User talk:"+data.user+"'>talk</a> | <a href='/wiki/Special:Contributions/"+data.user+"'>contribs</a>)" +
			(data.parsedcomment ? "&nbsp;<span style='font-style:italic'>(" + data.parsedcomment + ")</span>" : "") +
		"</li>";
	};
	
	var showCustomWatchlist = function(lists,target,limit,allrev) {
		var apiRoot = "/w/api.php?action=query";
		var pages = lists[target];
		$(".mw-changeslist").html("Loading...");
		
		var newHtml = "";
		$.get(apiRoot+"&list=watchlist&wlprop=user|parsedcomment|timestamp|sizes|title|ids&wltype=edit&wllimit="+limit+(allrev === true ? "&wlallrev=true" : "")+"&format=json", function(data) {
			var matches = $.grep(data.query.watchlist, function(el){
				var mwName = new mw.Title(el.title);
				return pages.indexOf(mwName.getNamespacePrefix()+mwName.getName()) >= 0;
			});
			for(var i=0; i<matches.length; i++) {
				newHtml += generateListItem(matches[i]);
			}
			$(".mw-changeslist").html(newHtml);
		});
	};
	
	var showCustomWatchlistsForm = function(appendHtml) {
		var html = "<form id='custom_watchlist_form'><fieldset style='margin:20px 0px'>" +
				"<legend>Custom watchlists</legend>" + appendHtml;
		$("#mw-watchlist-form").after(html);
	};
	
	var setupCactionInterface = function(data) {
		var customWatchlists = data ? JSON.parse(data.split("\n")[0]) : {};
		var customWatchlistNames = Object.keys(customWatchlists),
			inWatchlists = [];
		
		for(var wl in customWatchlists) {
			if(customWatchlists[wl].indexOf(wgPageName) !== -1) {
				inWatchlists.push(wl);
			}
		}
		
		var html = "<div id='cw-overlay'>" +
			"<div class='header'>" +
				"Add/remove page to custom watchlists" +
				"<span class='closer-x' onclick=\"$('#cw-overlay').remove();\"></span>" +
			"</div>" +
			"<div style='padding:14px' id='cw-overlay-body'>";
		
		for(var i=0; i < customWatchlistNames.length; i++) {
			var listName = customWatchlistNames[i];
			html += "<span><input class='cw-option' type='checkbox' value='"+i+"' "+(inWatchlists.indexOf(listName) !== -1 ? "checked data-index='"+customWatchlists[listName].indexOf(wgPageName)+"'" : "")+" id='cw-option-"+i+"' /><label for='cw-option-"+i+"'>"+listName+"</label> (<a class='cw-delete' href='javascript:' data-id='"+i+"'>del</a>)</span>";
		}
		
		html += "<div id='cw-overlay-new-watchlist' "+(data ? "" : "style='display:block'")+">" +
				"<input class='cw-option' type='checkbox' value='-1' id='cw-new-option' /><label for='cw-new-option'>New watchlist</label>" +
				"<input type='text' id='cw-overlay-new-watchlist-input' placeholder='Enter watchlist name' />" +
			"</div><button id='cw-overlay-selector-submit'>Save changes</button></div></div>";
		
		$("body").append(html);
		
		$("#cw-new-option").change(function() {
			if($(this).is(":checked")) {
				$("#cw-overlay-new-watchlist-input").show().focus();
			} else {
				$("#cw-overlay-new-watchlist-input").hide();
			}
		});
		
		$(".cw-delete").click(function() {
			if($(this).text() === "undel") {
				$("#cw-option-"+$(this).data('id')).prop('checked',false).siblings("label").removeClass("disabled");
				$("#cw-option-"+$(this).data('id')).data('delete',null);
				$(this).text("del");
			} else {
				var name = customWatchlistNames[$(this).data('id')];
				var cwToDelete = customWatchlists[name];
				if(confirm("Mark the watchlist \""+name+"\" and all it's "+cwToDelete.length+" entries for deletion?")) {
					$(this).text("undel");
					$("#cw-option-"+$(this).data('id')).data('delete',true);
					$("#cw-option-"+$(this).data('id')).prop('checked',true).one("click", function() {
						$(this).siblings("a").trigger("click");
					}).siblings("label").addClass("disabled");
				}
			}
		});
		
		$("#cw-overlay-selector-submit").click({
			customWatchlistNames: customWatchlistNames,
			customWatchlists: customWatchlists,
			inWatchlists: inWatchlists
		}, function(e) {
			$("#cw-overlay-selector-submit").replaceWith("Saving...");
			var cw = e.data.customWatchlists,
				iw = e.data.inWatchlists,
				toWatch = false,
				updateStr = "";

			$.each($(".cw-option"), function(i) {
				var id = parseInt($(this).val());
				var key = id < 0 ? $("#cw-overlay-new-watchlist-input").val().replace(/[^\w\s]/gi, '') : customWatchlistNames[id];
				var exists = iw.indexOf(key) >= 0;
				
				if($(this).is(":checked")) {
					if($(this).data("delete")) {
						updateStr = "Deleted the custom watchlist <b>"+key+"</b>.";
						delete cw[key];
					} else {
						toWatch = true;
						if(id < 0) {
							updateStr = "Created the custom watchlist <b>"+key+"</b> with <b>"+wgPageName+"</b>";
							cw[key] = [wgPageName];
						} else {
							updateStr = "Added <b>"+wgPageName+"</b> to the custom watchlist <b>"+key+"</b>";
							cw[key].push(wgPageName);
						}
					}
				} else if(exists) {
					updateStr = "Removed <b>"+wgPageName+"</b> from the custom watchlist <b>"+key+"</b>";
					cw[key].splice($(this).data('index'),1);
				}
			});
			
			var stringifiedCw = JSON.stringify(cw)+"\nBacklink: [[User:MusikAnimal/customWatchlists]]";

			var api = new mw.Api();
			api.watch(wgPageName).done(function(watchResult) {
				api.postWithToken( "edit", {
					action: "edit",
					title: "User:"+wgUserName+"/watchlists",
					summary: "updating [[User:MusikAnimal/customWatchlists|custom watchlists]]",
					text: stringifiedCw
				}).done(function(result, jqXHR) {
					$("#cw-overlay-body").html("Success!");
					mw.notify($("<div>"+updateStr+"</div"));
					setTimeout(function() {
						$("#cw-overlay").remove();
					},3000);
				}).fail(function(code, result) {
					if ( code === "http" ) {
						mw.log( "HTTP error: " + result.textStatus ); // result.xhr contains the jqXHR object
					} else if ( code === "ok-but-empty" ) {
						mw.log( "Got an empty response from the server" );
					} else {
						mw.log( "API error: " + code );
					}
				});
			}).fail(function(code, result) {
				if ( code === "http" ) {
					mw.log( "HTTP error: " + result.textStatus ); // result.xhr contains the jqXHR object
				} else if ( code === "ok-but-empty" ) {
					mw.log( "Got an empty response from the server" );
				} else {
					mw.log( "API error: " + code );
				}
			});
		});
	};
	
	if(wgRelevantPageName === "Special:Watchlist") {
		getCustomWatchlists().then(function(data) {
			var customWatchlists = JSON.parse(data.split("\n")[0]);
			var customWatchlistNames = Object.keys(customWatchlists);
			var html = "<p><label for='custom_watchlist_selector'>Custom list:</label>&nbsp;<select id='custom_watchlist_selector'>";

			for(var i=0; i < customWatchlistNames.length; i++) {
				var listName = customWatchlistNames[i];
				html += "<option value='"+i+"'>"+listName+"</option>";
			}
			
			html += "</select><br/>" +
				"<label for='custom_watchlist_limit'>Search limit (from base watchlist):</label>&nbsp;<select id='custom_watchlist_limit'>";
			var limitArr = [50,100,250,500,1000,2500,5000];
			for(var j=0; j<limitArr.length; j++) {	
				html += "<option val='"+limitArr[j]+"'>"+limitArr[j]+"</option>";
			}

			html += "</select><br/>" +
				"<input type='checkbox' id='custom_watchlist_all_rev' value='wlallrev' /><label for='custom_watchlist_all_rev'>Include multiple revisions to same page</label><br/>" +
				"<button id='custom_watchlist_submit'>Go</button></fieldset></p></form>";

			showCustomWatchlistsForm(html);
			
			$("#custom_watchlist_submit").click(function(e) {
				e.preventDefault();
				showCustomWatchlist(customWatchlists,customWatchlistNames[parseInt($("#custom_watchlist_selector").val())],$("#custom_watchlist_limit").val(),$("#custom_watchlist_all_rev").is(":checked"));
			});
		}, function() {
			showCustomWatchlistsForm("<p>No <a href='https://en.wikipedia.org/wiki/User:MusikAnimal/customWatchlists'>custom watchlists</a> yet! Go to a <a href='/wiki/Special:Random'>page</a> and create a custom watchlist by selecting the \"Custom Watchlists&hellip;\" item from the More menu.</p>");
		});
	} else if(wgNamespaceNumber >= 0) {
		mw.util.addPortletLink(
			'p-cactions',
			'javascript:',
			'Custom watchlist…',
			'ca-add-to-cw'
		);
		$("#ca-add-to-cw").click(function() {
			if($("#cw-overlay")[0]) return false;
			getCustomWatchlists().then(setupCactionInterface,setupCactionInterface.bind(this, null));
		});
	}
}());