MediaWiki

BibTest.js: Difference between revisions

From Illustrations in German Translations of Mark Twain's Works

No edit summary
No edit summary
Line 37: Line 37:


   // Sonderfarbe für Twain-Werke
   // Sonderfarbe für Twain-Werke
  const orangeTags = [
const orangeTags = [
    'a connecticut yankee in king arthur\'s court',
  'a connecticut yankee in king arthur\'s court',
    'adventures of huckleberry finn',
  'adventures of huckleberry finn',
    'pudd\'nhead wilson',
  'pudd\'nhead wilson',
    'roughing it',
  'roughing it',
    'the adventures of tom sawyer',
  'the adventures of tom sawyer',
    'the innocents abroad'
  'the innocents abroad'
  ];
];


  if (orangeTags.includes(originalName.toLowerCase())) {
if (orangeTags.includes(originalName.toLowerCase())) {
    span.classList.add('twain-work');
  span.classList.add('twain-work');
  }
}
  // Sonderfarbe für Illustratoren
 
// Sonderfarbe für Illustratoren
const illustratorTags = [
const illustratorTags = [
   'kemble, edward w.',
   'kemble, edward w.',
Line 56: Line 57:
   'williams, truman w.'
   'williams, truman w.'
];
];
if (illustratorTags.includes(originalName.toLowerCase())) {
  span.classList.add('illustrator-tag');
}


   span.onclick = () => toggleTag(originalName, span, normalized);
   span.onclick = () => toggleTag(originalName, span, normalized);

Revision as of 16:47, 13 July 2026

/**
 * Bibliography Tag Filter, Sorting and Search
 */

(function() {
  'use strict';

  let ACTIVE_TAGS = new Set();
  let SEARCH_TERM = '';

  function init() {
    const tagBar = document.getElementById('tagBar');
    const bibliography = document.getElementById('listView');
    const searchInput = document.getElementById('bibSearch');
    
    if (!tagBar || !bibliography) return;

    

    // Sammle alle Original-Tagnamen aus den Einträgen
    const allTagsMap = new Map();
    document.querySelectorAll('.bib-entry .tag').forEach(tagEl => {
      const originalName = tagEl.textContent.trim();
      const normalized = normalizeTag(originalName);
      allTagsMap.set(normalized, originalName);
    });

    // Lösche alte Tags aus tagBar (aber nur einmal!)
    if (tagBar.children.length === 0) {
      Array.from(allTagsMap.entries())
        .sort((a, b) => a[1].localeCompare(b[1]))
        .forEach(([normalized, originalName]) => {
  const span = document.createElement('span');
  span.className = 'tag inactive';
  span.textContent = originalName;
  span.dataset.normalized = normalized;

  // Sonderfarbe für Twain-Werke
const orangeTags = [
  'a connecticut yankee in king arthur\'s court',
  'adventures of huckleberry finn',
  'pudd\'nhead wilson',
  'roughing it',
  'the adventures of tom sawyer',
  'the innocents abroad'
];

if (orangeTags.includes(originalName.toLowerCase())) {
  span.classList.add('twain-work');
}

// Sonderfarbe für Illustratoren
const illustratorTags = [
  'kemble, edward w.',
  'senior, frank m.',
  'warren, calvin h.',
  'williams, truman w.'
];

if (illustratorTags.includes(originalName.toLowerCase())) {
  span.classList.add('illustrator-tag');
}

  span.onclick = () => toggleTag(originalName, span, normalized);
  tagBar.appendChild(span);
});
    }

    // Search Input Listener
    if (searchInput && !searchInput.dataset.listenerSet) {
      searchInput.addEventListener('input', (e) => {
        SEARCH_TERM = e.target.value.toLowerCase();
        filterEntries();
      });
      searchInput.dataset.listenerSet = 'true';
    }

    sortEntries();



if (illustratorTags.includes(originalName.toLowerCase())) {
  span.classList.add('illustrator-tag');
}

removeEmptyAbstractButtons();
removeEmptyNotesButtons();

collapseAbstractsInitially();
collapseNotesInitially();

setupClickHandlers();
  }

 function removeEmptyAbstractButtons() {
  document.querySelectorAll('.bib-entry').forEach(entry => {

    const abstractDiv = entry.querySelector('.abstract');
    const button = entry.querySelector('.expand-btn');

    if (!abstractDiv || !button) return;

    const text = abstractDiv.textContent.trim();

    // Nur prüfen ob leer bzw. Platzhaltertext
    if (
      text === '' ||
      text === 'No abstract available.'
      
    ) {
      button.remove();
      abstractDiv.remove();
    }
  });
}
function collapseAbstractsInitially() {
  document.querySelectorAll('.abstract').forEach(el => {
    el.classList.add('hidden');
    el.style.display = ''; // entfernt evtl. inline overrides
  });
}

function removeEmptyNotesButtons() {
  document.querySelectorAll('.bib-entry').forEach(entry => {

    const notesDiv = entry.querySelector('.notes');
    const button = entry.querySelector('.expand-btn-notes');

    if (!notesDiv || !button) return;

    const text = notesDiv.textContent.trim();

    if (text === '') {
      button.remove();
      notesDiv.remove();
    }
  });
}
function collapseNotesInitially() {
  document.querySelectorAll('.notes').forEach(notesDiv => {
    notesDiv.classList.add('hidden');
  });
}
  function setupClickHandlers() {
    document.removeEventListener('click', handleClicks);
    document.addEventListener('click', handleClicks);
  }

  function handleClicks(e) {

  // =========================
  // ABSTRACT TOGGLE
  // =========================
  if (e.target.classList.contains('expand-btn') &&
      !e.target.classList.contains('expand-btn-notes')) {

    const entry = e.target.closest('.bib-entry');
    const abstractDiv = entry?.querySelector('.abstract');

    if (!abstractDiv) return;

    const isHidden = abstractDiv.classList.toggle('hidden');

    e.target.textContent = isHidden
      ? 'Show Abstract'
      : 'Hide Abstract';
  }

  // =========================
  // NOTES TOGGLE
  // =========================
  if (e.target.classList.contains('expand-btn-notes')) {

    const entry = e.target.closest('.bib-entry');
    const notesDiv = entry?.querySelector('.notes');

    if (!notesDiv) return;

    const isHidden = notesDiv.classList.toggle('hidden');

    e.target.textContent = isHidden
      ? 'Show Notes'
      : 'Hide Notes';
  }
}

  function toggleTag(tagName, element, normalized) {
    if (ACTIVE_TAGS.has(normalized)) {
      ACTIVE_TAGS.delete(normalized);
      element.classList.remove('active');
      element.classList.add('inactive');
    } else {
      ACTIVE_TAGS.add(normalized);
      element.classList.add('active');
      element.classList.remove('inactive');
    }
    filterEntries();
  }

  function sortEntries() {
    const container = document.getElementById('listView');
    if (!container) return;

    const entries = Array.from(container.querySelectorAll('.bib-entry'));
    
    entries.sort((a, b) => {
      const titleA = a.querySelector('h3')?.textContent || '';
      const titleB = b.querySelector('h3')?.textContent || '';
      return titleA.localeCompare(titleB);
    });

    entries.forEach(entry => container.appendChild(entry));
  }

  function normalizeTag(tag) {
    return tag.toLowerCase().replace(/\s+/g, '_').replace(/,/g, '').replace(/\./g, '').replace(/'/g, '').replace(/"/g, '');
  }

  function matchesSearch(entry) {
    if (!SEARCH_TERM) return true;

    const searchText = SEARCH_TERM;
    
    const title = entry.querySelector('h3')?.textContent || '';
    if (title.toLowerCase().includes(searchText)) return true;

    const tagElements = entry.querySelectorAll('.tag');
    for (let tag of tagElements) {
      if (tag.textContent.toLowerCase().includes(searchText)) return true;
    }

    const abstractDiv = entry.querySelector('.abstract');
    if (abstractDiv) {
      const abstractText = abstractDiv.textContent || '';
      if (abstractText.toLowerCase().includes(searchText)) return true;
    }

    const notesDiv = entry.querySelector('.notes');
    if (notesDiv) {
      const notesText = notesDiv.textContent || '';
      if (notesText.toLowerCase().includes(searchText)) return true;
    }

    return false;
  }

  function filterEntries() {
    const entries = document.querySelectorAll('.bib-entry');
    
    entries.forEach(entry => {
      const entryTags = (entry.getAttribute('data-tags') || '').split(' ').filter(t => t);
      
      let matchesTags = true;
      if (ACTIVE_TAGS.size > 0) {
        matchesTags = Array.from(ACTIVE_TAGS).every(activeTag => {
          return entryTags.includes(activeTag);
        });
      }

      const matchesSearchTerm = matchesSearch(entry);

      entry.style.display = (matchesTags && matchesSearchTerm) ? 'block' : 'none';
    });
  }

  // Starte wenn DOM bereit
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }

  document.addEventListener('DOMContentLoaded', init);
})();