Участник:Js/apl01.js

Материал из Википедии — свободной энциклопедии
/* small library for MW API requests */

var apl = new function(){


//initialization
var wgServerTime
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 = 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.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
   obj = obj[key]
 }
 return obj
}





//---------------------------- HTML OUTPUT


this.toggleCSS = (function (){ //example:  toggleCSS( 'p{display:none}', true )
 var sheet = {}
 return function(css, isOn){
   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
 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(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,'&quot;') + '"'
 page = encodeURI(page.replace(/ /g,'_')).replace(/\?/g,'%3F')
 // could use encodeURIComponent(page).replace(/%2F/g,'/')  ?
 return '<a href="' + wgArticlePath.replace('$1', '') + page + '"'
  + tip + '>'+name+'</a>'
}



this.outputCell = function (val, key){
 var attr = '', a1 = '', a2 = '', clss = key
 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
}



//----------- AUX Functions 

function pad0(v, len){ // 6 -> '06'
 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(ts, fromTime){ //timestamp -> "2:30" or 5,06 or 21
 var ms = ( fromTime || wgServerTime ) - parseTS(ts)
 var mm = Math.floor(ms/60000)
 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,2)+'</small>':'')
 else return '<small>'+hh + ':' + pad0(mm,2)+'</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]) )
}





//---------- RU ONLY

var simplerTitles =
{'Википедия:Проект:Инкубатор/Статьи/': 'Инк:'
,'Обсуждение Википедии:': 'ОВ:'
,'Википедия:':'ВП:'
}


function simplifyTitle(ttl){
  for (var tt in simplerTitles)
    if ( ttl.substring (0, tt.length) == tt )
      ttl = simplerTitles[ tt ] + ttl.substring(tt.length)
  return ttl   
}



}//library



 
//add popup to element
$.fn.extend({
 addPopup: function( htm ){
   $(this)
   .data( 'popup', htm )
   .mouseenter ( function(){
      $('#popup').remove()
      var el = $(this)
      var pp = $('<div id=popup style="position:absolute; background:#f5f5f5; max-width:400px; border:1px outset gray; padding:5px" />')
      .appendTo( document.body )
      .offset( el.offset() )
      .html( el.data( 'popup' ) )
      .bind('click mouseleave', function(){ $(this).remove() } )
      //position 
      pp.offset( el.offset() ) // need this again for Opera 11 ?
      if( pp.offset().left + pp.width() > $(window).width() ) //move left if needed
        pp.css( 'left', $(window).width() - pp.width() - 50 + 'px' )
  
   })
 }
})