MediaWiki:Common.js: Difference between revisions

From MediaWiki
Jump to navigation Jump to search
No edit summary
Tag: Reverted
No edit summary
Tag: Reverted
Line 1: Line 1:
mw.loader.using(['mediawiki.api']).then(function () {
/* Any JavaScript here will be loaded for all users on every page load. */
   var box = document.getElementById('random-teaser');
 
  if (!box) { console.warn('[teaser] #random-teaser not found'); return; }
/* -----------------------------------------
  box.textContent = 'JS loaded, calling API…';
  jQuery UI tabs (safe) – won't break page
  new mw.Api().get({ action: 'query', meta: 'siteinfo', formatversion: 2 })
------------------------------------------*/
    .then(function(){ box.textContent = 'API OK — teaser will load next…'; })
mw.loader.using(['jquery.ui']).then(function () {
    .catch(function(e){ box.textContent = 'API error: ' + e; console.error(e); });
   try {
});
    if ($("[class^=portal_vtab]").length) {
      $("[class^=portal_vtab]").tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
      $("[class^=portal_vtab] li").removeClass("ui-corner-top").addClass("ui-corner-left");
    }


    var $tabs = $("#portal_slider");
    if ($tabs.length) {
      $tabs.tabs({ fx: { opacity: 'toggle', duration: 100 } });


/* Any JavaScript here will be loaded for all users on every page load. */
      function selectTab(idx) {
        idx = parseInt(idx, 10) || 0;
        $tabs.tabs("option", "active", idx);
      }


/****************************************/
      $("[class*=portal_sliderlink]").on('click', function (e) {
/* sliders using jquery by User:Tierrie */
        e.preventDefault();
/****************************************/
        var m = this.className.match(/portal_sliderlink-(\d+)/);
mw.loader.using(['jquery.cookie']);
        if (m) selectTab(m[1]);
      });


/****************************************/
      $('#portal_next').on('click', function (e) {
/* sliders using jquery by User:Tierrie */
        e.preventDefault();
/****************************************/
        var active = $tabs.tabs("option", "active");
mw.loader.using(['jquery.ui'], function () {
        var total  = $tabs.find("> ul > li").length || 1;
  $("[class^=portal_vtab]").tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
        selectTab((active + 1) % total);
  $("[class^=portal_vtab] li").removeClass("ui-corner-top").addClass("ui-corner-left");
      });


  var $tabs = $("#portal_slider").tabs({ fx: { opacity: 'toggle', duration: 100 } });
      $('#portal_prev').on('click', function (e) {
  $("[class*=portal_sliderlink]").on('click', function () {
        e.preventDefault();
    $tabs.tabs('select', this.className.match(/portal_sliderlink-(\d+)/)[1]);
        var active = $tabs.tabs("option", "active");
    return false;
        var total  = $tabs.find("> ul > li").length || 1;
  });
        selectTab((active - 1 + total) % total);
  $('#portal_next').on('click', function () {
      });
    $tabs.tabs('select', ($tabs.tabs('option', 'selected') == ($tabs.tabs('length')) - 1) ? 0 : $tabs.tabs('option', 'selected') + 1);
    }
    return false;
   } catch (err) {
  });
     console.warn('[tabs] disabled due to error:', err);
   $('#portal_prev').on('click', function () {
   }
     $tabs.tabs('select', ($tabs.tabs('option', 'selected') == 0) ? ($tabs.tabs('length') - 1) : $tabs.tabs('option', 'selected') - 1);
    return false;
   });
});
});


/* lockdown for reference popup configuration */
/* -----------------------------------------
  ReferencePopups lockdown + upload tweak
------------------------------------------*/
((window.dev = window.dev || {}).ReferencePopups = dev.ReferencePopups || {}).lockdown = true;
((window.dev = window.dev || {}).ReferencePopups = dev.ReferencePopups || {}).lockdown = true;
/* Disable license check for multi upload */
mw.config.set('UMFBypassLicenseCheck', true);
mw.config.set('UMFBypassLicenseCheck', true);


/* Hide Admin toolbox for non-admins */
/* -----------------------------------------
  Hide Admin toolbox for non-admins
------------------------------------------*/
mw.loader.using('mediawiki.util').then(function () {
mw.loader.using('mediawiki.util').then(function () {
   var g = mw.config.get('wgUserGroups') || [];
   try {
  var isAdmin = g.indexOf('sysop') !== -1 || g.indexOf('interface-admin') !== -1;
    var g = mw.config.get('wgUserGroups') || [];
  if (!isAdmin) document.querySelectorAll('.only-sysop').forEach(function (el) { el.style.display = 'none'; });
    var isAdmin = g.indexOf('sysop') !== -1 || g.indexOf('interface-admin') !== -1;
    if (!isAdmin) {
      document.querySelectorAll('.only-sysop').forEach(function (el) { el.style.display = 'none'; });
    }
  } catch (e) {
    console.warn('[only-sysop] hide failed:', e);
  }
});
});


/* ============================
/* ==========================================================
   RANDOM PAGE TEASER (robust)
   RANDOM PAGE TEASER robust, pageid-based, no extensions
   ============================ */
   Renders into <div id="random-teaser" class="random-card">
========================================================== */
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () {
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () {
   var box = document.getElementById('random-teaser');
   var box = document.getElementById('random-teaser');
Line 59: Line 75:


   var api = new mw.Api();
   var api = new mw.Api();
   var THUMB_WIDTH = 280;
   var THUMB_W = 280;


   function esc(s) { return mw.html.escape(String(s || '')); }
   function esc(s){ return mw.html.escape(String(s || '')); }


   function makeExcerptFromHTML(html, maxChars) {
   function excerptFromHTML(html, maxChars) {
     var tmp = document.createElement('div');
     var d = document.createElement('div');
     tmp.innerHTML = html;
     d.innerHTML = html;
     var p = tmp.querySelector('p');
    // pick first meaningful paragraph
     var txt = (p ? p.innerText : tmp.innerText || '').replace(/\s+/g, ' ').trim();
     var p = d.querySelector('p');
     if (txt.length > maxChars) txt = txt.slice(0, maxChars).replace(/\s+\S*$/, '') + '…';
     var t = (p ? p.innerText : d.innerText || '').replace(/\s+/g, ' ').trim();
     return txt || 'No description available.';
     if (t.length > maxChars) t = t.slice(0, maxChars).replace(/\s+\S*$/, '') + '…';
     return t || 'No description available.';
   }
   }


   function pickImageTitle(list) {
   function firstRaster(list) {
  if (!Array.isArray(list) || !list.length) {
    if (!Array.isArray(list) || !list.length) return null;
     console.log('[teaser] no images in page');
    // Prefer raster formats
     return null;
     var pick = list.find(function (t) { return /\.(jpe?g|png|gif|webp)$/i.test(t || ''); });
     return pick || list[0] || null;
   }
   }
  // Logni všetky
  console.log('[teaser] candidate images:', list);
  // Vyber len rastre (jpg/png/gif/webp)
  var raster = list.find(function (t) {
    return /\.(jpe?g|png|gif|webp)$/i.test(t || '');
  });
  if (raster) {
    console.log('[teaser] picked raster:', raster);
    return raster;
  }
  // fallback – prvý
  console.log('[teaser] fallback to first:', list[0]);
  return list[0];
}


   function getThumbUrl(fileTitle) {
   function getThumbUrl(fileTitle) {
Line 103: Line 104:
       prop: 'imageinfo',
       prop: 'imageinfo',
       iiprop: 'url',
       iiprop: 'url',
       iiurlwidth: THUMB_WIDTH
       iiurlwidth: THUMB_W
     }).then(function (res) {
     }).then(function (r) {
       var p = res.query && res.query.pages && res.query.pages[0];
       var p = r.query && r.query.pages && r.query.pages[0];
       var ii = p && p.imageinfo && p.imageinfo[0];
       var ii = p && p.imageinfo && p.imageinfo[0];
       return (ii && (ii.thumburl || ii.url)) || null;
       return (ii && (ii.thumburl || ii.url)) || null;
     }).catch(function () { return null; });
     }).catch(function (e) {
      console.warn('[teaser] imageinfo failed:', e);
      return null;
    });
   }
   }


   function render(title, extract, imgUrl) {
   function render(title, text, imgUrl) {
     var url = mw.util.getUrl(title);
     var url = mw.util.getUrl(title);
     box.innerHTML =
     box.innerHTML =
Line 119: Line 123:
       '<div class="content">' +
       '<div class="content">' +
         '<h3><a href="' + url + '">' + esc(title) + '</a></h3>' +
         '<h3><a href="' + url + '">' + esc(title) + '</a></h3>' +
         '<p>' + esc(extract) + '</p>' +
         '<p>' + esc(text) + '</p>' +
         '<div class="actions">' +
         '<div class="actions">' +
           '<a class="btn" href="' + url + '">Open</a>' +
           '<a class="btn" href="' + url + '">Open</a>' +
Line 126: Line 130:
         '</div>' +
         '</div>' +
       '</div>';
       '</div>';
     box.classList.remove('loading');
     box.classList.remove('loading');


     var refreshBtn = document.getElementById('rand-refresh');
     var btn = document.getElementById('rand-refresh');
     if (refreshBtn) refreshBtn.addEventListener('click', function () {
     if (btn) btn.addEventListener('click', function () {
       box.classList.add('loading');
       box.classList.add('loading');
       loadRandom();
       load();
     });
     });
   }
   }


   function loadRandom() {
   function load() {
     // 1) pick random title
     // 1) Random page with pageid (stable)
     api.get({
     api.get({
       action: 'query',
       action: 'query',
       formatversion: 2,
       formatversion: 2,
       list: 'random',
       generator: 'random',
       rnnamespace: 0,
       grnnamespace: 0,
       rnlimit: 1
       grnlimit: 1,
     }).then(function (r) {
      prop: 'info'
       var item = r && r.query && r.query.random && r.query.random[0];
     }).then(function (q) {
       if (!item) throw new Error('No random page');
       var pg = q.query && q.query.pages && q.query.pages[0];
       var title = item.title;
       if (!pg) throw new Error('No random page');
      var pageid = pg.pageid;
       var title = pg.title;


       // 2) parse HTML + list images (no extensions required)
       // 2) Parse via pageid → HTML + images (avoids missingtitle)
       return api.get({
       return api.get({
         action: 'parse',
         action: 'parse',
         page: title,
         pageid: pageid,
         prop: 'text|images',
         prop: 'text|images',
         redirects: 1
         redirects: 1
       }).then(function (p) {
       }).then(function (p) {
         var html = p.parse && p.parse.text && p.parse.text['*'] || '';
         var html   = p.parse && p.parse.text && p.parse.text['*'] || '';
         var images = p.parse && p.parse.images || [];
         var images = p.parse && p.parse.images || [];
         var excerpt = makeExcerptFromHTML(html, 420);
         var text  = excerptFromHTML(html, 420);
         var fileTitle = pickImageTitle(images);
         var file  = firstRaster(images);


         return getThumbUrl(fileTitle).then(function (thumb) {
        // 3) Resolve thumbnail (if any)
           render(title, excerpt, thumb);
         return getThumbUrl(file).then(function (thumb) {
           render(title, text, thumb);
         });
         });
       });
       });
     }).catch(function (e) {
     }).catch(function (e) {
       console.warn('Random teaser failed:', e);
       console.error('[teaser] failed:', e);
       box.classList.remove('loading');
       box.classList.remove('loading');
       box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>';
       box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>';
Line 171: Line 179:
   }
   }


   loadRandom();
   // Initial load
});
 
mw.loader.using(['mediawiki.api','mediawiki.util']).then(function () {
  var box = document.getElementById('random-teaser');
  if (!box) return;
 
  var api = new mw.Api();
  var THUMB = 280;
 
  function esc(s){ return mw.html.escape(String(s||'')); }
  function excerptFromHTML(html, maxChars){
    var d=document.createElement('div'); d.innerHTML=html;
    var p=d.querySelector('p'); var t=(p?p.innerText:d.innerText||'').replace(/\s+/g,' ').trim();
    if(t.length>maxChars) t=t.slice(0,maxChars).replace(/\s+\S*$/,'')+'…';
    return t||'No description available.';
  }
  function firstRaster(list){
    if(!Array.isArray(list)||!list.length) return null;
    return list.find(function(t){return /\.(jpe?g|png|gif|webp)$/i.test(t||'');}) || list[0];
  }
  function thumbUrl(fileTitle){
    if(!fileTitle) return Promise.resolve(null);
    return api.get({
      action:'query',formatversion:2,titles:fileTitle,
      prop:'imageinfo',iiprop:'url',iiurlwidth:THUMB
    }).then(function(r){
      var p=r.query&&r.query.pages&&r.query.pages[0];
      var ii=p&&p.imageinfo&&p.imageinfo[0];
      return (ii&&(ii.thumburl||ii.url))||null;
    }).catch(function(){return null;});
  }
  function render(title,text,img){
    var url=mw.util.getUrl(title);
    box.innerHTML=
      '<div class="thumb">'+(img?'<img src="'+esc(img)+'" alt="">':'<span>🡲</span>')+'</div>'+
      '<div class="content">'+
        '<h3><a href="'+url+'">'+esc(title)+'</a></h3>'+
        '<p>'+esc(text)+'</p>'+
        '<div class="actions">'+
          '<a class="btn" href="'+url+'">Open</a>'+
          '<button type="button" class="btn" id="rand-refresh">Another</button>'+
          '<a class="btn" href="'+mw.util.getUrl("Special:Random")+'">Special:Random</a>'+
        '</div>'+
      '</div>';
    box.classList.remove('loading');
    var btn=document.getElementById('rand-refresh');
    if(btn) btn.addEventListener('click',function(){ box.classList.add('loading'); load(); });
  }
 
  function load(){
    // 1) vezmi náhodnú stránku (id + title)
    api.get({ action:'query', formatversion:2, list:'random', rnnamespace:0, rnlimit:1 })
      .then(function(r){
        var it=r && r.query && r.query.random && r.query.random[0];
        if(!it) throw new Error('no random page');
        var pageid=it.id;          // <— použijeme pageid, nie title
        var title=it.title;
 
        // 2) parse cez pageid (vyhne sa missingtitle)
        return api.get({
          action:'parse', pageid:pageid, prop:'text|images', redirects:1
        }).then(function(p){
          var html=p.parse && p.parse.text && p.parse.text['*'] || '';
          var images=p.parse && p.parse.images || [];
          var text=excerptFromHTML(html, 420);
          var file=firstRaster(images);
          return thumbUrl(file).then(function(url){ render(title, text, url); });
        });
      })
      .catch(function(e){
        console.error('[teaser] failed:', e);
        box.classList.remove('loading');
        box.innerHTML='<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>';
      });
  }
 
   load();
   load();
});
});

Revision as of 10:08, 5 September 2025

/* Any JavaScript here will be loaded for all users on every page load. */

/* -----------------------------------------
   jQuery UI tabs (safe) – won't break page
------------------------------------------*/
mw.loader.using(['jquery.ui']).then(function () {
  try {
    if ($("[class^=portal_vtab]").length) {
      $("[class^=portal_vtab]").tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
      $("[class^=portal_vtab] li").removeClass("ui-corner-top").addClass("ui-corner-left");
    }

    var $tabs = $("#portal_slider");
    if ($tabs.length) {
      $tabs.tabs({ fx: { opacity: 'toggle', duration: 100 } });

      function selectTab(idx) {
        idx = parseInt(idx, 10) || 0;
        $tabs.tabs("option", "active", idx);
      }

      $("[class*=portal_sliderlink]").on('click', function (e) {
        e.preventDefault();
        var m = this.className.match(/portal_sliderlink-(\d+)/);
        if (m) selectTab(m[1]);
      });

      $('#portal_next').on('click', function (e) {
        e.preventDefault();
        var active = $tabs.tabs("option", "active");
        var total  = $tabs.find("> ul > li").length || 1;
        selectTab((active + 1) % total);
      });

      $('#portal_prev').on('click', function (e) {
        e.preventDefault();
        var active = $tabs.tabs("option", "active");
        var total  = $tabs.find("> ul > li").length || 1;
        selectTab((active - 1 + total) % total);
      });
    }
  } catch (err) {
    console.warn('[tabs] disabled due to error:', err);
  }
});

/* -----------------------------------------
   ReferencePopups lockdown + upload tweak
------------------------------------------*/
((window.dev = window.dev || {}).ReferencePopups = dev.ReferencePopups || {}).lockdown = true;
mw.config.set('UMFBypassLicenseCheck', true);

/* -----------------------------------------
   Hide Admin toolbox for non-admins
------------------------------------------*/
mw.loader.using('mediawiki.util').then(function () {
  try {
    var g = mw.config.get('wgUserGroups') || [];
    var isAdmin = g.indexOf('sysop') !== -1 || g.indexOf('interface-admin') !== -1;
    if (!isAdmin) {
      document.querySelectorAll('.only-sysop').forEach(function (el) { el.style.display = 'none'; });
    }
  } catch (e) {
    console.warn('[only-sysop] hide failed:', e);
  }
});

/* ==========================================================
   RANDOM PAGE TEASER – robust, pageid-based, no extensions
   Renders into <div id="random-teaser" class="random-card">
========================================================== */
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () {
  var box = document.getElementById('random-teaser');
  if (!box) return; // run only if the container exists

  var api = new mw.Api();
  var THUMB_W = 280;

  function esc(s){ return mw.html.escape(String(s || '')); }

  function excerptFromHTML(html, maxChars) {
    var d = document.createElement('div');
    d.innerHTML = html;
    // pick first meaningful paragraph
    var p = d.querySelector('p');
    var t = (p ? p.innerText : d.innerText || '').replace(/\s+/g, ' ').trim();
    if (t.length > maxChars) t = t.slice(0, maxChars).replace(/\s+\S*$/, '') + '…';
    return t || 'No description available.';
  }

  function firstRaster(list) {
    if (!Array.isArray(list) || !list.length) return null;
    // Prefer raster formats
    var pick = list.find(function (t) { return /\.(jpe?g|png|gif|webp)$/i.test(t || ''); });
    return pick || list[0] || null;
  }

  function getThumbUrl(fileTitle) {
    if (!fileTitle) return Promise.resolve(null);
    return api.get({
      action: 'query',
      formatversion: 2,
      titles: fileTitle,
      prop: 'imageinfo',
      iiprop: 'url',
      iiurlwidth: THUMB_W
    }).then(function (r) {
      var p = r.query && r.query.pages && r.query.pages[0];
      var ii = p && p.imageinfo && p.imageinfo[0];
      return (ii && (ii.thumburl || ii.url)) || null;
    }).catch(function (e) {
      console.warn('[teaser] imageinfo failed:', e);
      return null;
    });
  }

  function render(title, text, imgUrl) {
    var url = mw.util.getUrl(title);
    box.innerHTML =
      '<div class="thumb">' +
        (imgUrl ? '<img src="' + esc(imgUrl) + '" alt="">' : '<span>🡲</span>') +
      '</div>' +
      '<div class="content">' +
        '<h3><a href="' + url + '">' + esc(title) + '</a></h3>' +
        '<p>' + esc(text) + '</p>' +
        '<div class="actions">' +
          '<a class="btn" href="' + url + '">Open</a>' +
          '<button type="button" class="btn" id="rand-refresh">Another</button>' +
          '<a class="btn" href="' + mw.util.getUrl('Special:Random') + '">Special:Random</a>' +
        '</div>' +
      '</div>';

    box.classList.remove('loading');

    var btn = document.getElementById('rand-refresh');
    if (btn) btn.addEventListener('click', function () {
      box.classList.add('loading');
      load();
    });
  }

  function load() {
    // 1) Random page with pageid (stable)
    api.get({
      action: 'query',
      formatversion: 2,
      generator: 'random',
      grnnamespace: 0,
      grnlimit: 1,
      prop: 'info'
    }).then(function (q) {
      var pg = q.query && q.query.pages && q.query.pages[0];
      if (!pg) throw new Error('No random page');
      var pageid = pg.pageid;
      var title  = pg.title;

      // 2) Parse via pageid → HTML + images (avoids missingtitle)
      return api.get({
        action: 'parse',
        pageid: pageid,
        prop: 'text|images',
        redirects: 1
      }).then(function (p) {
        var html   = p.parse && p.parse.text && p.parse.text['*'] || '';
        var images = p.parse && p.parse.images || [];
        var text   = excerptFromHTML(html, 420);
        var file   = firstRaster(images);

        // 3) Resolve thumbnail (if any)
        return getThumbUrl(file).then(function (thumb) {
          render(title, text, thumb);
        });
      });
    }).catch(function (e) {
      console.error('[teaser] failed:', e);
      box.classList.remove('loading');
      box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>';
    });
  }

  // Initial load
  load();
});