コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

利用者:Frozen-mikan/OtherLangImages.js

お知らせ: 保存した後、ブラウザのキャッシュをクリアしてページを再読み込みする必要があります。

多くの WindowsLinux のブラウザ

  • Ctrl を押しながら F5 を押す。

Mac における Safari

  • Shift を押しながら、更新ボタン をクリックする。

Mac における ChromeFirefox

  • Cmd Shift を押しながら R を押す。

詳細についてはWikipedia:キャッシュを消すをご覧ください。

/*
 * 言語間リンクで他言語の画像ファイルを調べるスクリプト。
 * 試作版。
 * ヘルプは以下のURLにあります。
 * @see http://ja-two.iwiki.icu/wiki/User:Frozen-mikan/OtherLangImages
 */
(function(window, document){ jQuery( document ).ready( function($){
  var rootId = 'other_lang_images';
  var viewAllSelector = '.view_all';
  var callbackName = 'appendImages';
  var commonsHost = 'commons.wikimedia.org';
  var contentLang = mw.config.get( 'wgContentLanguage');
  
  /* 言語コードを用いて、姉妹プロジェクトのホスト名を返す関数 */
  var getHostName = (function(){
    var baseHost = /^.+?(\..+)$/.exec(location.host)[1];
    return function(lang){
      return lang + baseHost;
    };
  })();
  
  var imageTitles = [];
  var imagesByTitle = {};
  var imagesByLang = {};
  
  function initUI() {
    var root = getRoot();
    $( '.control' , root ).toggle(false);
    $( viewAllSelector , root ).toggle(false).click(function() {
      $( 'tr.raw_false, tr.' + contentLang, root).toggle(true);
      $( viewAllSelector , root ).toggle(false);
      return false;
    }).attr( 'value' , '全ての画像を表示');
    root.toggle(true);
  }
  
  function getRoot() {
    var root = $( '#' + rootId );
    if (root.length == 0) {
      mw.util.$content.before('<div id="' + rootId + '">' +
        '<div class="progressbar" />' +
        '<form class="control">' +
        '<input class="view_all" type="button" /></form>'
      );
      root = $( '#' + rootId ).toggle( false );
    }
    return root;
  }
  function redrawUI() {
    $( '.progressbar' , getRoot()).toggle(false);
    if( imageTitles.length == 0 ) return;
    var area = getDataArea();
    for (var i = 0; i < imageTitles.length; ++i) {
      var title = imageTitles[i];
      var image = imagesByTitle[title];
      var url = 'http://' + commonsHost + '/wiki/File:' + title;
      var raw = image.raw;
      var clang = imagesByLang[contentLang] &&
        imagesByLang[contentLang][title];
      area.append('<tr class="raw_' + raw +
        (clang ? ' ' + contentLang : '') + '"' +
        (!raw || clang ? ' style="display:none;"' : '') + '>' +
        '<td>' + formatLangs(image.langs, title) + '</td>' +
        '<td><a href="' + url + '">' + formatTitle(title, raw) +
        '</a></td>' +
      '</tr>');
    }
  }
  function getDataArea() {
    var root = getRoot();
    $( 'table', root ).remove();
    $( viewAllSelector , root ).toggle(true);
    $( root ).append(
      '<table class="wikitable"><tbody>' +
      '<tr><th>Langs</th><th>Filename</th></tr>' +
      '</tbody></table>'
    );
    return $( 'table', root ).last();
  }
  function formatLangs(langs, title) {
    var t = '';
    for (var i = 0; i < langs.length; ++i) {
      if (i != 0) {
        t += ', ';
      }
      var lang = langs[i];
      if (lang == contentLang) {
        t += '<b>';
      }
      t += '<a href="http://' + getHostName(lang) +
        '/wiki/File:' + title + '">' + lang + '</a>';
      if (lang == contentLang) {
        t += '</b>';
      }
    }
    return t;
  }
  function formatTitle(title, raw) {
    if (raw) {
      return '<b>' + title + '</b>';
    }
    return title;
  }
  function progress(per) {
    function valid(per) {
      if (per < 0) {
        per = 0;
      } else if (100 < per) {
        per = 100;
      } else {
        per = Math.round(per);
      }
      return per;
    }
    var bar = $( '.progressbar' , getRoot() );
    var inner = $( 'div.inner' , bar );
    if (inner.length == 0) {
      bar.css({ 'width' : '300px' , 'border' : '1px solid #99c' })
        .append( '<div class="inner"' +
        ' style="height: 14px; width: 0px; background-color: #ccf;" />' );
    }
    $( 'div.inner' , bar ).css( 'width' , valid(per) + '%' );
    bar.toggle(true);
  }
  
  function strip(text) {
    var re = /^[^:]+:(.+)$/;
    var m = re.exec(text);
    if (m) return m[1];
    return text;
  }
  function appendTitle(imageTitle) {
    for (var i = 0; i < imageTitles.length; ++i) {
      if (imageTitles[i] == imageTitle) return;
    }
    imageTitles.push(imageTitle);
  }
  function sort() {
    imageTitles.sort(function(a, b) {
      // 利用されている言語数の多い順に並べる
      var numa = imagesByTitle[a].langs.length;
      var numb = imagesByTitle[b].langs.length;
      if (numa < numb) return 1;
      if (numb < numa) return -1;
      // 同数の場合には文字列順
      if (a < b) return -1;
      if (b < a) return 1;
      return 0;
    });
  }

  /* prop=images|revisions 用のコールバック関数 */
  window[callbackName] = function(data){
    if (!data.query || !data.query.pages) return;
    var lang = data.requestid;
    for (var pageid in data.query.pages) {
      var page = data.query.pages[pageid];
      var images = page.images;
      if (!images) continue;
      var content = page.revisions[0]['*'];
      
      for (var i = 0; i < page.images.length; ++i) {
        var imageTitle = strip(images[i].title);
        var image = imagesByTitle[imageTitle];
        if (!image) {
          image = {};
          image.title = imageTitle;
          imagesByTitle[imageTitle] = image;
          image.langs = [];
        }
        if (!image.raw) {
          image.raw = (-1 != content.indexOf(image.title));
        }
        if (!imagesByLang[lang]) {
          imagesByLang[lang] = {};
        }
        imagesByLang[lang][imageTitle] = image;
        image.langs.push(lang);
        image.langs.sort();
        appendTitle(imageTitle);
      }
    }
    // sort();
    // redrawUI();
  };
  
  var title = mw.config.get( 'wgPageName' );
  initUI();
  $.getJSON(
  'http://' + location.host + '/w/api.php?',
  {
    format: 'json',
    action: 'query',
    prop: 'langlinks',
    lllimit: 'max',
    titles: title
  },
  function(data){
    var c = max=0;
    function parseApiLanglinks(data) {
      var page = data.query.pages[mw.config.get( 'wgArticleId' )];
      var langlinks = page.langlinks;
      var llmap = {};
      llmap[contentLang] = page.title;
      if (!langlinks) return llmap;
      for(var i = 0; i < langlinks.length; ++i) {
        var ll = langlinks[i];
        llmap[ll.lang] = ll['*'];
      }
      return llmap;
    }
    var llmap = parseApiLanglinks(data);
    var interval = 30; // msec
    function getImageTitles(lang, title, callback) {
      $.getScript('http://' + getHostName(lang) +
        '/w/api.php?' +
        $.param({
          action: 'query',
          requestid: lang,
          format: 'json',
          callback: callbackName,
          prop: 'images|revisions',
          imlimit: 'max',
          rvlimit: '1',
          rvprop: 'content',
          titles: title
        }),
        callback
      );
    }
    /* 最後に実行される関数 */
    var last = function(){
      progress(100);
      sort();
      redrawUI();
      if ( imageTitles.length == 0 ) {
        $( '#' + rootId ).toggle(false);
      } else {
        $( 'form.control', getRoot() ).toggle(true);
      }
    };
    for (var lang in llmap) (function (lang) {
      var title = llmap[lang];
      var last0 = last; // このスコープに定着させるため
      last = function() {
        ++c;
        progress(100 * c / max);
        setTimeout(
          function(){ getImageTitles(lang, title, last0); },
          interval
        );
      };
      ++max;
    })(lang);
    if (typeof last == 'function') {
      last(); // 最後に生成したものから遡って実行する
    }
  });
}); /* end of ready */})(window, document);