JavaScript: Bibliothek - Find Text

Ich möchte hier unsere bib.js um folgende Funktion erweitern:
findTxt()
Diese soll das übergeordnete Element bzw. Elemente eines Such-Strings ermitteln und zurückgeben.
Ausgangsposition der Suche ist ein Start-Element wie z.B.: document.body oder die ID eines übergeordneten Elements: #start-id (dieses sollte eindeutig sein ansonsten wird das erstgefundene Element durchsucht). Von hierab wird in einer Rekursion abwärts nach dem gesuchten Begriff/Wort gesucht und bei einem Treffer das Eltern-Element zurückgegeben.
Diese Funktion erwartet 2 Parameter findTxt( root , text ):

  • root: übernimmt die Ausgangsposition der Suche:
  • text: übernimmt den zu findenden Suchbegriff
Doch sehen wir uns das genauer an:

HTML
...
<div id="wrapper">
	Das ist ein Beispieltext
	<div id="ebene-1" class="cl-ebene-1">
		dem Du <span id="span-eins" class="sp-eins">bitte keine</span> Beachtung
		<p id="p-1">schenken solltest.</p>
		<div id="ebene-2">
			Aber in diesem Beispieltext <span id="span-zwei" class="new-class">kannst Du auch</span> den Text finden.
		</div>
	</div>
</div>
...

Suchen wir z.B. das Wort: Beispieltext oder Du, sollten wir zwei Treffer erhalten.
Um das zu erreichen sehen wir uns ersteinmal die Rekursion in unserer Funktion genauer an.

bib.js
function findTxt( root , text ){
	...
	// Rekursion starten
	const walker  = document.createTreeWalker( 
		root, // Start der Suche (Node)
		NodeFilter.SHOW_TEXT, // durchsucht Text-Knoten
		null, // Platzhalter für zusätzliche Filterregeln
		false
	);
	...
}

Da wir ja mehr als nur einen Treffer erzielen können müssen wir dafür sorge tragen, dass wir den/die Treffer in einem Array speichern: const results = []
Die Methode document.createTreeWalker(...) startet die Rekursion. Sie erwartet folgende Parameter:

  • root,
  • whatToShow,
  • filter

Jetzt können wir unser Funktion erweitern:

bib.js
function findTxt( root , text ){
	const results = []; // Array für Treffer
	
	// Rekursion starten
	const walker  = document.createTreeWalker( 
		root, // Start der Suche (Node)
		NodeFilter.SHOW_TEXT, // durchsucht Text-Knoten
		null, // Platzhalter für zusätzliche Filterregeln
		false
	);
	
	let node;
	// Solange unterhalb des Startelementes Nodes/Elemente zu finden sind
	while( node = walker.nextNode() ){ 
		// Wenn Suchbegriff gefunden wurde in results pushen
		if( node.textContent.includes( text ) ){
			// Array füllen mit dem Parent-Node/Eltern-Element
			results.push(node.parentElement);
		}
	}
	return results;
}

Jetzt müssen wir unsere Suche bzw. das Ergebnis der Suche auslesen. Und hierbei kommt es jetzt darauf an:

  1. Was wollen wir als Ergebnis?
    1. Ausgabe: id's
    2. Ausgabe Classennamen
  2. Wie rufen wir unsere Funktion auf?
    1. findTxt( getObj('#wrapper') , 'Suchbegriff' ) oder
    2. findTxt( '#wrapper' , 'Suchbegriff' )
Ich persönlich finde den Aufruf 2.2 am sympathischsten.
Denn wir wollen unseren Code ja kurz halten.
Doch hierfür müssen wir unsere Funktion noch ein kleines Bisschen anpassen:

bib.js
function findTxt( myroot , text ){
	// Zuweisung des Elementes für den Start der Suche
	const root = getObj( myroot ); 
	...
}

Jetzt wo wir das angepasst haben sehen wir uns die Auswertung an.
Hierfür benötigen wir eine Schleife, denn das Ergebnis befindet sich ja in dem Array results.

JavaScript
// Ausführen
const textNodes = findTxt( '#wrapper' , 'Suchbegriff');
// Array auslesen
textNodes.forEach( el => {
	// Ausgabe für id's
	el.id;
	...
	// Ausgabe für ClassName
	el.className;
	...
	// Do somthing
});

Ob man hier mit einer forEach() arbeiten möchte, überlasse ich Euch.
Möglich wäre auch while()

Wenn Ihr Anregungen oder Kommentare habt, seid so nett und kontaktiert mich unter: Kontakt

Kopiert Euch gerne den Code und probiert es aus: Code
Kopiert Euch die gesamte bib.js als bib.txt: Code

Beispiel
Das ist ein Beispieltext
dem Du bitte keine Beachtung

schenken solltest.

Aber in diesem Beispieltext kannst Du auch den Text finden.

Gib uns alle Eletern-Elemente aus für:

Suchbegriff:

Ausgabe:

Ausgabe:


Code
HTML: <div id="wrapper" class="my-wrapper"> Das ist ein Beispieltext <div id="ebene-1" class="cl-ebene-1"> dem Du <span id="span-eins" class="sp-eins">bitte keine</span> Beachtung <p id="p-1" class="p-1">schenken solltest.</p> <div id="ebene-2" class="eb-2"> Aber in diesem Beispieltext <span id="span-zwei" class="new-class">kannst Du auch</span> den Text finden. </div> </div> </div> <p class="my-fett"> Gib uns alle Eletern-Elemente aus für: </p> <form name="skillflow"> <p> Suchbegriff:<br> <select id="suche"> <option value="Beispieltext">Beispieltext</option> <option value="Du">Du</option> <option value="bitte">bitte</option> <option value="schenken">schenken</option> <option value="finden">finden</option> </select> </p> <p> Ausgabe:<br> <select id="selector"> <option value="id">id</option> <option value="className">className</option> </select> </p> </form> <div id="target"> <span>Ausgabe:</span><br> <div id="ausgabe" class="fett commentar"></div> </div> </div> <br> <button id="buttonid" class="ancor_button" name="buttonname" onclick="newAusgabe()">Ausgeben</button>

CSS: .example-wrapper select, .example-wrapper option{ color: var(--black) !important; } .my-fett{ font-weight: 600; color: rgba(112, 175, 4, 1) !important; }

JavaScript: bib.js: /* START::: getObj() */ function getObj ( identifier ) { const idfName = identifier; // Element speichern const myElem = document.querySelectorAll(idfName); // Rückgabe des Elementes if ( myElem.length === 1 ){ // Element ist eindeutig return myElem[0]; } else { // Mehrere Elemente vorhanden => Rückgabe Array return myElem; } } /* ENDE::: getObj() */ /* START::: Finde-Text */ function findTxt( myroot, text ){ const root = getObj( myroot ); const results = []; // Array für Treffer // Watch Dog starten const walker = document.createTreeWalker( root, // Start der Suche NodeFilter.SHOW_TEXT, // durchsucht Text-Knoten null, // Platzhalter für zusätzliche Filterregeln false ); let node; // Solange unterhalb des Startelementes "walker" Nodes zu finden sind while( node = walker.nextNode() ){ // Wenn Suchbegriff gefunden wurde in results pushen if( node.textContent.includes(text) ){ // Node pushen results.push(node.parentElement); } } return results; } /* ENDE::: Finde-Text */
JavaScript: function newAusgabe(){ // Auslesen der Options const myNewTx = getObj( '#suche' ).value; const myNewSel = getObj( '#selector' ).value; // Ausführen const textNodes = findTxt( '#wrapper', myNewTx ); let myNewAusgabe = ''; // Array auslesen textNodes.forEach( el => { if(myNewSel === 'id'){ // Ausgabe für id's myNewAusgabe += el.id+'
'; }else{ // Ausgabe für ClassName myNewAusgabe += el.className+'<br>'; } }); getObj('#ausgabe').innerHTML = myNewAusgabe; }