Enrico: Wie greife ich auf Elemente mit dynamischen ID's zu?

Guten Abend,

ich habe in einem Formular nicht angezeigte "Honigtopf"-Felder (diese werden nachfolgend im Rahmen des Spamschutzes abgefragt) mit ID's im Klartext und die eigentlichen Formularfelder mit chiffrierten ID's auf einer Ebene definiert:

<input id="FgenffrOdfc5" value="" type="text" ... />  
<input id="StrasseB" type="text" class="Text" value="" />

Wie kann ich über JavaScript ohne auf jQuery oder sonstige Frameworks zurückgreifen zu müssen, ausgehend vom Element mit der ID "StrasseB" die ID des vorherigen Textfeldes ermitteln?
Da sich die Chiffrierungen bei jedem Aufruf des Formulars ändern, kann ich hier zur Laufzeit nicht direkt darauf zugreifen.

document.getElementById("StrasseB").previousSibling.id bringt mir leider "undefined".

Ich hoffe, ihr könnt mir weiterhelfen.

Vielen Dank und Gruß,
Enrico

  1. @@Enrico:

    nuqneH

    document.getElementById("StrasseB").previousSibling.id bringt mir leider "undefined".

    Hast du dir den previousSibling-Knoten mal angesehen? nodeName statt id:
    console.log(document.getElementById("StrasseB").previousSibling.nodeName) verrät dir, warum das so ist. Da ist noch ein Knoten im DOM, und der hat keine ID.

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. Hallo Gunnar,

      Da ist noch ein Knoten im DOM, und der hat keine ID.

      Hm, ich dachte da wohl zu einfach ("ein Input = ein Schritt").

      Gut, dann muss ich mich weiter hangeln.

      Danke für Deine Antwort :-)

      Gruß,
      Enrico

      1. Hallo Enrico,

        Gut, dann muss ich mich weiter hangeln.

        oder mit getElementsByName / querySelector alle Inputs suchen.

        Gruß, Jürgen

        1. Hallo,

          oder mit getElementsByName / querySelector alle Inputs suchen.

          oder die dynamisch erzeugte ID von dem eintragen lassen, der sie erzeugt hat.

          Gruß, Jürgen

          1. Hallo Jürgen,

            oder die dynamisch erzeugte ID von dem eintragen lassen, der sie erzeugt hat.

            Daran hatte ich auch schon gedacht, jedoch werden die chiffrierten Labels von PHP erzeugt und die müsste ich dann vorab an JavaScript übergeben, was ich nicht für optimal halte.

            Gruß,
            Enrico

      2. @@Enrico:

        nuqneH

        Gut, dann muss ich mich weiter hangeln.

        Dann hangel mal. Dabei würde ich nicht davon ausgehen, dass der Textknoten wirklich vorhanden ist. Vielleich schreibst du auch mal <input /><input /> oder verwendest einen HTML-Minifier, der dies tut.

        Also eher sowas:

        function getPreviousInputElement(id)  
        {  
        	var currentNode = document.getElementById(id);  
        	do {  
        		currentNode = currentNode.previousSibling;  
        	} while (currentNode && currentNode.nodeName != "INPUT");  
          
        	return currentNode;  
        }  
          
        var previousInputElement = getPreviousInputElement("StrasseB");  
        if (previousInputElement)  
        {  
        	console.log(previousInputElement.id);  
        }
        

        In Zukunft sollte auch einfach folgendes möglich sein:

        var previousInputElement = document.querySelector("!input + #StrasseB");  
        
        

        Was für die Gegenwart die Frage aufwirft: Können die beiden Input-Felder auch andersrum stehen?

        Dann ginge

        var nextInputElement = document.querySelector("#StrasseB" + input);  
        
        

        Beachte auch, dass du das Formular für Nutzer assistiver Techniken (wie Screenreader) bedienbar hältst. Auch solche Nutzern muss klar sein, dass der Honigtopf nicht gefüllt werden soll. Also die Eingabefelder mit entsprechenden labels versehen.

        Qapla'

        --
        „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
        1. Hallo Gunnar,

          danke für Deinen (mehr als nur) Ansatz.

          Habe ihn gleich probiert, er findet aber nicht die vorausgehende ID.

          Wahrscheinlich muss ich wirklich den Umweg (?) über das Elternelement machen, um dann eine Ebene nach unten zu gehen (das relevante Textfeld ist immer das erste Kindelement).

          previousElementSibling, wie es Mathias vorgeschlagen hat, liefert mir "nichts", nur leere alert-Fenster.

          Gruß,
          Enrico

          1. Hallo,

            previousElementSibling, wie es Mathias vorgeschlagen hat, liefert mir "nichts", nur leere alert-Fenster.

            Das ist leider wenig hilfreich. alert() ist keine sonderlich gute Debugging-Technik in solchen Fällen.

            Es gibt viele Werte in JavaScript, die beim alert zu einem leeren Fenster führen. Das kann auch ein Objekt oder ein leerer String sein!

            Verwende besser console.log(typeof wert, wert) oder ähnliches.

            undefined: Der Browser kennt die Eigenschaft wahrscheinlich nicht. Es gibt Polyfills.

            null: Es gibt kein vorherigen Geschwisterknoten, der ein Element ist (z.B. wenn das Element das erste Kindelement seines Eltern ist)

            Es hilft auch, einen Breakpoint im Code zu setzen und per Mouseover oder Watch-Expression den Wert anzusehen.

            Grüße,
            Mathias

            1. Hallo Mathias,

              ich muss mein Konstrukt umzustellen, da ich eben festgestellt habe, dass ich bei meiner jetzigen Herangehensweise vereinzelt pro tag zwei ID's vergeben müsste, was ja nicht geht. Und ein Zusammenfassen zweier ID's zu einer einzelnen, verbunden ID die Abfrage unnötig verkompliziert.

              Herrschaftszeiten...

              Gruß,
              Enrico

          2. @@Enrico:

            nuqneH

            Habe ihn gleich probiert, er findet aber nicht die vorausgehende ID.

            Also bei mir tut er’s.

            Wahrscheinlich muss ich wirklich den Umweg (?) über das Elternelement machen, um dann eine Ebene nach unten zu gehen (das relevante Textfeld ist immer das erste Kindelement).

            Wenn’s so einfach ist, dann mach das doch. Für beides gibt’s DOM-Methoden.

            previousElementSibling, wie es Mathias vorgeschlagen hat, liefert mir "nichts", nur leere alert-Fenster.

            Auch das liefert mir die ID. Irgendwas machst du falsch.

            Qapla'

            --
            „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
      3. Meine Herren!

        Da ist noch ein Knoten im DOM, und der hat keine ID.

        Hm, ich dachte da wohl zu einfach ("ein Input = ein Schritt").

        Den Fall hättest du, wenn du den DOM-Baum vorher normalisierst. Dann werden leere Text-Knoten entfernt und benachbarte Text-Knoten zusammengefasst.

  2. Hallo,

    document.getElementById("StrasseB").previousSibling.id bringt mir leider "undefined".

    Dafür ist eher previousElementSibling geeignet. Browserunterstützung beachten.

    Wie kann ich über JavaScript ohne auf jQuery oder sonstige Frameworks zurückgreifen zu müssen, ausgehend vom Element mit der ID "StrasseB" die ID des vorherigen Textfeldes ermitteln?
    Da sich die Chiffrierungen bei jedem Aufruf des Formulars ändern, kann ich hier zur Laufzeit nicht direkt darauf zugreifen.

    Eine Grundregel des DOM-Scriptings ist m.M.n., dass man keine Annahmen über das konkrete Aussehen des DOMs macht (Verschachtelung, Reihenfolge, z.T. Elementtypen). Verwende immer sprechende Namen und verwende ausschließlich diese im CSS und JavaScript.

    Wenn du dynamische IDs hast, so verwende statische Klassen. Steige auf zu einem gemeinsamen Elternelement (identifiziert durch eine Klasse) und suche von dort das fragliche input-Element (identifiziert durch eine Klasse). So etwas geht mit jQuery sehr einfach, aber auch ohne mit ein paar Helferfunktionen.

    Warum müssen die IDs überhaupt zufällig sein? Sind für den Server nicht eher die name-Attribut ausschlaggebend?

    Grüße,
    Mathias

    1. Hallo Mathias,

      Dafür ist eher previousElementSibling geeignet

      Das liefert mir leider nur leere alert-Fenster.

      Warum müssen die IDs überhaupt zufällig sein?

      Ich habe mal gelesen, dass dies Spam verhindern soll, da die Felder für die Bots dann nicht mehr eindeutig zu identifizieren wären.

      Sind für den Server nicht eher die name-Attribut ausschlaggebend?

      Ich übertrage die Formulare über JavaScript und greife auf die Inhalte über die ID's zu.

      Gruß,
      Enrico

  3. Hallo,

    ich setze mein Vorhaben jetzt doch mittels einer Kombination aus PHP, das alle Feldnamen den Vorgaben chiffriert, Arrays zuordnet und letztendlich in JavaScript-Notation ausgibt, und JavaScript, das sich um die Auswertungen etc. kümmert, um.

    Trotzdem Danke an euch!

    Gruß,
    Enrico