User:Magnus Manske/MediaWiki:Gadget-Check-usage.js

Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
// JavaScript-based CheckUsage using query.php
// Version 0.2
// (c) 2007 by Magnus Manske
// Released under GPL

// This script will check hundreds, of MediaWiki installations via query.php
// To not overload the connection, it will limit itself to checkusage_concurrent_connections
// connections at any time

// Some variables
var checkusage_concurrent_connections = 10 ; // Max number of simultanious queries
var checkusage_header ; // CheckUsage header <div>
var checkusage_footer ; // CheckUsage footer <div>
var checkusage_counter ; // Total number of queries left
var checkusage_running ; // Currently number of queries running
var checkusage_init_done ; // Prevents showing of countdown until initialization is done
var checkusage_using ; //How many sites are using this image?
var checkusage_totaluse ; //How many times is this used?
var checkusage_biguse ; //How many sites use it a lot? (> 50)

// Install onload handler, which will display the link to start the script
if( wgNamespaceNumber == 6 ) addOnloadHook ( init_commons_usage ) ;

// Generates the link to start this script
function get_checkusage_link () {
  return '<a href="#" onClick="run_checkusage();">JavaScript CheckUsage</a>' ;
}

// Onload handler
// Adds div section with id "checkusage"
function init_commons_usage () {
  var file_div = document.getElementById("file") ;
  var insert_before = null;
  if (!file_div) {
      if (document.getElementById("filelinks")) {
          file_div = document.getElementById("filelinks");
          insert_before = file_div.nextSibling;
          file_div = file_div.parentNode;
          // just insert it after the "filelinks" header
      } else
          return; // Don't know where to insert it
  } else
    insert_before = file_div.firstChild;

  var cu_header = document.createElement ( "DIV" ) ;
  var cu_footer = document.createElement ( "DIV" ) ;
  var cu_div = document.createElement ( "DIV" ) ;

  cu_header.id = "checkusage_header" ;
  cu_footer.id = "checkusage_footer" ;
  cu_div.id = "checkusage" ;
  cu_div.style.cssFloat = "right" ;
  cu_div.style.clear = "right" ;

  cu_div.appendChild ( cu_header ) ;
  cu_div.appendChild ( cu_footer ) ;
  file_div.insertBefore ( cu_div , insert_before ) ;
/*
  file_div.innerHTML = '<div id="checkusage" style="float:right;clear:right">' +
  '<div id="checkusage_header"></div>' +
  '<div id="checkusage_footer"></div>' +
  '</div>' + file_div.innerHTML ;
*/
  checkusage_header = document.getElementById("checkusage_header") ;
  checkusage_footer = document.getElementById("checkusage_footer") ;
  checkusage_header.innerHTML = get_checkusage_link() ;
}

// Constructs the query.php URL based on image name, project, and language
function get_usage_url ( language , project , image ) {
  var url = "http://commons.wikimedia.org/w/query.php?" ;
  if ( project != "wikimedia" || language != "commons" ) url += "proxysite=" + project + "&proxylang=" + language + "&" ;
  url +=    "format=xml" +
            "&what=imagelinks" +
            "&illimit=51" + // 51 links maximum
            "&titles=Image:" + encodeURIComponent(image) ;
  return url ;
}

// Handler to toggle the listing of hits for a single language/project
function usage_toggle_id ( id ) {
  var e = document.getElementById(id) ;
  if ( e.style.display == "none" ) e.style.display = "block" ;
  else e.style.display = "none" ;
}

// Helper function for toggle_all()
function usage_getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

// Handler to toggle the listing of hits for all languages/projects
function usage_toggle_all () {
  var newstate = "" ;
  var els = usage_getElementsByClass ( "checkusage_item" , checkusage_footer , "*" ) ;
  for ( var i = 0 ; i < els.length ; i++ ) {
    if ( newstate == "" ) {
      if ( els[i].style.display == "none" ) newstate = "block" ;
      else newstate = "none" ;
    }
    els[i].style.display = newstate ;
  }
}

// When a query changes its status, this function is called
// It updates the display with new results and manages the "remaining" counter
// as well as the running queries
function checkusage_callback () {
  checkusage_header = document.getElementById("checkusage_header") ;
  checkusage_footer = document.getElementById("checkusage_footer") ;

  for ( var i = 0 ; i < xmlobjects.length ; i++ ) {
    if ( xmlobjects[i].done ) continue ;
    checkusage_start_task ( i ) ;
    if (xmlobjects[i].readyState==4 && xmlobjects[i].done == false) {
      xmlobjects[i].done = true ;
      var lp = xmlobjects[i].lp ;
      var text = xmlobjects[i].responseText ;
      var lines = text.split ( "</il>" ) ;
      checkusage_counter-- ;
      checkusage_running-- ;
//checkusage_header.innerHTML += "." ;

      if ( lines.length > 1 ) {
        lines.pop () ;
        checkusage_using++;
        var oversize = false ;
        while ( lines.length > 50 ) {
          lines.pop() ;
          oversize = true ;
          checkusage_biguse++;
        }
        checkusage_totaluse += lines.length ;

        var id = "results_" + lp ;
        var init = "<b>" + lp + " :</b> " ;
        init += "<a href='#' onClick='usage_toggle_id(\"" + id + "\");'>" + lines.length ;
        if ( oversize ) init += "<b>+</b>" ;
        if ( lines.length == 1 ) init += " page</a>" ;
        else init += " pages</a>" ;
        init += "<br/>" ;
        text = "<span class='checkusage_item' id='" + id + "' style='display:none;text-align:left'><small><ul>" ;
        for ( l = 0 ; l < lines.length ; l++ ) {
          var s = lines[l].split ( ">" ) ;
          s = s.pop () ;
          text += "<li><a href=\"http://" + lp + ".org/wiki/" + s + "\">" + s + "</a></li>" ;
        }
        checkusage_footer.innerHTML += init + text + "</ul></small></span>" ;
      }
    }
  }
  if ( checkusage_counter == 0 ) { // Done!
    checkusage_header.innerHTML = get_checkusage_link() ;

    if ( checkusage_footer.innerHTML != "" ) {
      checkusage_header.innerHTML += " &nbsp; <a href='#' onClick='usage_toggle_all();'>Show/hide all</a>" ;
    } else checkusage_header.innerHTML += " &nbsp; No usage found!" ;

    if (checkusage_using)
        checkusage_header.innerHTML += "<p>Used on " + checkusage_using + " sites" + (checkusage_biguse ? " (" + checkusage_biguse + " +50), on +" : ", ") + checkusage_totaluse + " pages.</p>" ;
  } else if ( checkusage_init_done == true ) {
    checkusage_header.innerHTML = checkusage_counter + " sites remaining. ";
    if (checkusage_using)
        checkusage_header.innerHTML += checkusage_using + " sites using it" ;
    if (checkusage_totaluse) {
        checkusage_header.innerHTML += " on " + (checkusage_biguse ? "+" : "") + checkusage_totaluse + " pages.";
    }
  } else checkusage_header.innerHTML = "Initializing..." ;
}

// Starts a new query if appropriate
function checkusage_start_task ( i ) {
  if ( checkusage_running >= checkusage_concurrent_connections ) return ; // Maximum running tasks
  if ( xmlobjects[i].done ) return ; // Already done
  if ( xmlobjects[i].running ) return ; // Already running
  xmlobjects[i].running = true ;
  xmlobjects[i].open ( "GET" , xmlobjects[i].theurl , true ) ;
  xmlobjects[i].send ( null ) ;
  checkusage_running++ ;
}

// Prepares a new query and adds it to the list
function add_checkusage_task ( language , project ) {
  var lp = language + "." + project ;
  var url = get_usage_url ( language , project , wgTitle ) ;

  var i = xmlobjects.length ;
  xmlobjects.push ( new XMLHttpRequest() ) ;
  xmlobjects[i].i = i ;
  xmlobjects[i].lp = lp ;
  xmlobjects[i].theurl = url ;
  xmlobjects[i].done = false ;
  xmlobjects[i].running = false ;
  xmlobjects[i].onreadystatechange = checkusage_callback ;
  checkusage_start_task ( i ) ;
  checkusage_counter++ ;
}

// Adds queries for all given languages for a single project
function add_checkusage_tasks ( project , languages ) {
  for ( var l = 0 ; l < languages.length ; l++ ) add_checkusage_task ( languages[l] , project ) ;
}

// Initializes the run of the script and prepares/starts the queries
function run_checkusage () {
  checkusage_footer.innerHTML = "" ;
  checkusage_counter = 0 ;
  checkusage_running = 0 ;
  checkusage_using = 0;
  checkusage_totaluse = 0;
  checkusage_biguse = 0;
  checkusage_init_done = false ;
  var checkusage = document.getElementById("checkusage") ;
  checkusage.style.width = "250px" ;
  checkusage.style.border = "1px solid black" ;

  var lang_wikinews = new Array ( "en","de","it","pl","sv","pt","es","ja","fr","zh","ru","nl","ro","sr","uk","ca","no","he","ar","bs","th","bg" ) ;
  var lang_wikipedia = new Array ( 'aa','ab','af','ak','als','am','an','ang','ar','arc','as','ast','av','ay','az','ba','bar','bat-smg','be','be-tarask','be-x-old','bg','bh','bi','bm','bn','bo','bpy','br','bs','bug','bxr','ca','cbk-zam','cdo','ce','ceb','ch','cho','chr','chy','co','cr','crh','crh-latn','crh-cyrl','cs','csb','cu','cv','cy','da','de','diq','dk','dv','dz','ee','el','eml','en','eo','es','et','eu','fa','ff','fi','fiu-vro','fj','fo','fr','frp','fur','fy','ga','gd','gl','glk','gn','got','gsw','gu','gv','ha','haw','he','hi','hil','ho','hr','hsb','ht','hu','hy','hz','ia','id','ie','ig','ii','ik','ilo','io','is','it','iu','ja','jbo','jv','ka','kaa','kab','kg','ki','kj','kk','kk-cn','kk-kz','kk-tr','kl','km','kn','ko','kr','ks','ksh','ksh-c-a','ksh-p-b','ku','kv','kw','ky','la','lad','lbe','lb','lg','li','lij','lld','lmo','ln','lo','lt','lv','lzz','map-bms','mg','mh','mi','minnan','mk','ml','mn','mo','mr','ms','mt','mus','my','mzn','na','nah','nan','nap','nb','nds','nds-nl','ne','new','ng','nl','nn','no','non','nov','nrm','nv','ny','oc','om','or','os','pa','pag','pam','pap','pdc','pi','pih','pl','pms','ps','pt','pt-br','qu','rm','rmy','rn','ro','roa-rup','roa-tara','ru','ru-sib','rw','sa','sc','scn','sco','sd','se','sg','sh','si','simple','sk','sl','sm','sn','so','sq','sr','sr-ec','sr-jc','sr-el','sr-jl','ss','st','su','sv','sw','ta','te','tet','tg','th','ti','tk','tl','tlh','tn','to','tokipona','tp','tpi','tr','ts','tt','tum','tw','ty','tyv','udm','ug','uk','ur','uz','ve','vec','vi','vls','vo','wa','war','wo','wuu','xal','xh','yi','yo','yue','za','zea','zh','zh-cfr','zh-classical','zh-cn','zh-hans','zh-hant','zh-hk','zh-min-nan','zh-sg','zh-tw','zh-yue','zu');
  var lang_wikibooks = lang_wikinews;

  xmlobjects= new Array() ;
  add_checkusage_task ( "commons" , "wikimedia" ) ;
  add_checkusage_tasks ( "wikipedia" , lang_wikipedia ) ;
  add_checkusage_tasks ( "wikibooks" , lang_wikibooks ) ;
  add_checkusage_tasks ( "wikinews" , lang_wikinews ) ;
  checkusage_init_done = true ;
}