/* small library for MW API requests */
var wgServerTime
var apl = new function(){
mw.loader.using('mediawiki.util').done(function () {
//initialization
mw.util.addCSS('span.sort {display:none}')
});
//-------------------API
var queryType =
{rc:'list=recentchanges'
,uc:'list=usercontribs'
,ap:'list=allpages'
,rv:'prop=revisions'
,le:'list=logevents'
}
// Usage: var myQ = new simpleQuery('rc', {limit:20}, myFunc)
// then myQ.call(); ... if (myQ.isMore) myQ.call(50)
this.simpleQuery = function(tp, params, cbfunc){
var shortName = tp // 'rc'
var longName = queryType[shortName].split('=')[1] // 'recentcontribs'
var url = mw.config.get('wgScriptPath')+'/api.php?action=query&format=json&rawcontinue=&' + queryType[shortName]
var request = {}, callback = cbfunc, next
for (var k in params) addParam(k, params[k])
this.isMore = false
function addParam(key, val){
if (!/titles|pageids|revids|redirects|indexpageids|requestid/.test(key))
key = shortName + key
request[key] = val
}
this.call = function(params){
if (typeof params == 'number') request[shortName+'limit'] = params
else if (typeof params == 'object') for (var k in params) addParam(k, params[k])
$.getJSON(url, $.extend({}, request, next), recv)
}
this.isMore = function() {
return next
}
var recv = function(data, textStatus, jqXHR){
updateServerTime(jqXHR)
//save continue values
if (next = data['query-continue']) next = next[longName]
if (!data.query) return dispMsg('Server returned empty data')
callback(data.query[longName], data)
}
}
this.queryAPI = function(req, callback){
$.getJSON(
mw.config.get('wgScriptPath')+'/api.php?action=query&rawcontinue=&format=json',
req,
function(resp, status, xhr){
updateServerTime(xhr)
callback(resp)
}
)
}
this.updateServerTime = updateServerTime = function(xhr){
if (xhr) wgServerTime = new Date( xhr.getResponseHeader('Date') )
}
this.parseTimestamp = parseTS
this.getChild = function(obj, path){ //example: getSomeChild( data , 'query.pages..somekey' )
path = path.split('.')
for( var i=0; i<path.length; i++ ){
var key = path[i]
if( key == '' ) for (key in obj) break //get any child
if( obj ) obj = obj[key]
}
return obj
}
//---------------------------- HTML OUTPUT
this.toggleCSS = (function (){ //example: toggleCSS( 'p{display:none}', true )
var sheet = {}
return function(css, isOn){
mw.loader.using('mediawiki.util').done(function () {
if (!sheet[css]) sheet[css] = mw.util.addCSS(css)
sheet[css].disabled = ! isOn
});
}
})()
this.spinner = function (el){
if (el)
$(el).append('<img class=spinner style="margin-left:1em" src="'
+ stylepath +'/common/images/spinner.gif" alt="..." title="..." />')
else
$('img.spinner').remove()
}
this.checkbox = function (name, id, val, txt){
return '<input type=checkbox name='+name+' id='+id + ' value="'+val+'">'
+ '<label for='+id+'>' + txt + '</label>'
}
this.icon = function(src, size, attr){ //returns <img ...> from Commons
if( size ) src = 'thumb/'+src+'/'+size+'px-'+src.split('/')[2] //+'.png' //for svg: not needed?
return '<img src="http://upload.wikimedia.org/wikipedia/commons/'
+ src + '" ' + (attr||'')+'>'
}
this.output = function (val, type){
switch ( type ){
case 'title': return this.outputPage(val, simplifyTitle(val) )
case 'user': return this.outputPage('Special:Contributions/'+val, val)
case 'touched':
case 'timestamp': return inHours( wgServerTime - parseTS(val) )
case 'hours': return inHours(val)
//case 'size': case 'oldlen': case 'newlen':
default:
return val
}
}
this.outputPage = function (page, name){
name = name || page
if (name.length > 40) name = name.substr(0, 37) + '…'
var tip = ''
if (page != name) tip = ' title="'+page.replace(/"/g,'"') + '"'
page = encodeURI(page.replace(/ /g,'_')).replace(/\?/g,'%3F')
// could use encodeURIComponent(page).replace(/%2F/g,'/') ?
return '<a href="' + mw.config.get('wgArticlePath').replace('$1', '') + page + '"'
+ tip + '>'+name+'</a>'
}
this.outputLink = function (link, name){
return '<a href="' + mw.config.get('wgScript') + '?' + link + '">'+name+'</a>'
}
this.outputCell = function (val, key, attr){
var a1 = '', a2 = '', clss = key
attr = attr || ''
if( typeof val == 'object' ){
if( key == 'title' && typeof val.redirect == 'string' ) clss += ' redirect'
val = val[key]
}
if ( key == 'timestamp'){ //handle timestamp
attr += ' title="' + val + '"'
a1 = '<span class=sort>' + val + '</span><span class=hours>'
a2 = '</span>'
}
return '<td class="' + clss + '"' + attr + '>' + a1 + this.output( val, key ) + a2
}
this.makeAPITimestamp = function(d){ //date -> 2008-01-26T06:34:19Z
return d.getUTCFullYear() + '-'
+ pad0(d.getUTCMonth()+1) + '-'
+ pad0(d.getUTCDate()) + 'T'
+ pad0(d.getUTCHours()) + ':'
+ pad0(d.getUTCMinutes()) + ':'
+ pad0(d.getUTCSeconds()) + 'Z'
}
//----------- AUX Functions
function pad0(v, len){ // 6 -> '06'
len = len || 2
v = v.toString()
while (v.length < len) v = '0'+v
return v
}
function diffSize(n){
return '<span class='
+ 'mw-plusminus-'+ (n>0 ? 'pos' : (n<0?'neg':'null'))
+ (n < - 500 ? ' style="font-weight:bold"' : '')
+ '>' + n.toString() + '</span>'
}
function inHours(ms){ //milliseconds -> "2:30" or 5,06 or 21
var mm = Math.floor(ms/60000)
if( !mm ) return '<small>'+Math.floor(ms/1000)+'s</small>'
var hh = Math.floor(mm/60); mm = mm % 60
var dd = Math.floor(hh/24); hh = hh % 24
if (dd) return dd + (dd<10?'<small>,'+pad0(hh)+'</small>':'')
else return '<small>'+hh + ':' + pad0(mm)+'</small>'
}
//20081226220605 or 2008-01-26T06:34:19Z -> date
function parseTS(ts){
var m = ts.replace(/\D/g,'').match(/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/)
return new Date ( Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]) )
}
function simplifyTitle(ttl){
for (var tt in simplerTitles)
if ( ttl.substring (0, tt.length) == tt )
ttl = simplerTitles[ tt ] + ttl.substring(tt.length)
return ttl
}
//---------- Per Project
// enwiki
var simplerTitles =
{'Wikipedia:' :'WP:'
,'Wikipedia talk:':'WT:'
}
// ruwiki
var simplerTitles =
{'Википедия:Проект:Инкубатор/Статьи/': '::'
,'Обсуждение Википедии:': 'ОВ:'
,'Википедия:':'ВП:'
}
}//library