MediaWiki:CustomFiltered.js: Difference between revisions

From The Seven Sages of Rome
No edit summary
No edit summary
Tag: Reverted
Line 24: Line 24:
     $container.before($bar);
     $container.before($bar);


    // Track whether SMW is currently changing things, not us
     var $rows = $container.find('tr.filtered-table-item');
     var smwChanging = false;


    // Use a real HTML attribute (not jQuery .data()) so we can always
    // distinguish SMW state from our own display manipulation
     function snapshotSMW() {
     function snapshotSMW() {
       $container.find('tr.filtered-table-item').each(function () {
       $rows.each(function () {
         // Temporarily show the row to read SMW's intended state
         // Read the raw inline style before we touch anything
        // SMW stores its hidden state via inline style directly
         $(this).attr('data-smw-hidden', this.style.display === 'none' ? '1' : '0');
        var inlineDisplay = this.style.display;
         $(this).data('smw-hidden', inlineDisplay === 'none');
       });
       });
     }
     }
Line 38: Line 37:
     function applySearch() {
     function applySearch() {
       var term = $.trim($searchInput.val()).toLowerCase();
       var term = $.trim($searchInput.val()).toLowerCase();
       var total = 0;
       var total = $rows.length;
       var visible = 0;
       var visible = 0;


       $container.find('tr.filtered-table-item').each(function () {
       $rows.each(function () {
         var $row = $(this);
         var $row = $(this);
        total++;


         if ($row.data('smw-hidden')) {
         if ($row.attr('data-smw-hidden') === '1') {
           $row.hide();
           // Restore SMW's hidden state without triggering observer
          this.style.display = 'none';
           return;
           return;
         }
         }


         if (!term || $row.text().toLowerCase().indexOf(term) !== -1) {
         if (!term || $row.text().toLowerCase().indexOf(term) !== -1) {
           $row.show();
           this.style.display = '';
           visible++;
           visible++;
         } else {
         } else {
           $row.hide();
           this.style.display = 'none';
         }
         }
       });
       });
Line 61: Line 60:
     }
     }


    // Use a flag + timeout approach: when mutations fire, set a flag,
    // wait a tick for all SMW batch changes to settle, then snapshot + apply
     var smwTimer = null;
     var smwTimer = null;
    var observing = true;


     var observer = new MutationObserver(function (mutations) {
     var observer = new MutationObserver(function (mutations) {
      // Check if any mutation came from a filtered-table-item row
       var relevantChange = mutations.some(function (m) {
      // If yes, it's SMW changing things — snapshot after it settles
         return m.target.hasAttribute && m.target.hasAttribute('data-smw-hidden') === false
       var smwMutation = mutations.some(function (m) {
          && $(m.target).hasClass('filtered-table-item');
         return $(m.target).hasClass('filtered-table-item');
       });
       });


       if (!smwMutation) return;
       if (!relevantChange) return;
 
      // Pause observer, snapshot raw SMW state, then reapply search
      observer.disconnect();


       clearTimeout(smwTimer);
       clearTimeout(smwTimer);
Line 79: Line 77:
         snapshotSMW();
         snapshotSMW();
         applySearch();
         applySearch();
        observer.observe($container[0], observerConfig);
       }, 50);
       }, 50);
     });
     });


     observer.observe($container[0], {
     var observerConfig = {
       subtree: true,
       subtree: true,
       attributes: true,
       attributes: true,
       attributeFilter: ['style']
       attributeFilter: ['style']
     });
     };
 
    // Initial snapshot before observer starts
    snapshotSMW();
    applySearch();
 
    observer.observe($container[0], observerConfig);


     $searchInput.on('input', function () {
     $searchInput.on('input', function () {
       applySearch();
       applySearch();
     });
     });
    snapshotSMW();
    applySearch();
   }
   }



Revision as of 15:17, 27 February 2026

(function ($) {
  function init() {
    var $container = $('.filtered-views-container');
    if (!$container.length) return;

    var $bar = $('<div>', {
      id: 'smw-filter-bar',
      css: { marginBottom: '10px', display: 'flex', gap: '16px', alignItems: 'center', flexWrap: 'wrap' }
    });

    var $searchInput = $('<input>', {
      type: 'text',
      id: 'smw-search-input',
      placeholder: 'Search all columns…',
      css: { padding: '5px 10px', fontSize: '14px', border: '1px solid #ccc', borderRadius: '4px', minWidth: '250px' }
    });

    var $counter = $('<span>', {
      id: 'smw-filter-counter',
      css: { fontSize: '14px', color: '#555' }
    });

    $bar.append($searchInput, $counter);
    $container.before($bar);

    var $rows = $container.find('tr.filtered-table-item');

    // Use a real HTML attribute (not jQuery .data()) so we can always
    // distinguish SMW state from our own display manipulation
    function snapshotSMW() {
      $rows.each(function () {
        // Read the raw inline style before we touch anything
        $(this).attr('data-smw-hidden', this.style.display === 'none' ? '1' : '0');
      });
    }

    function applySearch() {
      var term = $.trim($searchInput.val()).toLowerCase();
      var total = $rows.length;
      var visible = 0;

      $rows.each(function () {
        var $row = $(this);

        if ($row.attr('data-smw-hidden') === '1') {
          // Restore SMW's hidden state without triggering observer
          this.style.display = 'none';
          return;
        }

        if (!term || $row.text().toLowerCase().indexOf(term) !== -1) {
          this.style.display = '';
          visible++;
        } else {
          this.style.display = 'none';
        }
      });

      $counter.text('Showing ' + visible + ' of ' + total + ' entries');
    }

    var smwTimer = null;

    var observer = new MutationObserver(function (mutations) {
      var relevantChange = mutations.some(function (m) {
        return m.target.hasAttribute && m.target.hasAttribute('data-smw-hidden') === false
          && $(m.target).hasClass('filtered-table-item');
      });

      if (!relevantChange) return;

      // Pause observer, snapshot raw SMW state, then reapply search
      observer.disconnect();

      clearTimeout(smwTimer);
      smwTimer = setTimeout(function () {
        snapshotSMW();
        applySearch();
        observer.observe($container[0], observerConfig);
      }, 50);
    });

    var observerConfig = {
      subtree: true,
      attributes: true,
      attributeFilter: ['style']
    };

    // Initial snapshot before observer starts
    snapshotSMW();
    applySearch();

    observer.observe($container[0], observerConfig);

    $searchInput.on('input', function () {
      applySearch();
    });
  }

  $(document).ready(function () {
    init();
  });

}(jQuery));