Friedel: Dursuchbares Archiv mit <details>

Hallo, ich habe für einen Verein ein Beschlussarchiv in Html erstellt. Es wurde wert darauf gelegt, dass das ganze nur mit Html (und CSS) funktioniert. Ohne Php und vor allem ohne Datenbank.

Ich habe dazu die vielen Beschlüsse jeweils in einen Container nach folgendem Muster gepackt.

      <details class="angenommen">
        <summary>Titel des Beschlusses</summary>
        <p>Beschlossen durch Telefonkonferenz</p>
        <dl class="boxKopf">
          <dt>Antragstext:<br><img src="Pictogramme/angenommen.svg" alt="angenommen" class="status"></dt>
          <dd>Hier steht der Antragstext</dd>
        </dl>
        Hier folgen weitere Inhalte, z.B. ein Abstimmungsergebnis
     </details>

Das ist auch alles OK. Nur soll das ganze natürlich durchsuchbar sein. Leider durchsucht die browserinterne Suche (mit Strg + f) nur die aufgeklappten Container. Kann man das irgendwie beeinflussen. Die Suche hat ja meist den Zweck, einen Beschluss zu finden, wenn man dessen Titel nicht kennt.

Falls das nicht geht, gibt es eine Möglichkeit, alle details-Container z.B. mit einem Button aufzuklappen?

  1. @@Friedel

    gibt es eine Möglichkeit, alle details-Container z.B. mit einem Button aufzuklappen?

    Ja: die open-Eigenschaft aller details-Elemente auf true setzen. ☞ Codepen

    🖖 Живіть довго і процвітайте

    --
    When the power of love overcomes the love of power the world will know peace.
    — Jimi Hendrix
    1. Ich mache Schluss für heute. Wenn ich dein Beispiel aus dem Codepen nachbaue, funktioniert es nicht. Wenn den Nachbau wieder in Codepen kopiere, funktioniert es. Ich finde keinen Fehler. Ich denke, ich habe alle möglichen Fehlerquelle ausgeschlossen. Ich habe sogar testweise ein alert("jhgfjhc"); an den Anfang vom Script eingebaut. Der Alert kommt. Das Script sollte also ausgeführt werden.

      Ich habe deinen Codepen getestet → funktioniert.

      Ich habe deinen Quellcode in eine Html-, CSS- und JS-Datei kopiert → funktioniert nicht.

      Ich habe dein Script in meine Seite eingebaut → funktioniert nicht.

      Ich die so veränderte Seite in Codepen kopiert → funktioniert.

      Ich bin ratlos.

      1. Hallo Friedel,

        alert("jhgfjhc");

        Das ist das Debug-Tool von 1999. Heute haben Browser Entwicklerwerkzeuge, wo man Breakpoints setzen kann und wo man in der Konsole Fehlermeldungen bekommt, wenn Syntax-Fehler im Script sind.

        Welche Fehlermeldung steht bei Dir in der Konsole?

        Wenn alle Stricke reißen: Stell die Seite (oder eine anonymisierte Version davon) online, damit wir draufschauen können.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. alert("jhgfjhc");

          Das ist das Debug-Tool von 1999. Heute haben Browser Entwicklerwerkzeuge, wo man Breakpoints setzen kann und wo man in der Konsole Fehlermeldungen bekommt, wenn Syntax-Fehler im Script sind.

          Sollte 2022 in jedem Browser funktionieren, im Gegensatz zu 1999. Da ging sowas nicht in jedem Browser.

          Welche Fehlermeldung steht bei Dir in der Konsole?

          Uncaught TypeError: document.querySelector(...) is null
              <anonymous> file:///Pfad/beschlussarchiv.js:13
          beschlussarchiv.js:13:10
              <anonym> file:///Pfad/beschlussarchiv.js:13
          

          Und in file:///Pfad/beschlussarchiv.js:13 steht:

          document.querySelector('#open-all').addEventListener(
          
          1. Liebe(r) Friedel,

            Uncaught TypeError: document.querySelector(...) is null
                <anonymous> file:///Pfad/beschlussarchiv.js:13
            beschlussarchiv.js:13:10
                <anonym> file:///Pfad/beschlussarchiv.js:13
            

            Und in file:///Pfad/beschlussarchiv.js:13 steht:

            document.querySelector('#open-all').addEventListener(
            

            die Fehlermeldung will Dir sagen, dass im Dokument kein Element mit der ID open-all gefunden werden konnte.

            Liebe Grüße

            Felix Riesterer

            1. Was so ein Feierabend alles bewirken kann …

              Heute morgen kurz drüber geschaut und verwundert gedacht: Das kann doch nicht gehen. Das ganze Script in eine init() gepackt und mit DOMContentLoaded aufgerufen → funktioniert.

              1. @@Friedel

                Heute morgen kurz drüber geschaut und verwundert gedacht: Das kann doch nicht gehen. Das ganze Script in eine init() gepackt und mit DOMContentLoaded aufgerufen → funktioniert.

                Mit dem Script an der richtigen™ Stelle wäre das nicht passiert: am Ende des body. Dann blockiert das Laden und Ausführen des Scripts nicht die Generierung des DOM und das Rendern der Seite – Performancegewinn.

                Und DOMContentLoaded braucht man dann auch nicht.

                🖖 Живіть довго і процвітайте

                --
                When the power of love overcomes the love of power the world will know peace.
                — Jimi Hendrix
  2. Hallo Friedel,

    darf auch JavaScript verwendet werden?

    Damit könntest Du die Textinhalte durchsuchen und die Container, in denen Du den Text antriffst, aufklappen.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo,

      darf auch JavaScript verwendet werden?

      das hoffe ich doch stark. Denn die browsereigene Suche (Ctrl-F) findet meines Wissens nur Text, der auch aktuell angezeigt wird.[1]

      Damit könntest Du die Textinhalte durchsuchen und die Container, in denen Du den Text antriffst, aufklappen.

      Das ist noch zielführender und näher an der Frage als Gunnars Tipp, einfach alle detail-Elemente aufzuklappen.

      Einen schönen Tag noch
       Martin

      --
      Мир для України.

      1. Ich schrieb bewusst nicht "sichtbar ist". Denn Ctrl-F findet auch Text, der in Weiß auf Weiß gesetzt ist, oder Schriftgröße 0 hat. Aber eben nicht in unsichtbaren Elementen (hidden-Attribut, display:none oder eben zugeklappte details-Elemente. ↩︎

      1. darf auch JavaScript verwendet werden?

        das hoffe ich doch stark. Denn die browsereigene Suche (Ctrl-F) findet meines Wissens nur Text, der auch aktuell angezeigt wird.[^1]

        Es wäre besser, wenn es ohne JavaScript ginge. Aber das geht offensichtlich nicht.

        Damit könntest Du die Textinhalte durchsuchen und die Container, in denen Du den Text antriffst, aufklappen.

        Das ist noch zielführender und näher an der Frage als Gunnars Tipp, einfach alle detail-Elemente aufzuklappen.

        Das erscheint mir sinnvoll, die Idee ist mir aber nicht gekommen. Näher an der Frage ist es sicher nicht.

        Falls das nicht geht, gibt es eine Möglichkeit, alle details-Container z.B. mit einem Button aufzuklappen?

        1. @@Friedel

          Es wäre besser, wenn es ohne JavaScript ginge. Aber das geht offensichtlich nicht.

          Du hattest selbst JavaScript ins Spiel gebracht.


          Damit könntest Du die Textinhalte durchsuchen und die Container, in denen Du den Text antriffst, aufklappen.

          Das ist noch zielführender und näher an der Frage als Gunnars Tipp, einfach alle detail-Elemente aufzuklappen.

          Das erscheint mir sinnvoll, die Idee ist mir aber nicht gekommen. Näher an der Frage ist es sicher nicht.

          Vielleicht nicht näher an deiner Frage, aber näher an deinem Problem.

          ☞ neuer Codepen:

          • Der Einfachheit halber lasse ich in dem Beispiel nur in den details-Elementen suchen; das sollte man eigentlich im ganzen body tun.
          • Statt innerHTML könnte man besser einen TreeWalker verwenden?
          • Gefundene Treffer werden jeweils mit einem mark-Element ausgezeichnet.

          🖖 Живіть довго і процвітайте

          --
          When the power of love overcomes the love of power the world will know peace.
          — Jimi Hendrix
          1. @@Gunnar Bittersmann

            ☞ neuer Codepen:

            Das steckt noch ein Fehler drin. In den Artikeln 1 und 3 kommt „Recht“ vor; das wird aber nicht gefunden. Wieso nicht? Wer findet den Fehler?

            🖖 Живіть довго і процвітайте

            --
            When the power of love overcomes the love of power the world will know peace.
            — Jimi Hendrix
            1. Hallo Gunnar,

              includes ist case sensitive. Entweder toLowerCase auf den textContent (was vermutlich auch bei toLocaleLowerCase im Unicode-Dschungel zu Problemen führen kann) oder du musst zum Suchen schon die Regex benutzen. Und die bitte vor dem foreach erzeugen, nicht pro Durchlauf.

              Rolf

              --
              sumpsi - posui - obstruxi
              1. @@Rolf B

                includes ist case sensitive.

                🤦‍♂️

                oder du musst zum Suchen schon die Regex benutzen.

                Im Codepen geändert: detailsElement.textContent.includes(term)) zu regexp.test(detailsElement.textContent)).

                Und die bitte vor dem foreach erzeugen, nicht pro Durchlauf.

                Isch ’abe gar kein forEach. 😉

                Aber ja, natürlich außerhalb der Schleife; wo denn sonst?

                🖖 Живіть довго і процвітайте

                --
                When the power of love overcomes the love of power the world will know peace.
                — Jimi Hendrix
            2. Hallo Gunnar,

              ich hab gebastelt und bin damit rausgekommen:

              const detailsElements = document.querySelectorAll('details');
              
              document.forms['search-form']?.addEventListener('submit', (event) => {
              	event.preventDefault();
              	const term = document.forms['search-form'].elements.search.value;
              	if (!term) {
              		for (let detailsElement of detailsElements) {
              			detailsElement.open = false;
              		}	
              	}	
              	else {
              		const matcher = new RegExp(`(${term})`, 'gi');
              		for (let detailsElement of detailsElements) {
              			let html = detailsElement.innerHTML.replace(/<\/?mark>/g, '');
              			if (matcher.test(detailsElement.textContent)) {
              				html = html.replace(matcher, '<mark>$1</mark>');
              				detailsElement.open = true;
              			}
              			else {
              				detailsElement.open = false;
              			}
              			detailsElement.innerHTML = html;
              		}		
              	}
              });
              

              Die Version, die mir wegen der Polymorphie noch besser gefällt, aber schon unter "write-only" laufen müsste, ist:

              const detailsElements = document.querySelectorAll('details');
              
              document.forms['search-form']?.addEventListener('submit', (event) => {
              	event.preventDefault();
              	const term = document.forms['search-form'].elements.search.value;
              	const matcher = term ?
              				new RegExp(`(${term})`, 'gi') :
              				{ test: () => false };
              
              	for (let detailsElement of detailsElements) {
              		let html = detailsElement.innerHTML.replace(/<\/?mark>/g, '');
              		detailsElement.open = matcher.test(detailsElement.textContent);
              		if (detailsElement.open) {
              			html = html.replace(matcher, '<mark>$1</mark>');
              		}
              		detailsElement.innerHTML = html;
              	}
              });
              

              Rolf

              --
              sumpsi - posui - obstruxi
          2. Servus!

            ...

            Vielleicht nicht näher an deiner Frage, aber näher an deinem Problem.

            ☞ neuer Codepen:

            • Der Einfachheit halber lasse ich in dem Beispiel nur in den details-Elementen suchen; das sollte man eigentlich im ganzen body tun.
            • Statt innerHTML könnte man besser einen TreeWalker verwenden?
            • Gefundene Treffer werden jeweils mit einem mark-Element ausgezeichnet.

            🖖 Живіть довго і процвітайте

            @@Gunnar Bittersmann Vielen Dank! Das ist ein sehr schönes Beispiel.

            Die Frage nach „Suchen innerhalb einer Seite“ kommt immer wieder. Als Linuchs im Januar/Februar danach gefragt hatte, hatte ich mal einen Stub im Wiki aufgesetzt:

            Ich habe im Moment nur keine Zeit dazu.

            Herzliche Grüße

            Matthias Scharwies

            --
            Einfach mal was von der ToDo-Liste auf die Was-Solls-Liste setzen.“
            1. Hallo,

              unter „PHP-Suchscripte“ würde auch die Suchmaschine von Werner Zenk gut reinpassen.

          3. @@Gunnar Bittersmann

            ☞ neuer Codepen:

            Und noch einen Fehler berichtigt: das ARIA-Attribut role="search" am form-Element hatte gefehlt.

            (Bei der Gelegenheit auch noch die Namen von form und input geändert.)

            🖖 Живіть довго і процвітайте

            --
            When the power of love overcomes the love of power the world will know peace.
            — Jimi Hendrix
            1. Da sind noch mehr Fehler drin. Eine Suche nach s findet z.B. auch das s in <summary> und zerschießt damit die dl. Textstellen, die nach einem Slash stehen, werden nicht gefunden. Ein „recht“ in „Pflicht/Recht“ wird daher nicht gefunden. Trotzdem vielen Dank für die tollen Vorlagen.

              Inzwischen gibt es bei mir einen einen großen Fortschritt, der das ganze vielleicht überflüssig macht. Das Beschlussarchiv umfasst bis jetzt mehrere Hundert Beschlüsse und es kommen immer wieder welche dazu. Offensichtlich hatten einige Vorstandsmitglieder die irre Vorstellung, dass ich das ganze auch noch in eine Typo3-Website einfriemle. Selbst wenn ich glauben würde, dass das möglich ist, würde ich das nicht versuchen. Nachdem ich das also ausgeschlossen habe, halten einige Vorstandsmitglieder es nicht mehr für ausgeschlossen, das ganze mit Php und Datenbank zu machen… Imho ist das auch die einzige sinnvolle Option. In wenigen Jahren wird das Archiv auf mehrere Tausend Beschlüsse gewachsen sein. Das ist nicht das ideale Umfeld für eine JavaScript-Suche. Da fehlen ja auch noch einige Features. Und JavaScript kommt da irgendwann an seine Grenzen. Dazu kommt, dass das ganze auch auf dem Smartphone funktionieren muss. Ich habe kein Smartphone und die Testumgebungen, die der Firefox und andere Browser auf dem Desktop bieten, sind nicht wirklich geeignet, um die Performance und Usability auf dem Smartphone zu testen. Da kann man meist nur Anhaltspunkte über die Eignung des Layouts gewinnen.

    2. @@Rolf B

      Hallo Friedel,

      darf auch JavaScript verwendet werden?

      Die Frage hatte Friedel schon beantwortet, bevor du sie gestellt hast: „gibt es eine Möglichkeit, alle details-Container z.B. mit einem Button aufzuklappen?“

      Buttons tun 2½erlei Dinge:

      • ein Formular absenden. Das will Friedel nicht.
      • (die Eingaben in einem Formular zurücksetzen. Dafür gibt es kaum sinnvolle Anwendungsfälle.)
      • Eine Aktion (JavaScript) auf der Seite ausführen. Das ist hier gefragt.

      🖖 Живіть довго і процвітайте

      --
      When the power of love overcomes the love of power the world will know peace.
      — Jimi Hendrix
  3. @@Friedel

    Leider durchsucht die browserinterne Suche (mit Strg + f) nur die aufgeklappten Container.

    Chrome hat da eine Idee: hidden="until-found" (via Stefan Judis)

    🖖 Живіть довго і процвітайте

    --
    When the power of love overcomes the love of power the world will know peace.
    — Jimi Hendrix
  4. @@Friedel

    Leider durchsucht die browserinterne Suche (mit Strg + f) nur die aufgeklappten Container.

    In Firefox und Safari ist das so.

    In Chromia (Chrome, Edge) wird auch in zugeklappten details gesucht und diese werden bei Treffern automatisch aufgeklappt – genau, wie du es willst.

    Wäre wünschenswert, wenn andere das auch so machen würden. Gleich mal Tickets für Firefox und Safari angelegt.

    🖖 Живіть довго і процвітайте

    --
    When the power of love overcomes the love of power the world will know peace.
    — Jimi Hendrix