MediaWiki:Common.js: Difference between revisions

From UAPedia
Jump to navigationJump to search
Created page with "Any JavaScript here will be loaded for all users on every page load.: // Add a copyable 100px-wide thumb link on File: pages (good for portrait 440x587 -> ~100x133) mw.hook('wikipage.content').add(function ($content) { // Namespace 6 = File: if (mw.config.get('wgNamespaceNumber') !== 6) return; // On File: pages, wgTitle is usually the filename without "File:" var filename = mw.config.get('wgTitle'); if (!filename) return; // Build: /wiki/Special:Redir..."
 
No edit summary
 
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
// UAPedia: File-page helper to generate & copy a 100px-wide thumbnail direct URL
// Add a copyable 100px-wide thumb link on File: pages (good for portrait 440x587 -> ~100x133)
mw.hook('wikipage.content').add(function ($content) {
mw.hook('wikipage.content').add(function ($content) {
   // Namespace 6 = File:
   // File namespace only
   if (mw.config.get('wgNamespaceNumber') !== 6) return;
   if (mw.config.get('wgNamespaceNumber') !== 6) return;


  // On File: pages, wgTitle is usually the filename without "File:"
   var fileTitle = mw.config.get('wgPageName'); // e.g. "File:Silouette-portrait.webp"
   var filename = mw.config.get('wgTitle');
   if (!fileTitle) return;
   if (!filename) return;


   // Build: /wiki/Special:Redirect/file/<filename>?width=100
   var targetWidth = 100; // your desired thumb width (=> ~133px tall for 440x587)
  var rel = mw.util.getUrl('Special:Redirect/file/' + filename, { width: 100 });
 
   var abs = (mw.config.get('wgServer') || location.origin) + rel;
  var api = new mw.Api();
 
  function setStatus($box, msg) {
    $box.find('.uap-thumb-status').text(msg);
  }
 
  function copyText(text, $box) {
    if (navigator.clipboard && navigator.clipboard.writeText) {
      return navigator.clipboard.writeText(text).then(function () {
        setStatus($box, 'Copied!');
        setTimeout(function () { setStatus($box, ''); }, 1200);
      });
    }
    // fallback
    var $tmp = $('<textarea readonly></textarea>').val(text).css({
      position: 'absolute', left: '-9999px', top: '-9999px'
    }).appendTo(document.body);
    $tmp[0].select();
    try { document.execCommand('copy'); } catch (e) {}
    $tmp.remove();
    setStatus($box, 'Copied!');
    setTimeout(function () { setStatus($box, ''); }, 1200);
    return Promise.resolve();
  }
 
  function fetchImageInfo() {
    // Get original URL + thumb URL at width=100
    return api.get({
      action: 'query',
      titles: fileTitle,
      prop: 'imageinfo',
      iiprop: 'url',
      iiurlwidth: targetWidth,
      format: 'json'
    }).then(function (data) {
      var pages = data && data.query && data.query.pages;
      if (!pages) throw new Error('No API pages returned');
 
      var pageId = Object.keys(pages)[0];
      var page = pages[pageId];
      if (!page || !page.imageinfo || !page.imageinfo.length) {
        throw new Error('No imageinfo found (is this a file page?)');
      }
      var ii = page.imageinfo[0];
      return {
        originalUrl: ii.url || '',
        thumbUrl: ii.thumburl || '',
        thumbWidth: ii.thumbwidth || null,
        thumbHeight: ii.thumbheight || null
      };
    });
   }
 
  function forceGenerateThumb(thumbUrl, $box) {
    // Preload the thumb URL; this usually forces thumb generation if it wasn’t created yet.
    return new Promise(function (resolve, reject) {
      if (!thumbUrl) return reject(new Error('No thumb URL to generate'));
      var img = new Image();
      img.onload = function () { resolve(); };
      img.onerror = function () { reject(new Error('Thumb load failed')); };
      // cache-bust to ensure a request actually happens
      img.src = thumbUrl + (thumbUrl.indexOf('?') === -1 ? '?' : '&') + 'uapgen=' + Date.now();
    });
  }
 
  // UI
  var $box = $(
    '<div class="uap-thumb-linkbox">' +
      '<div class="uap-thumb-title"><b>Thumbnail helper</b> <span class="uap-thumb-status"></span></div>' +
 
      '<div class="uap-thumb-row">' +
        '<div class="uap-thumb-label">Original file URL</div>' +
        '<input class="uap-thumb-input uap-original" type="text" readonly />' +
        '<button class="uap-thumb-copy-original mw-ui-button">Copy</button>' +
      '</div>' +
 
      '<div class="uap-thumb-row">' +
        '<div class="uap-thumb-label">Generate ' + targetWidth + 'px thumb</div>' +
        '<button class="uap-thumb-generate mw-ui-button mw-ui-progressive">Generate / Refresh</button>' +
        '<span class="uap-thumb-dims"></span>' +
      '</div>' +


  var $box = $('<div class="uap-thumb-linkbox">' +
      '<div><b>Thumb link (100w ≈ 133h)</b></div>' +
       '<div class="uap-thumb-row">' +
       '<div class="uap-thumb-row">' +
         '<input class="uap-thumb-input" type="text" readonly />' +
        '<div class="uap-thumb-label">Direct thumb URL (' + targetWidth + 'px wide)</div>' +
         '<button class="uap-thumb-copy mw-ui-button mw-ui-progressive">Copy</button>' +
         '<input class="uap-thumb-input uap-thumb" type="text" readonly />' +
         '<button class="uap-thumb-copy-thumb mw-ui-button">Copy</button>' +
       '</div>' +
       '</div>' +
      '<div class="uap-thumb-note">Use this URL in wiki entries / phpBB. It will always resolve to a 100px-wide thumb.</div>' +
    '</div>');


  $box.find('input.uap-thumb-input').val(abs);
      '<div class="uap-thumb-note">' +
        'Use the <b>Direct thumb URL</b> in external <code>&lt;img src=""&gt;</code> tags. ' +
        'It points into <code>/wiki/images/thumb/...</code> and avoids Special-page redirects.' +
      '</div>' +
    '</div>'
  );


   $box.find('button.uap-thumb-copy').on('click', function () {
   // Insert somewhere stable across skins
    var $input = $box.find('input.uap-thumb-input');
  var $container = $('#mw-content-text');
    $input.trigger('focus').trigger('select');
  ($container.length ? $container : $content).prepend($box);


    var text = $input.val();
  // Wire buttons
  var state = { originalUrl: '', thumbUrl: '' };


     // Modern clipboard API
  function refreshUI(info) {
     if (navigator.clipboard && navigator.clipboard.writeText) {
     state.originalUrl = info.originalUrl || '';
      navigator.clipboard.writeText(text).then(function () {
     state.thumbUrl = info.thumbUrl || '';
        // tiny feedback
 
        $box.find('.uap-thumb-note').text('Copied!');
    $box.find('input.uap-original').val(state.originalUrl);
        setTimeout(function () {
    $box.find('input.uap-thumb').val(state.thumbUrl);
          $box.find('.uap-thumb-note').text('Use this URL in wiki entries / phpBB. It will always resolve to a 100px-wide thumb.');
 
        }, 1500);
    if (info.thumbWidth && info.thumbHeight) {
      }).catch(function () {
      $box.find('.uap-thumb-dims').text('(' + info.thumbWidth + '×' + info.thumbHeight + ')');
        // fallback
        document.execCommand('copy');
      });
     } else {
     } else {
       // Legacy fallback
       $box.find('.uap-thumb-dims').text('');
      document.execCommand('copy');
     }
     }
  }
  function loadOnce() {
    setStatus($box, 'Loading…');
    return fetchImageInfo()
      .then(function (info) {
        refreshUI(info);
        setStatus($box, '');
      })
      .catch(function (err) {
        setStatus($box, 'Error: ' + err.message);
      });
  }
  $box.find('.uap-thumb-copy-original').on('click', function () {
    if (!state.originalUrl) return setStatus($box, 'No original URL yet');
    copyText(state.originalUrl, $box);
   });
   });


   // Insert near the file info table if present
   $box.find('.uap-thumb-copy-thumb').on('click', function () {
   var $target = $('#fileinfotable');
    if (!state.thumbUrl) return setStatus($box, 'No thumb URL yet');
  if ($target.length) {
    copyText(state.thumbUrl, $box);
    $target.after($box);
  });
  } else {
 
    $content.prepend($box);
   $box.find('.uap-thumb-generate').on('click', function () {
   }
    setStatus($box, 'Generating…');
    fetchImageInfo()
      .then(function (info) {
        refreshUI(info);
        return forceGenerateThumb(info.thumbUrl, $box).then(function () {
          // Re-fetch in case the thumb URL/dims change after generation
          return fetchImageInfo().then(function (info2) {
            refreshUI(info2);
            setStatus($box, 'Generated');
            setTimeout(function () { setStatus($box, ''); }, 1200);
          });
        });
      })
      .catch(function (err) {
        setStatus($box, 'Error: ' + err.message);
      });
   });
 
  // Initial load
  loadOnce();
});
});

Latest revision as of 01:30, 7 February 2026

// UAPedia: File-page helper to generate & copy a 100px-wide thumbnail direct URL
mw.hook('wikipage.content').add(function ($content) {
  // File namespace only
  if (mw.config.get('wgNamespaceNumber') !== 6) return;

  var fileTitle = mw.config.get('wgPageName'); // e.g. "File:Silouette-portrait.webp"
  if (!fileTitle) return;

  var targetWidth = 100; // your desired thumb width (=> ~133px tall for 440x587)

  var api = new mw.Api();

  function setStatus($box, msg) {
    $box.find('.uap-thumb-status').text(msg);
  }

  function copyText(text, $box) {
    if (navigator.clipboard && navigator.clipboard.writeText) {
      return navigator.clipboard.writeText(text).then(function () {
        setStatus($box, 'Copied!');
        setTimeout(function () { setStatus($box, ''); }, 1200);
      });
    }
    // fallback
    var $tmp = $('<textarea readonly></textarea>').val(text).css({
      position: 'absolute', left: '-9999px', top: '-9999px'
    }).appendTo(document.body);
    $tmp[0].select();
    try { document.execCommand('copy'); } catch (e) {}
    $tmp.remove();
    setStatus($box, 'Copied!');
    setTimeout(function () { setStatus($box, ''); }, 1200);
    return Promise.resolve();
  }

  function fetchImageInfo() {
    // Get original URL + thumb URL at width=100
    return api.get({
      action: 'query',
      titles: fileTitle,
      prop: 'imageinfo',
      iiprop: 'url',
      iiurlwidth: targetWidth,
      format: 'json'
    }).then(function (data) {
      var pages = data && data.query && data.query.pages;
      if (!pages) throw new Error('No API pages returned');

      var pageId = Object.keys(pages)[0];
      var page = pages[pageId];
      if (!page || !page.imageinfo || !page.imageinfo.length) {
        throw new Error('No imageinfo found (is this a file page?)');
      }
      var ii = page.imageinfo[0];
      return {
        originalUrl: ii.url || '',
        thumbUrl: ii.thumburl || '',
        thumbWidth: ii.thumbwidth || null,
        thumbHeight: ii.thumbheight || null
      };
    });
  }

  function forceGenerateThumb(thumbUrl, $box) {
    // Preload the thumb URL; this usually forces thumb generation if it wasn’t created yet.
    return new Promise(function (resolve, reject) {
      if (!thumbUrl) return reject(new Error('No thumb URL to generate'));
      var img = new Image();
      img.onload = function () { resolve(); };
      img.onerror = function () { reject(new Error('Thumb load failed')); };
      // cache-bust to ensure a request actually happens
      img.src = thumbUrl + (thumbUrl.indexOf('?') === -1 ? '?' : '&') + 'uapgen=' + Date.now();
    });
  }

  // UI
  var $box = $(
    '<div class="uap-thumb-linkbox">' +
      '<div class="uap-thumb-title"><b>Thumbnail helper</b> <span class="uap-thumb-status"></span></div>' +

      '<div class="uap-thumb-row">' +
        '<div class="uap-thumb-label">Original file URL</div>' +
        '<input class="uap-thumb-input uap-original" type="text" readonly />' +
        '<button class="uap-thumb-copy-original mw-ui-button">Copy</button>' +
      '</div>' +

      '<div class="uap-thumb-row">' +
        '<div class="uap-thumb-label">Generate ' + targetWidth + 'px thumb</div>' +
        '<button class="uap-thumb-generate mw-ui-button mw-ui-progressive">Generate / Refresh</button>' +
        '<span class="uap-thumb-dims"></span>' +
      '</div>' +

      '<div class="uap-thumb-row">' +
        '<div class="uap-thumb-label">Direct thumb URL (' + targetWidth + 'px wide)</div>' +
        '<input class="uap-thumb-input uap-thumb" type="text" readonly />' +
        '<button class="uap-thumb-copy-thumb mw-ui-button">Copy</button>' +
      '</div>' +

      '<div class="uap-thumb-note">' +
        'Use the <b>Direct thumb URL</b> in external <code>&lt;img src=""&gt;</code> tags. ' +
        'It points into <code>/wiki/images/thumb/...</code> and avoids Special-page redirects.' +
      '</div>' +
    '</div>'
  );

  // Insert somewhere stable across skins
  var $container = $('#mw-content-text');
  ($container.length ? $container : $content).prepend($box);

  // Wire buttons
  var state = { originalUrl: '', thumbUrl: '' };

  function refreshUI(info) {
    state.originalUrl = info.originalUrl || '';
    state.thumbUrl = info.thumbUrl || '';

    $box.find('input.uap-original').val(state.originalUrl);
    $box.find('input.uap-thumb').val(state.thumbUrl);

    if (info.thumbWidth && info.thumbHeight) {
      $box.find('.uap-thumb-dims').text('(' + info.thumbWidth + '×' + info.thumbHeight + ')');
    } else {
      $box.find('.uap-thumb-dims').text('');
    }
  }

  function loadOnce() {
    setStatus($box, 'Loading…');
    return fetchImageInfo()
      .then(function (info) {
        refreshUI(info);
        setStatus($box, '');
      })
      .catch(function (err) {
        setStatus($box, 'Error: ' + err.message);
      });
  }

  $box.find('.uap-thumb-copy-original').on('click', function () {
    if (!state.originalUrl) return setStatus($box, 'No original URL yet');
    copyText(state.originalUrl, $box);
  });

  $box.find('.uap-thumb-copy-thumb').on('click', function () {
    if (!state.thumbUrl) return setStatus($box, 'No thumb URL yet');
    copyText(state.thumbUrl, $box);
  });

  $box.find('.uap-thumb-generate').on('click', function () {
    setStatus($box, 'Generating…');
    fetchImageInfo()
      .then(function (info) {
        refreshUI(info);
        return forceGenerateThumb(info.thumbUrl, $box).then(function () {
          // Re-fetch in case the thumb URL/dims change after generation
          return fetchImageInfo().then(function (info2) {
            refreshUI(info2);
            setStatus($box, 'Generated');
            setTimeout(function () { setStatus($box, ''); }, 1200);
          });
        });
      })
      .catch(function (err) {
        setStatus($box, 'Error: ' + err.message);
      });
  });

  // Initial load
  loadOnce();
});