MediaWiki:Common.js: Difference between revisions

From SZ
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
/**
/**
  * Collapsible Sidebar (Debug Build) for MW 1.44 (Vector + Vector 2022)
  * Collapsible Sidebar (Debug Build) - Patched for Vector & Vector 2022
  * - Writes verbose logs to the console
  * Logs everything to console for verification
* - Inserts a real <span> arrow (▶), so you see it even if :before fails
* - No jquery.cookie, no extra modules
*
* Toggle logging at runtime with: window.MWSidebarDebug = true/false
  */
  */
(function () {
(function () {
  // Turn on debug by default; you can turn off in the console if too chatty.
   window.MWSidebarDebug = true;
   window.MWSidebarDebug = true;


   function log() {
   function log() {
     if (window.MWSidebarDebug && typeof console !== 'undefined') {
     if (window.MWSidebarDebug) console.log('[SidebarCollapsible]', ...arguments);
      console.log.apply(console, ['[SidebarCollapsible]'].concat([].slice.call(arguments)));
    }
   }
   }
   function warn() {
   function warn() {
     if (typeof console !== 'undefined') {
     if (window.MWSidebarDebug) console.warn('[SidebarCollapsible]', ...arguments);
      console.warn.apply(console, ['[SidebarCollapsible]'].concat([].slice.call(arguments)));
    }
   }
   }


Line 25: Line 16:
   log('Init start. Detected skin =', skin);
   log('Init start. Detected skin =', skin);


   function findTopList($panel) {
   function findPanels($root) {
     // Works for Vector/Vector-2022 portlets and (fallback) legacy .portal markup
     // Match both Vector and Vector 2022 classes
     return $panel.find('> .vector-menu-content > .vector-menu-content-list, > .body > ul').first();
     var $panels = $root.find('#mw-panel .vector-menu-portal, #mw-panel .vector-menu.mw-portlet');
    log('Panels found:', $panels.length);
    return $panels;
   }
   }


   function initOnce($root) {
   function initOnce($root) {
     // Find all sidebar portlets that look like menus
     var $panels = findPanels($root);
    //var $panels = $('#mw-panel .vector-menu-portal, .vector-menu-portal', $root);
var $panels = $('#mw-panel .vector-menu-portal, #mw-panel .vector-menu.mw-portlet', $root);
 


     if (!$panels.length) {
     if (!$panels.length) {
       warn('No .vector-menu-portal found. Are you using Vector/Vector-2022?');
       warn('No sidebar panels found using selectors for Vector/Vector-2022');
    } else {
       return;
       log('Found', $panels.length, 'portal(s).');
     }
     }


Line 45: Line 34:
       var $panel = $(el);
       var $panel = $(el);
       var id = $panel.attr('id') || ('panel#' + idx);
       var id = $panel.attr('id') || ('panel#' + idx);
       var $list = findTopList($panel);
       var $list = $panel.find('> .vector-menu-content > .vector-menu-content-list, > .body > ul').first();


       if (!$list.length) {
       if (!$list.length) {
         warn('Panel has no UL list:', id, $panel.get(0));
         warn('No list in panel:', id);
         return;
         return;
       }
       }


       var $items = $list.children('li');
       var $items = $list.children('li');
       log('Panel', id, ':', $items.length, 'top-level <li> item(s).');
       log('Panel', id, ':', $items.length, 'top-level item(s)');


       $items.each(function (i, li) {
       $items.each(function (i, li) {
         var $li = $(li);
         var $li = $(li);
         var $sub = $li.children('ul');
         var $sub = $li.children('ul');
        if (!$sub.length) return;


        if (!$sub.length) {
          // Not a collapsible candidate
          return;
        }
        // Mark as collapsible and hide sub-list (if not already)
         $li.addClass('collapsible-header');
         $li.addClass('collapsible-header');
         if (!$li.children('.mw-collapsible-arrow').length) {
         if (!$li.children('.mw-collapsible-arrow').length) {
          // Insert a real arrow character so it’s guaranteed visible
           $li.prepend($('<span class="mw-collapsible-arrow" aria-hidden="true">▶</span>'));
           $li.prepend($('<span class="mw-collapsible-arrow" aria-hidden="true">▶</span>'));
         }
         }
         $sub.hide();
         $sub.hide();


        // Log header text for reference
         var headerText = ($li.find('> a').first().text() || '').trim();
         var headerText = ($li.find('> a').first().text() || $li.clone().children().remove().end().text() || '')
          .trim()
          .replace(/\s+/g, ' ');
         log('Registered collapsible item', i, 'in', id, 'header=', headerText);
         log('Registered collapsible item', i, 'in', id, 'header=', headerText);


        // Click to toggle (but let actual links work)
         $li.off('.mwCollapsibleSidebar')
         $li.off('.mwCollapsibleSidebar') // avoid duplicate binding
           .on('click.mwCollapsibleSidebar', function (e) {
           .on('click.mwCollapsibleSidebar', function (e) {
             if ($(e.target).closest('a').length) {
             if ($(e.target).closest('a').length) return;
              // Click on a link inside; do not toggle
              log('Link click passthrough for header:', headerText);
              return;
            }
             e.preventDefault();
             e.preventDefault();
            var willOpen = !$li.hasClass('open');
             $li.toggleClass('open');
             $li.toggleClass('open');
             $sub.stop(true, true).slideToggle(200);
             $sub.stop(true, true).slideToggle(200);
             log('Toggled', (willOpen ? 'open' : 'closed') + ':', headerText);
             log('Toggled', $li.hasClass('open') ? 'open' : 'closed', ':', headerText);
           });
           });
       });
       });
Line 96: Line 70:
   }
   }


  // Run on DOM ready and on content re-renders
   mw.loader.using('mediawiki.util').then(function () {
   mw.loader.using('mediawiki.util').then(function () {
     $(function () {
     $(function () {

Revision as of 20:48, 25 August 2025

/**
 * Collapsible Sidebar (Debug Build) - Patched for Vector & Vector 2022
 * Logs everything to console for verification
 */
(function () {
  window.MWSidebarDebug = true;

  function log() {
    if (window.MWSidebarDebug) console.log('[SidebarCollapsible]', ...arguments);
  }
  function warn() {
    if (window.MWSidebarDebug) console.warn('[SidebarCollapsible]', ...arguments);
  }

  var skin = mw.config.get('skin');
  log('Init start. Detected skin =', skin);

  function findPanels($root) {
    // Match both Vector and Vector 2022 classes
    var $panels = $root.find('#mw-panel .vector-menu-portal, #mw-panel .vector-menu.mw-portlet');
    log('Panels found:', $panels.length);
    return $panels;
  }

  function initOnce($root) {
    var $panels = findPanels($root);

    if (!$panels.length) {
      warn('No sidebar panels found using selectors for Vector/Vector-2022');
      return;
    }

    $panels.each(function (idx, el) {
      var $panel = $(el);
      var id = $panel.attr('id') || ('panel#' + idx);
      var $list = $panel.find('> .vector-menu-content > .vector-menu-content-list, > .body > ul').first();

      if (!$list.length) {
        warn('No list in panel:', id);
        return;
      }

      var $items = $list.children('li');
      log('Panel', id, ':', $items.length, 'top-level item(s)');

      $items.each(function (i, li) {
        var $li = $(li);
        var $sub = $li.children('ul');
        if (!$sub.length) return;

        $li.addClass('collapsible-header');
        if (!$li.children('.mw-collapsible-arrow').length) {
          $li.prepend($('<span class="mw-collapsible-arrow" aria-hidden="true">▶</span>'));
        }
        $sub.hide();

        var headerText = ($li.find('> a').first().text() || '').trim();
        log('Registered collapsible item', i, 'in', id, 'header=', headerText);

        $li.off('.mwCollapsibleSidebar')
          .on('click.mwCollapsibleSidebar', function (e) {
            if ($(e.target).closest('a').length) return;
            e.preventDefault();
            $li.toggleClass('open');
            $sub.stop(true, true).slideToggle(200);
            log('Toggled', $li.hasClass('open') ? 'open' : 'closed', ':', headerText);
          });
      });
    });
  }

  mw.loader.using('mediawiki.util').then(function () {
    $(function () {
      console.group && console.group('[SidebarCollapsible] bootstrap');
      initOnce($(document));
      console.groupEnd && console.groupEnd();
    });
    mw.hook('wikipage.content').add(function ($c) {
      log('wikipage.content hook fired (re-init on dynamic content).');
      initOnce($c);
    });
  });
})();