User:Yair rand/interwikiwatchlist.js

// newNode from wikt:Mediawiki:Common.js, JsMwApi from wikt:WT:EDIT, // interwiki watchlist from wikt:User:Yair rand/superwatchlist.js. To enable, add // importScript ("User:Yair rand/interwikiwatchlist.js"); // to Special:MyPage/common.js. You should see an "Import watchlist" button // in the top-right corner of Special:Watchlist. For more info see the notes at the // top of http://en.wikipedia.org/wiki/User_talk:Yair_rand/interwikiwatchlist.js

function newNode(tagname){ var node = document.createElement(tagname); for( var i=1;i<arguments.length;i++ ){ if(typeof arguments[i] == 'string'){ //Text node.appendChild( document.createTextNode(arguments[i]) ); }else if(typeof arguments[i] == 'object'){ if(arguments[i].nodeName){ //If it is a DOM Node node.appendChild(arguments[i]); }else{ //Attributes (hopefully) for(var j in arguments[i]){ if(j == 'class'){ //Classname different because... node.className = arguments[i][j]; }else if(j == 'style'){ //Style is special node.style.cssText = arguments[i][j]; }else if(typeof arguments[i][j] == 'function'){ //Basic event handlers try{ node.addEventListener(j,arguments[i][j],false); //W3C }catch(e){try{ node.attachEvent('on'+j,arguments[i][j],"Language"); //MSIE }catch(e){ node['on'+j]=arguments[i][j]; }}; //Legacy }else{ node.setAttribute(j,arguments[i][j]); //Normal attributes }       }      }    }  }  return node; }

//JsMwApi documentation is at http://en.wiktionary.org/wiki/User_talk:Conrad.Irwin/Api.js function JsMwApi (api_url, request_type) { if (!api_url) {		if (typeof(true) === 'undefined' || true == false) throw "Local API is not usable."; api_url = mw.config.get('wgScriptPath') + "/api.php"; }	if (!request_type) {		if (api_url.indexOf('http://') == 0 || api_url.indexOf('https://') == 0 || api_url.indexOf('//') == 0) request_type = "remote"; else request_type = "local"; }	function call_api (query, callback) {		if(!query || !callback) throw "Insufficient parameters for API call"; query = serialise_query(query); if(request_type == "remote") request_remote(api_url, query, callback, call_api.on_error || default_on_error); else request_local(api_url, query, callback, call_api.on_error || default_on_error); }	var default_on_error = JsMwApi.prototype.on_error || function (xhr, callback, res) {		if (typeof(console) != 'undefined') console.log([xhr, res]); callback(null); }	function get_xhr {		try{ return new XMLHttpRequest; }catch(e){ try { return new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){ try { return new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){ throw "Could not create an XmlHttpRequest"; }}}	}	function request_local (url, query, callback, on_error) {		var xhr = get_xhr; xhr.open('POST', url + '?format=json', true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(query); xhr.onreadystatechange = function {			if (xhr.readyState == 4) {				var res; if (xhr.status != 200) res = {error: { code: '_badresponse', info: xhr.status + " " + xhr.statusText }};				else {					try {						res = JSON.parse("("+xhr.responseText+")"); }					catch(e) {						res = {error: { code: '_badresult', info: "The server returned an incorrectly formatted response" }};					}				}				if (!res || res.error || res.warnings) on_error(xhr, callback, res); else callback(res); }		}	}	function request_remote (url, query, callback, on_error) {		if(! window.__JsMwApi__counter) window.__JsMwApi__counter = 0; var cbname = '__JsMwApi__callback' + window.__JsMwApi__counter++; window[cbname] = function (res) {			if (res.error || res.warnings) on_error(null, callback, res); else callback(res); }		var script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('src', url + '?format=json&callback=window.' + cbname + '&' + query); document.getElementsByTagName('head')[0].appendChild(script); }	function serialise_query (obj) {		var amp = ""; var out = ""; if (String(obj) === obj) {			out = obj; }		else if (obj instanceof Array) {			for (var i=0; i < obj.length; i++) {				out += amp + serialise_query(obj[i]); amp = (out == '' || out.charAt(out.length-1) == '&') ? '' : '&';			}		}		else if (obj instanceof Object) {			for (var k in obj) {				if (obj[k] === true) out += amp + encodeURIComponent(k) + '=1'; else if (obj[k] === false) continue; else if (obj[k] instanceof Array) out += amp + encodeURIComponent(k) + '=' + encodeURIComponent(obj[k].join('|')); else if (obj[k] instanceof Object) throw "API parameters may not be objects"; else out += amp + encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); amp = '&'; }		}		else if (typeof(obj) !== 'undefined' && obj !== null) {			throw "An API query can only be a string or an object"; }		return out; }	// Make JSON.parse work var JSON = (typeof JSON == 'undefined' ? new Object : JSON); if (typeof JSON.parse != 'function') JSON.parse = function (json) { return eval('(' + json + ')'); }; // Allow .prototype. extensions if (JsMwApi.prototype) {		for (var i in JsMwApi.prototype) {			call_api[i] = JsMwApi.prototype[i]; }	}	return call_api; }

mw.config.get('wgCanonicalSpecialPageName') == "Watchlist" && $(document).ready(function {    var v = document.getElementById("mw-watchlist-options");    if(!v) return    v = v.parentNode.insertBefore(newNode('div'), v.nextSibling)    var opt = JSON.parse(mw.user.options.values['userjs-YRIWW'] || "{}");

function updateOpt( cb ) { $.get( "/w/api.php?format=json&action=query&meta=tokens", function( r ) {       $.post( "/w/api.php?format=json&action=options&change=userjs-YRIWW=" + JSON.stringify( opt ), {token : r.query.tokens.csrftoken }, function { cb && cb; })     })    }    for ( var i in opt ) { ( function( i ) {       var tkn = opt[ i ].token,          project = "//" + i + ".org/";        JsMwApi( project + "w/api.php" )({ action: 'query', list: 'watchlist', wlowner: mw.config.get('wgUserName'), wltoken: tkn, wlexcludeuser: mw.user.options.get('watchlisthideown') ? mw.config.get('wgUserName') : 'Example', wlprop: 'title|flags|user|parsedcomment|timestamp|ids', continue: '' }, function ( r ) { t = r           var b = newNode('ul', {                'style': 'display:' +                ( opt[ i ].hidden ? 'none;' : 'block;' )             }); v.parentNode.insertBefore(b, v.nextSibling); v.parentNode.insertBefore(newNode('h3', project + " watchlist", newNode('span', {                   'style': 'font-size:12px;'                  }, ' [', newNode('a', 'Remove', { style: 'cursor:pointer;', click: function { delete opt[ i ]; updateOpt( function { location.reload; } ); }                   }), '] [', newNode('a', opt[ i ].hidden ? 'Expand ▼' : 'Collapse ▲', { 'style': 'cursor:pointer;', 'click': function { if ( b.style.display == 'none') { b.style.display = 'block'; this.innerHTML = "Collapse ▲"; // todo: replace innerHTML with something more sanitary, hm? opt[ i ].hidden = false; updateOpt; } else { b.style.display = 'none'; this.innerHTML = "Expand ▼"; opt[ i ].hidden = true; }                       updateOpt; }                   }), ']')), v.nextSibling); var g = r.query.watchlist; for (var ii = 0; ii < g.length; ii++) { var zx = newNode('span', {                 class: 'comment'                }), item = g[ ii ]; zx.innerHTML = ' (' + item.parsedcomment.replace(/\ href\=\"\//g, ' href="' + project) + ')'; b.appendChild(newNode('li', '(',                 newNode('a', 'diff', { href: project + "w/index.php?title=" + item.title + "&curid=" + item.pageid + "&diff=" + item.revid }),                 ' | ',                  newNode('a', 'hist', { href: project + "w/index.php?title=" + item.title + "&curid=" + item.pageid + "&action=history" }),                 ') . . ',                  newNode('a', item.title, {                      href: project + "wiki/" + item.title                    }), '; ' + item.timestamp.match(/\d\d\:\d\d/)[0] + '. . ',                 item.user, zx)) }         })      })( i ); }   var qw, er = ['Wikipedia', 'Wiktionary', 'Wikibooks', 'Wikisource', 'Wikiquote', 'Wikiversity', 'Wikinews', 'Wikivoyage', 'Meta-Wiki', 'Commons', 'Wikispecies', 'Mediawiki', 'Wikidata'], domains = ['meta.wikimedia', 'commons.wikimedia', 'species.wikimedia', 'www.mediawiki', 'www.wikidata'], cv, bn, sd; document.getElementById('firstHeading').appendChild(newNode('a', "Import watchlist", { 'style': 'padding-left:10px;cursor:pointer; float:right; font-size: 13px;', click: function { v.innerHTML = ''; v.appendChild(newNode('form', { 'style': 'display: inline;' },               'Language: ', cv = newNode('input', {                    size: 3                  }), ' Project: ', qw = newNode('select'), newNode('br'), 'Watchlist token ', newNode('small', '(can be found be found at ', sd = newNode('a', 'Special:Preferences', {                     'href': '//en.wikipedia.org/wiki/Special:Preferences#mw-prefsection-watchlist'                    }), ' in the Watchlist section)'), ': ', bn = newNode('input'), newNode('input', {                   'type': 'submit',                    'value': 'Import watchlist'                  }), newNode('span', {                    style: 'color:red;'                  }))).onsubmit = function  { if (!/^[a-z]{2,3}(-?[a-z]{2,3})?$/.test(cv.value) && qw.value <= 7 || !bn.value) { bn.parentNode.lastChild.innerHTML = bn.value ? "Choose a valid language code." : "Enter watchlist token." return false }             var importedurl = (qw.value > 7 ? domains[ qw.value - 7 ] : cv.value + '.' + er[qw.value].toLowerCase) opt[ importedurl ] = { 'token' : bn.value }; updateOpt( function{ location.reload; }) return false; }           for (var i = 0; i < er.length; i++) { qw.appendChild(newNode('option', { 'value': i                 }, er[i])) };

function df { if (/^[a-z]{2,3}(-?[a-z]{2,3})?$/.test(cv.value) || qw.value > 7) { sd.href = "//" + (qw.value > 7 ? domains[ qw.value - 7 ] : cv.value + '.' + er[qw.value].toLowerCase) + ".org/wiki/Special:Preferences#mw-prefsection-watchlist"; }           }            cv.onchange = qw.onchange = df; }       }))  })