Enrico: Ermittlung/Wechsel von className's

Hallo,

ich verwende eigene Grafiken für die Darstellung von Checkboxen, damit sie zum Design unserer Homepage passen.

Die Formulare erzeuge ich über php und lasse sie ausgeben. Der nachfolgende Code beschränkt sich auf die Ausgabe der Checkboxen:

  
   echo "<div id='eMail_verstecken' class='eMail_verstecken' onclick='Zustand_aendern (\"eMail_verstecken\");'></div>";  
   echo "<div id='Privater_Eintrag' class='Privater_Eintrag' onclick='Zustand_aendern (\"Privater_Eintrag\");'></div>";  
   echo "<div id='Nicht_speichern' class='Nicht_speichern_aktiv' onclick='Zustand_aendern (\"Nicht_speichern\");'></div>";  

Kurz vor dem schliessenden body-Tag initialisiere ich die Elemente:

  
      <script type="text/javascript">  
  
         var Elemente = new Array ("Eingabefeld_Name",  
                                   "Eingabefeld_eMail",  
                                   "Eingabefeld_Homepage",  
                                   "Eingabefeld_Text",  
                                   "eMail_verstecken",  
                                   "Privater_Eintrag",  
                                   "Nicht_speichern");  
  
         for (var i = 0; i < Elemente.length; ++i)  
         {  
            var Objekt = document.getElementById (Elemente [i]);  
alert (Objekt);  
            if (Objekt)  
            {  
               var Objekt_ID = Objekt.id;  
  
               if (Objekt_ID.indexOf ("Eingabefeld_") !== -1)  
               {  
                  var Vorbelegung = Objekt_ID.substr (12);  
  
                  applyDefaultValue (Objekt, Vorbelegung);  
               }  
            }  
         }  
      </script>
~~~~~~html
  
   </body>

Die Funktion applyDefaultValue () hat für mein Anliegen keine Bedeutung (sie dient der Vorbelegung der input-Felder mit Ausgangswerten), ich habe die Anweisungen aber der Vollständigkeit hier mit aufgeführt.

Beim Anklicken einer checkbox-Grafik wird die Funktion Zustand_aendern () aufgerufen, die die ID des zu ändernden Elements übergibt.

Hier die Funktion Zustand_aendern ():

  
   function Zustand_aendern (Element)  
   {  
      var Vorherige_Klasse = Element.className;  
  
      Element.className = (Element.className == Element) ? Element + "_aktiv" : Element;  
  
      alert ("Element: " + Element + "\nVorherige Klasse: " + Vorherige_Klasse + "\nNeue Klasse: " + Element.className);  
   }  

Nun kommen wir zum eigentlichen Problem:

Weder der jeweilige Klassenname wird korrekt ermittelt, noch der Klassenname korrekt gewechselt.

Der zu Testzwecken eingebaute alert-Befehl gibt mir folgende Informationen (hier für die Checkbox "Nicht_speichern") aus:

Element:          Nicht_speichern
   Vorherige Klasse: undefined
   Neue Klasse:      undefined

Der alert-Befehl im script-Block gibt mir für alle Elemente "[object HTMLInputElement]" aus. Ob dies auf eine korrekte Referenzierung schliessen lässt, weiß ich nicht.

Wenn ja, dann kann/sollte der Fehler hier nicht liegen, zudem ist das Formular zu diesem Zeitpunkt vollständig aufgebaut, d.h. die Elemente existieren auch bereits zu diesem Zeitpunkt.

Wo liegt mein Fehler?

Vielen Dank und Gruß,
Enrico

  1. Hi,

    Der zu Testzwecken eingebaute alert-Befehl gibt mir folgende Informationen (hier für die Checkbox "Nicht_speichern") aus:

    Element:          Nicht_speichern

    Das ist kein Element, sondern ein Textliteral.

    Vorherige Klasse: undefined

    "Nicht_speichern" hat keine className-Eigenschaft - also ergibt der Zugriff darauf undefined.

    Der alert-Befehl im script-Block gibt mir für alle Elemente "[object HTMLInputElement]" aus.

    Dort hast du ja auch über die ID das Element suchen lassen; in deiner Funktion Zustand_aendern machst du das aber nicht. Offebar rufst du sie, entgegen der Bezeichnung des Parameters, nicht mit Übergabe einer Element-Referenz auf, sondern nur mit der Übergabe eines Textliterals.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Hallo ChrisB,

      danke für Deine Antwort.

      Ich habe es jetzt so gemacht, dass ich die ID innerhalb der Funktion Zustand_aendern () ermittle, jetzt klappt es.

      Leider kann ich aber nicht nachvollziehen, warum das jetzt klappt und vorher nicht.

      Gruß
      Enrico

      1. Hallo,

        Leider kann ich aber nicht nachvollziehen, warum das jetzt klappt und vorher nicht.

        soweit ich das sehe, übergibst du den Namen des Elemnts (z.B. eMail_verstecken) an die Funktion und nicht das Element selbst, das ist also nur Text (und das zeigt dir dein alert auch!) und auf den kannst du kein className anwenden.

        onclick='Zustand_aendern (this);' wäre ein Ansatz

        VG

  2. @@Enrico:

    nuqneH

    ich verwende eigene Grafiken für die Darstellung von Checkboxen, damit sie zum Design unserer Homepage passen.

    Das kannst du gerne tun. Du solltest aber NICHT 'div' anstelle von Checkboxen verwenden! Ansonsten baust du eine Barriere ein und machst deine Seite unzugänglich.

    Du kannst die vorhandenen Checkboxen aus dem Viewport schieben und dem 'label' je nach Status der Checkbox verschiedene Hintergrundgrafiken verpassen. (Oder dieselbe, aber verschiedene Ausschnitte daraus (CSS-Sprites).)

    Markup (ansatzweise):

    <input type="checkbox" name="foo" id="foo"/>  
    <label for="foo">Lorem ipsum</label>
    

    Stylesheet:

    [type="checkbox"]  
    {  
      position: absolute;  
      left: -9999px; /* für RTL-Schriften: right */  
    }  
      
    [type="checkbox"]+label  
    {  
      background: url(checkbox-not-checked.png) no-repeat;  
      padding-left: 42px;  
    }  
      
    [type="checkbox"]:checked+label  
    {  
      background: url(checkbox-checked.png) no-repeat;  
    }
    

    Du brauchst nur noch einen Fallback für Browser, welche die Pseudoklasse :checked nicht verstehen. Dieser kann so aussehen, dass du in dem Fall die normalen Checkboxen verwendest.

    Vorteil: Keine Barriere; kein JavaScript erforderlich.

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
    1. Du brauchst nur noch einen Fallback für Browser, welche die Pseudoklasse :checked nicht verstehen. Dieser kann so aussehen, dass du in dem Fall die normalen Checkboxen verwendest.

      Das ist doch der spannende Teil: Wie sieht dieser Fallback aus? Wie bringt man in Erfahrung, ob der Browser :checked versteht, und zeigt die Checkbox in dem Fall? Unter diesen Voraussetzungen:

      Vorteil: Keine Barriere; kein JavaScript erforderlich.

      Mathias

      1. @@molily:

        nuqneH

        Das ist doch der spannende Teil: Wie sieht dieser Fallback aus? Wie bringt man in Erfahrung, ob der Browser :checked versteht, und zeigt die Checkbox in dem Fall? Unter diesen Voraussetzungen:

        Vorteil: Keine Barriere; kein JavaScript erforderlich.

        Ich wollte gerade mit Modernizr kommen …

        Aber das sollte es doch tun, oder?

        [type="checkbox"], x:checked  
        {  
          position: absolute;  
          left: -9999px; /* für RTL-Schriften: right */  
        }  
          
        [type="checkbox"]+label, x:checked  
        {  
          background: url(checkbox-not-checked.png) no-repeat;  
          padding-left: 42px;  
        }  
          
        [type="checkbox"]:checked+label  
        {  
          background: url(checkbox-checked.png) no-repeat;  
        }
        

        Qapla'

        --
        Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
        (Mark Twain)
        1. Ich wollte gerade mit Modernizr kommen …

          Modernizr macht keine Feature-Tests für CSS-3-Selektoren. Das ist mit JavaScript nur sehr unschön testbar.

          [code lang=css][type="checkbox"], x:checked

          Das scheint mir eine Grauzone zu sein. Wo ist definiert, dass der Browser die komplette Regel ignorieren muss, wenn ein Teil des Selektors unbekannt ist?

          Hier ist nur von nicht parsebaren bzw. invaliden Selektoren die Rede: http://www.w3.org/TR/CSS2/syndata.html#rule-sets
          http://www.w3.org/TR/selectors/#Conformance

          IE 8 ignoriert die Regel jedenfalls nicht, also funktioniert der Fallback dort nicht.

          Mathias

          1. @@molily:

            nuqneH

            [type="checkbox"], x:checked
            Das scheint mir eine Grauzone zu sein.

            Ein As hab ich noch im Ärmel:

            [type="checkbox"]:checked:not(x), [type="checkbox"]:not(:checked)  
            {  
              position: absolute;  
              left: -9999px; /* für RTL-Schriften: right */  
            }  
              
            [type="checkbox"]:not(:checked)+label  
            {  
              background: url(checkbox-not-checked.png) no-repeat;  
              padding-left: 42px;  
            }  
              
            [type="checkbox"]:checked:not(x)+label  
            {  
              background: url(checkbox-checked.png) no-repeat;  
              padding-left: 42px;  
            }
            

            So hat man den Fallback für Browser, die weder :checked noch :not() verstehen.

            Qapla'

            --
            Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
            (Mark Twain)
      2. Hi,

        Du brauchst nur noch einen Fallback für Browser, welche die Pseudoklasse :checked nicht verstehen. Dieser kann so aussehen, dass du in dem Fall die normalen Checkboxen verwendest.

        Das ist doch der spannende Teil: Wie sieht dieser Fallback aus? Wie bringt man in Erfahrung, ob der Browser :checked versteht, und zeigt die Checkbox in dem Fall?

        Man kann vor den restlichen Checkboxen noch eine zusätzliche, gecheckte platzieren, und dann die folgenden Checkboxen über eine Kombination mit dem General Sibling Combinator ausblenden:

        #zusatzcheckbox:checked ~ input[type="checkbox"] { /*verstecken*/ }

        Versteht der Browser :checked nicht*, bleiben die restlichen Checkboxen halt sichtbar.

        Das mag man** vielleicht auf Grund der extra Checkbox nicht besonders elegant finden - dafür ist es an keine zusätzlichen Techniken wie bspw. JavaScript gebunden; m.E. damit ein vertretbarer Trade-off.

        Damit die extra Checkbox keinen Nutzer verwirrt, wenn das in einem Formular eingesetzt und ohne CSS betrachtet würde, könnte man diese Checkbox noch auf readonly setzen, und noch mit einer "bitte nicht beachten" Beschriftung/Label versehen, dann wäre dieser seltene Fall auch noch abgedeckt.

        MfG ChrisB

        * oder die ~ - aber Browser, die den GSC noch nicht kennen, haben von :checked höchstvermutlich auch noch nichts gehört.
        ** man in diesem Fall = Markup-Puristen

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. #zusatzcheckbox:checked ~ input[type="checkbox"] { /*verstecken*/ }

          Nicht schlecht. Setzt aber ein DOM voraus, bei dem alle Checkboxen ein gemeinsamen Elternelement haben. Letztlich käme man z.B. zu solchen absurden Selektoren:

          #zusatzcheckbox:checked ~ p input[type="checkbox"]
          #zusatzcheckbox:checked ~ p input[type="checkbox"] + label
          #zusatzcheckbox:checked ~ p input[type="checkbox"]:checked + label

          Das ginge. Schön ist das nicht, effizient schon gar nicht.

          Das mag man** vielleicht auf Grund der extra Checkbox nicht besonders elegant finden - dafür ist es an keine zusätzlichen Techniken wie bspw. JavaScript gebunden; m.E. damit ein vertretbarer Trade-off.

          Da es ohnehin um eine grafische Verschönerung geht, sehe ich kein Problem dabei, sie von JavaScript abhängig zu machen. Das erspart einem hässliche Hacks. Als Markup-Purist sollte es einem widerstreben, inhaltsloses Präsentations-Markup einzufügen. Nichts anderes ist die funktionslose Zusatz-Checkbox.

          Damit die extra Checkbox keinen Nutzer verwirrt, wenn das in einem Formular eingesetzt und ohne CSS betrachtet würde, könnte man diese Checkbox noch auf readonly setzen, und noch mit einer "bitte nicht beachten" Beschriftung/Label versehen, dann wäre dieser seltene Fall auch noch abgedeckt.

          Solcher Noise verwirrt den Nutzer eher vollends. Aber die Zusatzcheckbox könnte display: none, das hidden-Attribut und aria-hidden="true" besitzen, damit es unzugänglich ist.

          Mathias