JavaScript: Bibliothek - Find Tag

Ich möchte hier unsere bib.js um folgende Funktion erweitern:
findTag()
Diese soll das jewilige gesuchte Elemente/Node's 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 Tag gesucht und bei einem Treffer das jeweilige Element/Node zurückgegeben.
Diese Funktion erwartet 2 Parameter findTag( root , tagName ):

  • root: übernimmt die Ausgangsposition der Suche:
  • tagName: übernimmt das zu findenden Tag
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. nach: SPAN oder DIV und sollten wir zwei Treffer erhalten, werden diese zurückgeliefert bzw. die jeweiligen Node's.
Um das zu erreichen sehen wir uns ersteinmal die Rekursion in unserer Funktion genauer an.

bib.js
function findTag( root , tag ){
	...
	// Rekursion starten
	const walker  = document.createTreeWalker( 
		root, // Start der Suche (Node)
		NodeFilter.SHOW_ELEMENT, // durchsucht nach Elemente/TAG
		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 findTag( root , tag ){
	const results = []; // Array für Treffer
	// Umwandlung in Upper-Case: TagName muss immer in Upper-Case geschrieben sein
	const myTag = tag.toUpperCase();
	
	// Rekursion starten
	const walker  = document.createTreeWalker( 
		root, // Start der Suche (Node)
		NodeFilter.SHOW_ELEMENT, // durchsucht nach Elemente/TAG
		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.tagName === myTag ){
			results.push(node); 
		}else{
			// Wenn nicht das gesuchte TAG - überspringen
			NodeFilter.FILTER_SKIP;
		}
	}
	return results;
}

Jetzt müssen wir unsere Suche bzw. das Ergebnis der Suche auslesen. Und hierbei kommt es jetzt darauf an:
Wie genau möchte ich den Aufruf starten.

  1. findTag( getObj('#wrapper') , 'SPAN' ) oder
  2. findTag( '#wrapper' , 'SPAN' )
Ich persönlich finde den Aufruf 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 findTag( myroot , tag ){
	// Zuweisung des Elementes für den Start der Suche
	const root = getObj( myroot ); 
	...
}

Jetzt wo wir das angepasst haben sehen wir uns die Ausführung an.
(Wir wollen hier jedem gefundenem Tag eine neue Klasse zuweisen.)
Hierfür benötigen wir eine Schleife, denn das Ergebnis befindet sich ja in dem Array results.

JavaScript:
// Ausführen
const textNodes = findTag( '#wrapper' , 'tagName');
// Array auslesen
textNodes.forEach( el => {
	// z.B. eine neue Classe zuweisen
	el.classList.add('newClass');
});

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.

Weise gefundenen Node's neue Klasse zu:

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"> Weise gefundenen Node's neue Klasse zu: </p> <form name="skillflow"> <p> Ausgabe:<br> <select id="selector"> <option value="SPAN">SPAN</option> <option value="P">P</option> </select> </p> </form> </div> <br> <button id="buttonid" class="ancor_button" name="buttonname" onclick="scanTag()">Ausführen</button>

CSS: .newClass{ color: red !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-Tag */ function findTag( myroot , tag ){ const root = getObj(myroot); const results = []; // Array für Treffer // Umwandlung in Upper-Case: TagName muss immer in // Upper-Case geschrieben sein const myTag = tag.toUpperCase(); // Rekursion starten const walker = document.createTreeWalker( root, // Start der Suche (Node) NodeFilter.SHOW_ELEMENT, // durchsucht nach Elemente/TAG 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.tagName === myTag ){ results.push(node); }else{ // Wenn nicht das gesuchte TAG - überspringen NodeFilter.FILTER_SKIP; } } return results; } /* ENDE::: Finde-Tag */
JavaScript: function scanTag(){ // Auslesen der Options const myNewSel = getObj( '#selector' ).value; // Ausführen const textNodes = findTag( '#wrapper', myNewSel ); // Array auslesen textNodes.forEach( el => { // Neue Klasse zuweisen el.classList.add('newClass'); }); }