# Radio-Buttons - onChange, onFocus oder onClick



## ratio (13. März 2005)

Hallo Leute,

hier kommt ein ganz kniffeliges Problem. Ich habe ein HTML-Formular, welches sowohl SELECT-Boxen als auch RADIO-Buttons enthält. Per JavaScript sollen Aktionen ausgeführt werden, jedoch nur für den Fall, daß Werte - also eine Auswahl in einer SELECT-Box oder innerhalb einer Gruppe von RADIO-Buttons - geändert werden.

Für die SELECT-Boxen ist das kein Problem, hier funktioniert "onChange" in allen Browsern wunderbar. Bei den RADIO-Buttons sieht es da leider nicht so gut aus. Im Einzelnen:

-> onClick ist für den oben beschriebenen Zweck, Aktionen nur bei Änderungen durchzuführen, untauglich, weil bei jedem Click (auch bei Simulation mit Tastatur über TAB und Leertaste) die definierte Aktion ausgeführt würde.

-> onFocus funktioniert, allerdings geschieht der Funktionsaufruf auch dann, wenn ich den Browser minimiere oder ein anderes Progamm in den Vordergrund aktiviere und hinterher wieder das Ausgenagsfenster hervorhole. Sowohl in Mozilla als auch im IE scheint das den on Focus-Eventhandler anzustoßen.

-> onChange funktioniert in Mozilla einwandfrei, wie man es von den SELECT-Boxen her kennt. Stets dann, wenn auf ein RADIO-Button geklickt wird, wird die dort bei "onChange" definierte Funktion ausgeführt. Mit dem IE bleibt das Ganze unbefriedigend, weil die Aktion erst dann ausgeführt wird, wenn von diesem RADIO-Button weggeklickt wird.

Ziemlich frustierend. Die ganze Problematik entsteht offensichtlich daraus, daß RADIO-Buttons im Dokument nicht zentral, sondern verteilt definiert und gruppiert werden. Hier noch ein paar Versions-Infos: IE 6.0 und Mozilla 1.6

Ich hoffe, daß jemand helfen kann. Vielleicht ein workaround mit onClick, wobei eine weitere Bedingung eingefügt wird...? Jedenfalls schonmal vielen Dank für's Lesen.


----------



## Quaese (13. März 2005)

Hi,

hoffentlich habe ich dein Problem richtig verstanden.

Wenn in einer Radiogruppe ein neuer Wert angewählt wird, soll eine bestimmte Aktion 
ausgeführt werden.

Ich würde das über den *onclick*-Event lösen. Wird ein Button angeklickt, wird geprüft, ob
der Radiobutton auch wirklich gesetzt ist und ob sich das aktuelle Buttonobjekt von einem 
gespeicherten unterscheidet. Sind beide Bedingungen erfüllt, wird die gewünschte Aktion 
ausgeführt.

Da sich mehr Radiogruppen innerhalb eines Formulars befinden können, werden die aktuellen
Objekte in einem assoziativen Array gespeichert. Jede Gruppe erhält dabei eine neue Dimension.

```
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>www.tutorials.de</title>
<meta name="author" content="Quaese" />
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">
  <!--
// Array zum Merken des aktuellen Radio-Objektes in der jeweiligen Radio-Gruppe
var arrObjRadio = new Array();
function doAction(objRadio){
  // Falls der Radiobutton gesetzt ist und ein neuer Radiobutton gewählt wurde
  if((objRadio.checked == true) && (objRadio != arrObjRadio[objRadio.name])){
    // Aktuelles Objekt merken
    arrObjRadio[objRadio.name] = objRadio;

    // Änderungen durchführen
    switch(objRadio.name){
      case "radioGroup"  : alert("Änderungen für die erste Radiogruppe");
                           break;
      case "radioGroup2" : alert("Änderungen für die zweite Radiogruppe");
                           break;
    }
  }
}
 //-->
</script>
</head>
<body>
<form method="" action="">
  <fieldset style="padding: 6px;">
    <legend>Zifferngruppe</legend>
    <input type="radio" onclick="doAction(this);" name="radioGroup" value="1" /><label>Zifferngruppe: 1</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup" value="2" /><label>Zifferngruppe: 2</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup" value="3" /><label>Zifferngruppe: 3</label>
  </fieldset>
  <fieldset style="padding: 6px; margin-top: 12px;">
    <legend>Buchstabengruppe</legend>
    <input type="radio" onclick="doAction(this);" name="radioGroup2" value="a" /><label>Buchstabengruppe: a</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup2" value="b" /><label>Buchstabengruppe: b</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup2" value="c" /><label>Buchstabengruppe: c</label>
  </fieldset>
</form>
</body>
</html>
```
Ich hoffe, das hilft dir weiter.

Ciao
Quaese


----------



## ratio (14. März 2005)

Hallo Quaese,

vielen Dank für die schnelle und zielsichere Antwort. Dein Code-Beispiel ist genau die richtige Lösung für mein Problem. Ich werde ein Auge auf das Forum haben und hoffe, daß ich auch mal helfen kann. 

Besten Dank


----------



## ratio (15. März 2005)

Hallo Quaese,

hier noch eine kleine Nachfrage. Dein Script funktioniert wunderbar, bis auf eine Ausnahme. Nach dem Laden einer Seite ist das Array "arrObjRadio" zwar definiert, jedoch leer. Wenn man nun auf einen Radio-Button klickt, der bereits "focussed" ist, weil er defaultmäßig mit "input type=radio checked" geladen wird, dann wird gleichwohl die Funktion aufgerufen, weil für diese Gruppe erstmal der Wert gesetzt werden muß. Das sollte laut Vorgabe nicht passieren. Nun kann man zwar ein workaround in der aufgerufenen Funktion selbst einbauen, aber das belastet unnötig Ressourcen, verkompliziert die Funktion und trennt nicht mehr scharf zwischen den Aufgaben der verschiedenen Funktionen. Wie kann man also schon beim Laden der Seite die Werte im Array entsprechend der gesetzten Radio-Buttons setzen? Mir fällt nur quick'n dirty ein, nämlich die Werte arrObjRadio manuell zu setzen. Als Indizes würde man wahrscheinlich die Namen der Radio-Gruppen nehmen, aber wie verbinde ich das dann mit dem Objekt? Noch eleganter wäre es, wenn dieses Problem mit einer Art "foreach"-Schleife gelöst werden könnte, die über alle Radio-Buttons läuft und bei "checked==true" das Array füttert.

Vielen Dank im Voraus!


----------



## Quaese (15. März 2005)

Hi,

im *onload*-Event des BODYs könntest du eine Initialisierungsfunktion aufrufen, die alle
Formulare im Dokument durchläuft. Wird ein Radiobutton gefunden, wird geprüft, ob dieser
gesetzt ist und entsprechend der Wert im Objektarray gesetzt. Index ist der Name des Buttons,
der zugehörige Wert das Objekt.

Der gesamte Quelltext könnte folgendermassen aussehen:

```
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>www.tutorials.de</title>
<meta name="author" content="Quaese" />
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">
  <!--
// Array zum Merken des aktuellen Radio-Objektes in der jeweiligen Radio-Gruppe
var arrObjRadio = new Array();

function doAction(objRadio){
  // Falls der Radiobutton gesetzt ist und ein neuer Radiobutton gewählt wurde
  if((objRadio.checked == true) && (objRadio != arrObjRadio[objRadio.name])){
    // Aktuelles Objekt merken
    arrObjRadio[objRadio.name] = objRadio;

    // Änderungen durchführen
    switch(objRadio.name){
      case "radioGroup"	: alert("Änderungen für die erste Radiogruppe im ersten Formular");
                          break;
      case "radioGroup2": alert("Änderungen für die zweite Radiogruppe im ersten Formular");
                          break;
      case "radioGroup3": alert("Änderungen für die dritte Radiogruppe im zweiten Formular");
                          break;
    }
  }
}

function initForm(){
  var objForm = null;

  // Alle Formulare durchlaufen
  for(j=0; j<document.forms.length; j++){
    // Objekt des aktuellen Formulars holen
    objForm = document.forms[j];

    // Formularelemente durchlaufen
    for(i=0; i<objForm.elements.length; i++){
      // Falls es sich beim aktuellen Element um einen Radiobutton handelt
      if(objForm.elements[i].type == "radio"){
        // Falls der Button gesetzt ist
        if(objForm.elements[i].checked == true){
          // Objekt in entsprechendes Array schreiben
          arrObjRadio[objForm.elements[i].name] = objForm.elements[i];
        }
      }
    }  // ENDE - for(i=...)
  }  // ENDE - for(j=...)
}

 //-->
</script>
</head>
<body onload="initForm();">
<form method="" action="">
  <fieldset style="padding: 6px;">
    <legend>Zifferngruppe im ersten Formular</legend>
    <input type="radio" onclick="doAction(this);" name="radioGroup" value="1" checked="checked" /><label>Zifferngruppe: 1</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup" value="2" /><label>Zifferngruppe: 2</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup" value="3" /><label>Zifferngruppe: 3</label>
  </fieldset>
  <fieldset style="padding: 6px; margin-top: 12px;">
    <legend>Buchstabengruppe im ersten Formular</legend>
    <input type="radio" onclick="doAction(this);" name="radioGroup2" value="a" /><label>Buchstabengruppe: a</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup2" value="b" checked="checked" /><label>Buchstabengruppe: b</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup2" value="c" /><label>Buchstabengruppe: c</label>
  </fieldset>
</form>
<form method="" action="">
  <fieldset style="padding: 6px;">
    <legend>Zifferngruppe im zweiten Formular</legend>
    <input type="radio" onclick="doAction(this);" name="radioGroup3" value="1" checked="checked" /><label>Zifferngruppe: 1</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup3" value="2" /><label>Zifferngruppe: 2</label><br />
    <input type="radio" onclick="doAction(this);" name="radioGroup3" value="3" /><label>Zifferngruppe: 3</label>
  </fieldset>
</form>
</body>
</html>
```
Ciao
Quaese


----------



## ratio (16. März 2005)

Funktioniert perfekt - Tausend Dank!


----------



## ratio (21. März 2005)

Hallo Quaese,

aller guten Dinge sind drei - vielleicht weißt Du Du ja auch noch etwas zu diesem Phänomen:

Die RELOAD-Funktion im IE setzt sämtliche Formulareingaben auf die default-Werte zurück, die im html-Code beim Laden der Seite übermittelt wurden. Bei Mozilla und Firefox hingegen merkt sich der Browser die bisherigen Eingaben. Das führt in der obigen Sache zu folgendem Problem. Wenn man nach dem ersten Laden der Seite Veränderungen an den RADIO-Buttons vornimmt, werden die Objekte im arrObjRadio gespeichert. Nun handelt es sich bei dem Formular um eine Eingabemaske für Suchanfragen, wobei nach Benutzereingaben durch eine komplizierte Logik andere Elemente aktiviert, deaktiviert oder aktualisiert werden. Jedenfalls soll nach dem Absenden des Formulars dieses auf der Folgeseite wieder mit den gleichen Eingaben zu sehen sein. Dies, um den Besuchern den Anreiz zu nehmen, auf die BACK-Taste zu drücken, denn dann entstünde ein riesiges Wirrwarr. Also prüfe ich lieber die gesendeten Werte und stelle das Formular durch ein dynamisch generiertes Javascript, welches die Felder entsprechend aktiviert, deaktiviert oder aktualisiert, wieder so her, wie es vor dem Absenden bestand. Das funktioniert auch sehr gut, bis auf folgende Ausnahme: Da Mozilla und Firefox die Radiobuttons gecheckt lassen, wo sie vor dem RELOAD waren, geht der Funktionsaufruf "doAction" ins Leere, weil er an der zweiten IF-Bedingung scheitert. Denn der Wert hat sich nicht geändert, also kein Funktionsaufruf. Ich habe einen Tag lang alles probiert, was JavaScript hergibt... :-|

Irgendeine Idee?
Und nochmals Danke!


----------



## ratio (21. März 2005)

So, dieses letzte Problem ist nun auch noch gelöst:

Mozilla und Firefox scheinen die aktuellen Formulareinstellungen gruppenweise zu speichern und zurückzugeben. Ein javascript unmittelbar nach dem betreffenden radiobutton noch innerhalb des Formulares etwa dergestalt "document.form.radiogruppe[0].checked=true;" bleibt wirkungslos. Wenn man es jedoch nach dem End-Tag </form> platziert, dann zeigt es Wirkung. Toll.


----------

