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
... <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.
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:
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.
- findTag( getObj('#wrapper') , 'SPAN' ) oder
- findTag( '#wrapper' , 'SPAN' )
Denn wir wollen unseren Code ja kurz halten.
Doch hierfür müssen wir unsere Funktion noch ein kleines Bisschen anpassen:
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.
// 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
schenken solltest.
Weise gefundenen Node's neue Klasse zu:
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'); }); }