MediaWiki:Gadget-ajaxrecentchanges.js

来自工场百科
Yuanxing14留言 | 贡献2015年2月6日 (五) 15:52的版本 (创建页面,内容为“/* Ajax recent changes and patrolling framework, version [0.0.5a] Originally from: http://en.wikipedia.org/wiki/User:Splarka/ajaxrecentchanges.js Note: * Patrol fl...”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:Ctrl-F5
/* Ajax recent changes and patrolling framework, version [0.0.5a]
Originally from: http://en.wikipedia.org/wiki/User:Splarka/ajaxrecentchanges.js
 
Note:
* Patrol flags/links will sometimes show up where patrolling is not enabled.
** This was a bug in the API that generated patrol tokens too often.
** Fixed in http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=49000
 
Todo:
* Checkbox for batch patrolling
 
Wontdo:
* Parse comments
* Add (talk|contribs|block) links, click their name, lazy
* Localize error messages or focus on the log message 'logaction' (wrong tense, but it works fine).
*/
 
if( !window.arc_i18n ) {
	var arc_i18n = { 
		'title' : 'Ajax recent changes',
		'desc' : 'Paginated enhanced ajax recent changes and patrolling.',
		'mypatrol' : 'My patrol log',
		'startstamp' : 'Start timestamp (8601)',
		'limit' : 'Limit',
		'showapb' : 'Show ajax patrol buttons',
		'filterflag' : 'Filter by flag',
		'minor' : 'Minor',
		'bot' : 'Bot',
		'anon' : 'Anon',
		'redirect' : 'Redirect',
		'patrolled' : 'Patrolled',
		'all' : 'All',
		'filtertype' : 'Filter by type',
		'edit' : 'Edits',
		'new' : 'New pages',
		'log' : 'Logs',
		'filterns' : 'Filter by namespace',
		'fetch' : 'Fetch',
		'noresults' : 'Nothing found.',
		'diff' : 'diff',
		'hist' : 'hist',
		'patrolbtn' : 'Patrol',
		'logsuffix' : ' log',
		'patroldone' : 'done',
		'nsmain' : 'MAIN'
	}
}
 
$(function() {
	mw.util.addPortletLink( 'p-tb', '/wiki/Special:BlankPage?blankspecial=ajaxrc', arc_i18n['title'], 't-ajax-rc', arc_i18n['desc'] );
});
 
if( wgCanonicalSpecialPageName && wgCanonicalSpecialPageName.toLowerCase() == 'blankpage' && queryString( 'blankspecial' ) == 'ajaxrc' ) {
	document.title = arc_i18n['title'];
	addOnloadHook( ajaxRcForm );
}
 
function ajaxRcForm() {
	addPortletLink( 'p-tb', '/wiki/Special:Log/patrol?user=' + encodeURIComponent( wgUserName ), arc_i18n['mypatrol'] );
	// subvert this Special: page to our own needs.
	var con = document.getElementById( 'content' ) || document.getElementById( 'mw_content' );
	var bcon = document.getElementById( 'bodyContent' ) || document.getElementById( 'mw_contentholder' );
	var fh = getElementsByClassName( con, 'h1', 'firstHeading' )[0];
	while( fh.firstChild ) {
		fh.removeChild( fh.firstChild );
	}
	fh.appendChild( document.createTextNode( arc_i18n['title'] ) );
	for( var i = 0; i < bcon.childNodes.length; i++ ) {
		bcur = bcon.childNodes[i];
		if( bcur.id != 'siteSub' && bcur.id != 'contentSub' && bcur.className != 'visualClear') {
			while( bcur.firstChild ) {
				bcur.removeChild( bcur.firstChild );
			}
			if( bcur.nodeType == 3 ) {
				bcur.nodeValue = '';
			}
		}
	}
 
	appendCSS(
		'#arc-form {border:1px solid black;padding:.5em;margin:2em;} #arc-out {border:1px solid black;padding:.5em;margin:.5em;}' +
		'#arc-fetch {padding:0 1em;margin:0 .5em;} .clear {clear:both;} .arc-box {border:1px solid #bbbbbb;padding:.2em;margin:.5em;}' +
		'.arc-cbox {display:block;float:left;width:11em;white-space:nowrap;overflow:hidden;font-size:80%;margin:0 .f2em;}' +
		'.arc-box-label {text-align:center;border-bottom:1px solid #bbbbbb;margin-bottom:.3em} .spacer {border:1px solid transparent;margin-right:.5em;}' +
		'.arc-patrol {border:2px outset #bbbbbb;background-color:#bbbbbb;color:black;padding:2px;margin:3px;text-decoration:none;}'
	);
 
	var form = '<form id="arc-form" action="javascript:void(0)">' +
		'<label for="arc-start">' + arc_i18n['startstamp'] + ':</label> <input type="text" name="arc-start" id="arc-start" value="" size="25" maxlength="20"/><span class="spacer"></span>' +
		'<label for="arc-limit">' + arc_i18n['limit'] + ':</label> <input type="text" name="arc-limit" id="arc-limit" value="50" size="5" maxlength="3"/><span class="spacer"></span>' +
		'<input type="checkbox" name="arc-patrol-enable" id="arc-patrol-enable" /><label for="arc-patrol-enable">' + arc_i18n['showapb'] + '</label><br />' +
		'<div class="arc-box" id="arc-f-boxen">' + arc_i18n['filterflag'] + ': <span class="spacer"></span>' +
		'<label for="arc-f-minor">' + arc_i18n['minor'] + ':</label> <input type="button" name="arc-f-minor" id="arc-f-minor" value="' + arc_i18n['all'] + '" onclick="ajaxRcFlagChange(this)" /><span class="spacer"></span>' +
		'<label for="arc-f-bot">' + arc_i18n['bot'] + ':</label> <input type="button" name="arc-f-bot" id="arc-f-bot" value="!bot" onclick="ajaxRcFlagChange(this)" /><span class="spacer"></span>' +
		'<label for="arc-f-anon">' + arc_i18n['anon'] + ':</label> <input type="button" name="arc-f-anon" id="arc-f-anon" value="' + arc_i18n['all'] + '" onclick="ajaxRcFlagChange(this)" /><span class="spacer"></span>' +
		'<label for="arc-f-redirect">' + arc_i18n['redirect'] + ':</label> <input type="button" name="arc-f-redirect" id="arc-f-redirect" value="' + arc_i18n['all'] + '" onclick="ajaxRcFlagChange(this)" /><span class="spacer"></span>' +
		'<label for="arc-f-patrolled">' + arc_i18n['patrolled'] + ':</label> <input type="button" name="arc-f-patrolled" id="arc-f-patrolled" value="' + arc_i18n['all'] + '" onclick="ajaxRcFlagChange(this)" />' +
		'</div>' +
		'<div class="arc-box" id="arc-t-boxen">' + arc_i18n['filtertype'] + ': <span class="spacer"></span>' +
		'<input type="checkbox" name="arc-t-edit" id="arc-t-edit" checked="checked" value="edit" /><label for="arc-t-edit">' + arc_i18n['edit'] + '</label><span class="spacer"></span>' +
		'<input type="checkbox" name="arc-t-new" id="arc-t-new" checked="checked" value="new" /><label for="arc-t-new">' + arc_i18n['new'] + '</label><span class="spacer"></span>' +
		'<input type="checkbox" name="arc-t-log" id="arc-t-log" checked="checked" value="log" /><label for="arc-t-log">' + arc_i18n['log'] + '</label><span class="spacer"></span>' +
		'</div>' +
		'<div class="arc-box" id="arc-ns-boxen"><div class="arc-box-label">' + arc_i18n['filterns'] + '</div></div>' +
		'' +
		'<input type="button" name="fetch" value="' + arc_i18n['fetch'] + '" id="arc-fetch" onclick="ajaxRcFetch()" /><div class="clear"></div>' +
		'</form>'
 
	bcon.innerHTML += form + '<div id="arc-out"></div>';
	importScriptURI( wgScriptPath + '/api.php?action=query&meta=siteinfo&siprop=namespaces&format=json&callback=ajaxRcFormNamespacesCB&smaxage=2678400&maxage=2678400' );
}
 
function ajaxRcFetch( timestamp, direction ) {
	document.getElementById( 'arc-fetch' ).setAttribute( 'disabled', 'disabled' );
	var nav = document.getElementById( 'arc-fetchnav' );
	if( nav ) {
		nav.style.visibility = 'hidden';
	}
	injectSpinner( document.getElementById( 'arc-fetch' ), 'arc-spin' );
 
	// direction
	var rcdir = '';
	if( direction ) {
		rcdir = '&rcdir=' + direction + '&requestid=' + direction;
	}

	// start
	var rcstart = timestamp || document.getElementById( 'arc-start' ).value;
	rcstart = rcstart.replace( /[^\d]*/g, '' );
	if( rcstart != '' && /^\d{14}$/.test( rcstart ) ) {
		rcstart = '&rcstart=' + rcstart;
	} else {
		rcstart = '';
	}
 
	// limit
	var rclimit = parseInt( document.getElementById( 'arc-limit' ).value );
	if( isNaN( rclimit ) ) {
		rclimit = 100;
	}
	rclimit = '&rclimit=' + rclimit;
 
	// type
	var tb = document.getElementById( 'arc-t-boxen' ).getElementsByTagName( 'input' );
	var rctype = [];
	for( var i = 0; i < tb.length; i++ ) {
		if( tb[i].checked ) {
			rctype.push( tb[i].value );
		}
	}
	if( rctype.length > 0 ) {
		rctype = '&rctype=' + rctype.join( '|' );
	} else {
		rctype = '';
	}
 
	//show (flags)
	var fb = document.getElementById( 'arc-f-boxen' ).getElementsByTagName( 'input' );
	var rcshow = [];
	for( var i = 0; i < fb.length; i++ ) {
		if( fb[i].value != arc_i18n['all'] ) {
			rcshow.push( fb[i].value );
		}
	}
	if( rcshow.length > 0 ) {
		rcshow = '&rcshow=' + rcshow.join( '|' );
	} else {
		rcshow = '';
	}
 
	// namespace
	var nsb = document.getElementById( 'arc-ns-boxen' ).getElementsByTagName( 'input' );
	var rcnamespace = [];
	for( var i = 0; i < nsb.length; i++ ) {
		if( nsb[i].checked ) {
			rcnamespace.push( nsb[i].value );
		}
	}
	if( rcnamespace.length > 0) {
		rcnamespace = '&rcnamespace=' + rcnamespace.join('|');
	} else {
		rcnamespace = '';
	}
 
	// prop & token
	var rcprop = '&rcprop=user|comment|flags|timestamp|title|ids|sizes|redirect|patrolled|loginfo';
	var rctoken = '&rctoken=patrol';
 
	var url = wgScriptPath + '/api.php?action=query&format=json&list=recentchanges' + rcdir + rcstart + rclimit + rctype + rcshow + rcnamespace + rcprop + rctoken;
	var req = sajax_init_object();
	req.open( 'GET', url, true );
	req.onreadystatechange = function() {
		if( req.readyState == 4 && req.status == 200 ) {
			eval( "ajaxRcFetchHandler(" + req.responseText + ",'" + req.responseText.replace(/\'/g, "`") + "')" );
		}
	}
	req.send( null );
}
 
function ajaxRcFetchHandler( obj, txt ) {
	document.getElementById( 'arc-fetch' ).removeAttribute( 'disabled' );
	removeSpinner( 'arc-spin' );
	var out = document.getElementById( 'arc-out' );
	var ajaxpatrol = document.getElementById( 'arc-patrol-enable' ).checked;
	while( out.firstChild ) {
		out.removeChild( out.firstChild );
	}
	if( obj['error'] ) {
		out.appendChild( document.createTextNode( 'API error: ' + obj['error']['code'] + ' - ' + obj['error']['info'] + '\n' ) );
		return;
	}
	if( !obj['query'] || !obj['query']['recentchanges'] ) {
		out.appendChild(document.createTextNode( 'Unexpected response: ' + txt + '\n'));
		return;
	}
	var rc = obj['query']['recentchanges'];
	if( rc.length == 0 ) {
		out.appendChild( document.createTextNode( arc_i18n['noresults'] ) );
		return;
	}
 
	var backwards = false;
	if( obj['requestid'] && obj['requestid'] == 'newer' ) {
		backwards = true;
	}

	var nav = document.createElement( 'div' );
	nav.setAttribute( 'id', 'arc-fetchnav' );
	if( obj['query-continue'] && obj['query-continue']['recentchanges'] && obj['query-continue']['recentchanges']['rcstart'] ) {
		var rcstart = obj['query-continue']['recentchanges']['rcstart'];
		var rcstartnewer = rcstart;
		var rcstartolder = rcstart;
		if( !backwards ) {
			rcstartnewer = rc[0]['timestamp'];
		} else {
			rcstartolder = rc[0]['timestamp'];
		}
		addLinkChild( nav, 'javascript:ajaxRcFetch("' + rcstartnewer + '","newer")', 'Newer' );
		addText( nav, ' | ');
		addLinkChild( nav, 'javascript:ajaxRcFetch("' + rcstartolder + '","older")', 'Older' );
	} else if( backwards ) {
		addLinkChild( nav, 'javascript:ajaxRcFetch()', 'Older' );
	}
	out.appendChild( nav );
 
	var ul = document.createElement( 'ul' );
	for( var i = 0; i < rc.length; i++ ) {
		var r = rc[i];
		var li = document.createElement( 'li' );
		if( r['type'] == 'edit' ) {
			var rcid = '';
			if( typeof r['patrolled'] == 'undefined' && r['rcid'] && r['patroltoken'] ) {
				rcid = '&rcid=' + r['rcid'];
			}
			addText( li, '(' );
			addLinkChild( li, wgScript + '?oldid=' + r['old_revid'] + '&diff=' + r['revid'] + rcid, arc_i18n['diff'] );
			addText( li, ') (' );
			addLinkChild( li, wgScript + '?curid=' + r['pageid'] + '&action=history', arc_i18n['hist'] );
			addText( li, ') . . ');
			if( typeof r['bot'] != 'undefined' ) {
				addText( li, 'b', 'span', 'bot' );
			}
			if( typeof r['minor'] != 'undefined' ) {
				addText( li, 'm', 'span', 'minor' );
			}
			if( rcid != '' && r['patroltoken'] ) {
				addText( li, '!', 'span', 'unpatrolled' );
			}
			addText( li, ' ' );
			addLinkChild( li, wgScript + '?curid=' + r['pageid'], r['title'] );
			var size = '' + ( parseInt( r['newlen'] ) - parseInt( r['oldlen'] ) );
			if( size.substring( 0, 1 ) != '-' ) {
				size = '+' + size;
			}
			addText( li, '; ' + r['timestamp'].replace(/[TZ]/ig, ' ') + ' . . (' + size + ') . . ' );
			addLinkChild( li, wgScript + '?title=Special:Contributions&target=' + encodeURIComponent( r['user'] ), r['user'] );
			if( r['comment'] ) {
				addText( li, ' (' + r['comment'] + ')', 'i' );
			}
			if( ajaxpatrol == true && rcid != '' && r['patroltoken'] ) {
				addLinkChild( li, 'javascript:ajaxRcDoPatrol("' + r['rcid'] + '","' + encodeURIComponent( encodeURIComponent( r['patroltoken'] ) ) + '")', arc_i18n['patrolbtn'], 'arc-patrol-' + r['rcid'], 'arc-patrol' );
			}
		} else if( r['type'] == 'new' ) {
			var rcid = '';
			if( typeof r['patrolled'] == 'undefined' && r['rcid'] ) {
				rcid = '&rcid=' + r['rcid'];
			}
			addText( li, '(' + arc_i18n['diff'] + ') (' );
			addLinkChild( li, wgScript + '?curid=' + r['pageid'] + '&action=history', arc_i18n['hist'] );
			addText( li, ') . . ' );
			addText( li, 'N', 'span', 'newpage' );
			if( rcid != '' && r['patroltoken'] ) {
				addText( li, '!', 'span', 'unpatrolled' );
			}
			addText( li, ' ' );
			addLinkChild( li, wgScript + '?curid=' + r['pageid'] + rcid,r['title'] );
			addText( li, '; ' + r['timestamp'].replace(/[TZ]/ig, ' ') + ' . . (+' + r['newlen'] + ') . . ' );
			addLinkChild( li, wgScript + '?title=Special:Contributions&target=' + encodeURIComponent( r['user'] ), r['user'] );
			if( r['comment'] ) {
				addText( li, ' (' + r['comment'] + ')', 'i' );
			}
			if( ajaxpatrol == true && rcid != '' && r['patroltoken'] ) {
				addLinkChild( li, 'javascript:ajaxRcDoPatrol("' + r['rcid'] + '","' + encodeURIComponent( encodeURIComponent( r['patroltoken'] ) ) + '")', arc_i18n['patrolbtn'], 'arc-patrol-' + r['rcid'], 'arc-patrol' );
			}
		} else if( r['type'] == 'log' ) {
			addText( li, '(' );
			addLinkChild( li, wgScript + '?title=Special:Log&type=' + r['logtype'], r['logtype'] + arc_i18n['logsuffix'] );
			addText( li, '); ' + r['timestamp'].replace(/[TZ]/ig, ' ') + ' . . ' );
			addLinkChild( li, wgScript + '?title=Special:Contributions&target=' + encodeURIComponent( r['user'] ), r['user'] );
			addText( li,' ' + r['logaction'] + ' ' );
			addLinkChild( li, wgScript + '?title=' + encodeURIComponent( r['title'] ), r['title'] );
			if( r['comment'] ) {
				addText( li, ' (' + r['comment'] + ')', 'i' );
			}
		}
		if( backwards && ul.firstChild ) {
			ul.insertBefore( li, ul.firstChild );
		} else { 
			ul.appendChild( li );
		}
	}
	out.appendChild( ul );
}
 
function ajaxRcDoPatrol( rcid, token ) {
	var params = 'action=patrol&format=json&requestid=' + rcid + '&rcid=' + rcid + '&token=' + token;
	var url = wgScriptPath + '/api.php';
	var req = sajax_init_object();
	req.open( 'POST', url, true );
	req.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );
	req.setRequestHeader( 'Content-length', params.length );
	req.setRequestHeader( 'Connection', 'close' );
	req.onreadystatechange = function() {
		if( req.readyState == 4 && req.status == 200 ) {
			eval( "ajaxRcDidPatrol(" + req.responseText + ",'" + req.responseText.replace(/\'/g, "`") + "')" );
		}
	}
	req.send( params );
}
 
function ajaxRcDidPatrol( obj, txt ) {
	if( !obj['requestid'] ) {
		return;
	}
	if( obj['error'] ) {
		alert( 'API error in patrolling rcid=' + obj['requestid'] + ' : ' + obj['error']['code'] + '\n' + obj['error']['info'] );
		return;
	}
	var button = document.getElementById( 'arc-patrol-' + obj['requestid'] );
	if( !button || !obj['patrol'] ) {
		return;
	}
	button.setAttribute( 'href', 'javascript:alert("(' + arc_i18n['patroldone'] + ')");' );
	addText( button, ' (' + arc_i18n['patroldone'] + ')' );
	//{"requestid":"80879","error":{"code":"permissiondenied","info":"Permission denied"}}
	//{"requestid":"80871","patrol":{"rcid":80871,"ns":2,"title":"Page Title Here"}}
}
 
function ajaxRcFlagChange( obj ) {
	var type = obj.getAttribute( 'id' ).substring( 6 );
	var val = obj.value;
	if( val == type ) {
		obj.value = '!' + type;
	} else if( val == '!' + type ) {
		obj.value = arc_i18n['all'];
	} else {
		obj.value = type;
	}
}
 
function ajaxRcFormNamespacesCB( obj ) {
	if( !obj['query'] || !obj['query']['namespaces'] ) {
		return;
	}
	var ns = obj['query']['namespaces'];
	var nsb = document.getElementById( 'arc-ns-boxen' );
	for( var i in ns ) {
		if( typeof i != 'string' || ns[i]['id'] < 0 ) {
			continue;
		}
		var title = ns[i]['*'];
		if( ns[i]['id'] == '' ) {
			title = arc_i18n['nsmain'];
		}
		var canon = ns[i]['canonical'] || '';
		addCheckboxChild( nsb, 'arc-ns-' + ns[i]['id'], i, false, 'arc-ns-' + ns[i]['id'], title, 'arc-cbox', ns[i]['id'] + ' => ' + canon );
		//nsb.appendChild( document.createElement( 'br' ) );
	}
	var div = nsb.appendChild( document.createElement( 'div' ) );
	div.setAttribute( 'class', 'clear' );
}
 
function queryString( p ) {
	var re = RegExp( '[&?]' + p + '=([^&]*)' );
	var matches;
	if ( matches = re.exec( document.location ) ) {
		try { 
			return decodeURI( matches[1] );
		} catch ( e ) {
		}
	}
	return null;
}
 
function addText( obj, txt, elem, classes ) {
	if( elem ) {
		var e = document.createElement( elem );
		e.appendChild( document.createTextNode( txt ) );
		if( classes ) {
			e.setAttribute( 'class', classes );
		}
		obj.appendChild( e );
		return e;
	} else {
		obj.appendChild( document.createTextNode( txt ) );
	}
}
 
function addLinkChild( obj, href, text, id, classes, title ) {
	if( !obj || !href || !text ) {
		return false;
	}
	var a = document.createElement( 'a' );
	a.setAttribute( 'href', href );
	a.appendChild( document.createTextNode( text ) );
	if( id ) {
		a.setAttribute( 'id', id );
	}
	if( classes ) {
		a.setAttribute( 'class', classes );
	}
	if( title ) {
		a.setAttribute( 'title', title );
	}
	obj.appendChild( a );
	return a;
}
 
function addCheckboxChild( obj, name, value, checked, id, label, classes, title ) {
	if( !obj || !name ) {
		return false;
	}
	var span = document.createElement( 'span' );
	var c = document.createElement( 'input' );
	c.setAttribute( 'name', name );
	c.setAttribute( 'type', 'checkbox');
	if( value ) {
		c.setAttribute( 'value', value );
	}
	if( checked ) {
		c.setAttribute( 'checked', 'checked' );
	}
	if( title ) {
		c.setAttribute( 'title', title );
	}
	span.appendChild( c );
	if( id ) {
		c.setAttribute( 'id', id );
		if( label ) {
			var l = document.createElement( 'label' );
			l.setAttribute( 'for', id );
			l.appendChild( document.createTextNode( label ) );
			if( title ) {
				l.setAttribute( 'title', title );
			}
			span.appendChild( l );
		}
	}
	if( classes ) {
		span.setAttribute( 'class', classes );
	}
	obj.appendChild( span );
	return span;
}