User:MusikAnimal/customWatchlists-sandbox.js

(function {	$("head").append(importStylesheet("User:MusikAnimal/customWatchlists.css"));	var addCwLinkListener = function {		$(".cw-add").click(function { if($("#cw-overlay")[0]) return false; var pageName = new mw.Title($(this).siblings(".mw-title").text); pageName = pageName.getNamespacePrefix+pageName.getMain; getCustomWatchlists.then(setupCactionInterface.bind(this, pageName),setupCactionInterface.bind(this, null)); });	};	var getCustomWatchlists = function {		return Promise.resolve($.get("/wiki/User:"+wgUserName+"/watchlists?action=raw"));	};	var formatDate = function(dateObj) {		// TODO: replace monthNames with wgMonthNames		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 mwName = new mw.Title(data.title);		var pageUrl = "/w/index.php?title="+mwName.getNamespacePrefix+mwName.getMain.replace(/'/g, "%27"),			editDate = new Date(data.timestamp);		if(data.newlen) {			var lengthDiff = data.newlen - data.oldlen;			var diffClass = lengthDiff >= 0 ? "mw-plusminus-pos" : "mw-plusminus-neg"; }		return "" + "("+				"diff | " +				"hist | " +				"cw" +			") " + " . . " +			" "+formatDate(editDate)+" " + " "+data.title+" " + (data.newlen ? " . . ("+(lengthDiff > 0 ? "+" : "")+lengthDiff+") " : "") + " . . " +			""+data.user+" " + "(talk | contribs)" + (data.parsedcomment ? " (" + data.parsedcomment + ") " : "") + "</li>"; };	var showCustomWatchlist = function(type,lists,target,limit,allrev) { var apiRoot = "/w/api.php?action=query"; var pages = JSON.parse(JSON.stringify(lists[target])); var pagesLength = pages.length; for(var i=0; i<pagesLength; i++) { var mwPageName = new mw.Title(pages[i]); if(mwPageName.namespace % 2 === 0) { pages.push(mwPageName.getNamespacePrefix.slice(0,-1) + (mwPageName.namespace === 0 ? "Talk:" : "_talk:") + mwPageName.getMain); }		}		$(".mw-changeslist").html("Loading..."); var newHtml = ""; if(type === "rc") { $.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.getMain) >= 0; });				for(var i=0; i<matches.length; i++) {					newHtml += generateListItem(matches[i]);				}				$(".mw-changeslist").html(newHtml);				addCwLinkListener;				mw.hook( 'wikipage.content' ).fire($('.mw-changeslist'));			}); } else { var queryablePages = $.map(pages,function(p,i){return encodeURIComponent(p).replace(/'/g, "%27")}).join("|"); $.get(apiRoot+"&prop=revisions&rvprop=ids|timestamp|user|parsedcomment&titles="+queryablePages+"&format=json", function(data) {				var sortedData = [];				for(var pageId in data.query.pages) {					if(parseInt(pageId) > 0) {						var pageData = data.query.pages[pageId];						sortedData.push({ parsedcomment : pageData.revisions[0].parsedcomment, revid: pageData.revisions[0].revid, timestamp: pageData.revisions[0].timestamp, title: pageData.title, user: pageData.revisions[0].user });					}				}				$.each(sortedData.sort(function(x,y) {					if($("#cw-rw-options input:checked").val === "timestamp") {						return new Date(y.timestamp).getTime - new Date(x.timestamp).getTime;					} else {						return x.title.localeCompare(y.title);					}				}), function(i,v) { newHtml += generateListItem(v); });				$(".mw-changeslist").html(newHtml);				addCwLinkListener;				mw.hook( 'wikipage.content' ).fire($('.mw-changeslist'));			}); }	};	var showCustomWatchlistsForm = function(appendHtml) { var html = "<form id='custom_watchlist_form'> " + " Custom watchlists (<a href='//en.wikipedia.org/w/index.php?title=User:MusikAnimal/customWatchlists'>documentation</a>) " + appendHtml; $("#mw-watchlist-form").after(html); };	var setupCactionInterface = function(data, argName) { if(argName) { pageName = data; data = argName; } else { pageName = wgPageName; }		var customWatchlists = data ? JSON.parse(data.split("\n")[0]) : {}; var customWatchlistNames = Object.keys(customWatchlists), inWatchlists = []; for(var wl in customWatchlists) { if(customWatchlists[wl].indexOf(pageName.replace("_talk:",":").replace("Talk:","")) !== -1) { inWatchlists.push(wl); }		}		var html = " " + " " +				"Add/remove page to custom watchlists" + "<span class='closer-x' onclick=\"$('#cw-overlay').remove;\"> " + " " +			" " +				(argName ? "<p style='margin-top:0'>Page name: "+pageName.replace(/_/g, " ")+" " : ""); for(var i=0; i < customWatchlistNames.length; i++) { var listName = customWatchlistNames[i]; html += " <input class='cw-option' type='checkbox' value='"+i+"' "+(inWatchlists.indexOf(listName) !== -1 ? "checked data-index='"+customWatchlists[listName].indexOf(pageName)+"'" : "")+" id='cw-option-"+i+"' /><label for='cw-option-"+i+"'>"+listName+" (<a class='cw-delete' href='javascript:' data-id='"+i+"'>del</a>) "; }		html += " " + "<input class='cw-option' type='checkbox' value='-1' id='cw-new-option' "+(data ? "" : "checked")+" /><label for='cw-new-option'>New watchlist " + "<input type='text' id='cw-overlay-new-watchlist-input' placeholder='Enter watchlist name' "+(data ? "" : "style='display:inline-block'")+" />" + " <button id='cw-overlay-selector-submit'>Save changes "; $("body").append(html); if(!data) $("#cw-overlay-new-watchlist-input").focus; $("#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,			pageName : pageName		}, function(e) {			$("#cw-overlay-selector-submit").replaceWith("Saving...");			var cw = e.data.customWatchlists,				iw = e.data.inWatchlists,				pageName = e.data.pageName.replace("_talk:",":").replace("Talk:",":"),				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 "+key+".";						delete cw[key];					} else {						toWatch = true;						if(id < 0) {							updateStr = "Created the custom watchlist "+key+" with "+pageName+"";							cw[key] = [pageName];						} else {							updateStr = "Added "+pageName+" to the custom watchlist "+key+"";							cw[key].push(pageName);						}					}				} else if(exists) {					updateStr = "Removed "+pageName+" from the custom watchlist "+key+"";					cw[key].splice($(this).data('index'),1);				}			}); var stringifiedCw = JSON.stringify(cw)+"\nBacklink: User:MusikAnimal/customWatchlists";

var api = new mw.Api; api.watch(pageName).done(function(watchResult) {				api.postWithToken( "edit", { action: "edit", title: "User:"+wgUserName+"/watchlists", summary: "updating custom watchlists", text: stringifiedCw }).done(function(result, jqXHR) { $("#cw-overlay-body").html("Success!"); mw.notify($(" "+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 = " <label for='custom_watchlist_selector'>Custom list: <select id='custom_watchlist_selector'>";

for(var i=0; i < customWatchlistNames.length; i++) { var listName = customWatchlistNames[i]; html += "<option value='"+i+"'>"+listName+" "; }			html += " "+ "<p id='cw-list-type'>Show: <input type='radio' name='cw-display-type' value='rc' checked /> Recent changes <input type='radio' name='cw-display-type' value='rw' /> Raw watchlist " + "<p id='cw-rw-options' style='display:none'>Sorting: <input type='radio' name='cw-rw-sorting' value='timestamp' checked /> Last edited <input type='radio' name='cw-rw-sorting' value='title' />Alphabetical " + "<p id='cw-rc-options'><label for='custom_watchlist_limit'>Search limit (from base watchlist): <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]+" "; }

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

showCustomWatchlistsForm(html); $("#custom_watchlist_submit").click(function(e) {				e.preventDefault;				showCustomWatchlist($("#cw-list-type input[type=radio]:checked").val,customWatchlists,customWatchlistNames[parseInt($("#custom_watchlist_selector").val)],$("#custom_watchlist_limit").val,$("#custom_watchlist_all_rev").is(":checked"));			}); $("#custom_watchlist_form input[type=radio]").click(function {				if($(this).val === "rc") {					$("#cw-rc-options").show;					$("#cw-rw-options").hide;				} else {					$("#cw-rc-options").hide;					$("#cw-rw-options").show;				}			}); }, function { showCustomWatchlistsForm(" 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. "); });		$(".mw-changeslist .special li").each(function { $anchor = $(this).find("a").eq(1); if($anchor.text === "hist" && !$anchor.siblings(".wikibase-edit").length) { $anchor.after(" | <a class='cw-add' href='javascript:'>cw</a>"); }		});		addCwLinkListener;	} 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, null)); });	} });