L3: onChange auf Select legen

Moin Moin,

vielleicht vorab um kurz zu verdeutlichen was ich vorhabe:

Da ich relativ viele Formularelemente habe und ungern in meinem Template die HTML Tags mit JavaScript überflute, lege ich die JavaScript Events beim laden der Seite auf die ganzen Formelemente - so wie hier für ein paar Radio-Buttons:

	  
for( var i=0; i < document.foo.elements.length; i++ )  
{  
    document.getElementsByName("myFoo")[i].onClick = barNow;  
}  

Funktioniert tadellos und mit den vier Zeilen kann ich (übertrieben gesagt) hunderte Buttons auf einen Klick reagieren lassen.

So. Aber wieso will es mir nicht gelingen das auch bei einem <select> mit onChange zu machen?

ein <select id="myFoo" onChange="barNow();"> funktioniert.
Wenn ich es aber z.B. mit
document.getElementById("myFoo").onChange = barNow();
versuche führt er es genau einmal aus - beim laden :(

Ich spiele seit 3 Tagen damit und komm nicht weiter. Habe es auf die option-elemente gelegt, mit getElementsByName angesprochen, nicht direkt von sondern über das <form> angesprochen aber es interessiert in schlicht nicht. Im www findet man zwar unzählige Sachen über onChange bei <select> aber alle eben im Tag und nicht "von außerhalb" ;)

Was übersehe ich? Was mache ich falsch?

Freue mich über jede Antwort =)

Dank und Gruß,
L3

  1. document.getElementsByName("myFoo")[i].onClick = barNow;

    document.getElementById("myFoo").onChange = barNow();

    Schau dir doch mal den Unterschied zum obigen Code an.

    Häufiger Fehler: Handler-Funktion direkt aufrufen

    Außerdem sollte es onchange heißen (klein geschrieben).

    Mathias

    1. »» document.getElementsByName("myFoo")[i].onClick = barNow;
      »» document.getElementById("myFoo").onChange = barNow();

      Schau dir doch mal den Unterschied zum obigen Code an.

      Hoppla - mein Fehler ... ich schreibs mir hinter die Ohren und thx für den Link.

      Außerdem sollte es onchange heißen (klein geschrieben).

      ... und schon gehts - ich hab die selfHMTL 8.1 Version noch auf meim Server und da steht das c noch groß drin - das werde ich sofort aktualisieren ;)

      Vielen Dank!

  2. Hi,

    [...] ungern in meinem Template die HTML Tags mit JavaScript überflute lege ich die JavaScript Events beim laden der Seite auf die ganzen Formelemente [...]

    Gut.

    for( var i=0; i < document.foo.elements.length; i++ )
    {
        document.getElementsByName("myFoo")[i].onClick = barNow;
    }

    »»  
      
    Nein nein nein, das geht zwar so tatsächlich dass es funktioniert (purer Zufall), aber es ist trotdem falsch! :)  
      
    Du iterierst hier über alle Elemente deines Forms(?), und rufst jedes mal darin getElementsByName auf .. Unsinn.  
      
    Probiers mal so:  
      
    ~~~javascript
    	  
    selects = document.getElementsByTagName('select'); // liefert alle Elemente vom Typ <select>  
    for( var i=0; i < selects.length; i++ )  
    {  
         selects[i].onClick = barNow;  
    }  
      
    inputs= document.getElementsByTagName('input'); // liefert alle Elemente vom Typ <input>, der mehrere Untertypen hat ...  
    for( var i=0; i < selects.length; i++ )  
    {  
         // spezielles behandeln der Untertypen  
         if(inputs[i].type == 'text')  
              inputs[i].onClick = barNowTest;  
         else if(inputs[i].type == 'radio')  
              inputs[i].onClick = barNowRadio;  
         [...]  
         else if(inputs[i].type == 'password')  
              inputs[i].onClick = barNowRadio;  
    }  
    
    

    Das ginge noch besser, in dem du statt element.onClick = functionCall; auf addEventListener (standard) oder attachEvent (IE) zurückgreifst (siehe z.B. http://www.mediaevent.de/javascript/event_handler.html).

    Das is leider wie oben ersichtlich wieder nicht browserübergreifend gleich, und daher wieder lästig ... es sei denn du nutzt ein JS-Framework wie z.b. prototype.js o.a. was davon widerum abstrahiert (derweil würde ich dir davon abraten, du scheinst noch Lücken zu haben, die würd ich erstmal kitten bevor ich mich auf ein so mächtiges Framework stürze).

    Eine andere Lösung wäre noch das Event jeweils am Form abzufangen. Jeder Klick auf das Form (d.h. auf Selects, Radiobuttons etc. die im Form snd) wird auch an das Form weitergereicht (bubble-up).

    Das kannst du daher auch so lösen:

    document.myForm.onclick = myHandler;

    function MyHandler(event)
    {
       element = event.target; // auf dieses wurde geklickt
       nodeName= event.target.nodeName.toLowerCase;  // der Typ des Elements
       if(nodeName == 'select')
           handleSelect();
       else if(nodeName == 'input')
       {
          type = element.type;
          if(type == 'text')
              handleText();
          else if(type == 'radio')
              handleRadio();
          [...]
          else if(type == 'password')
              handlePassword();
       }
    }

    function handleSelect()
    {
    // code
    }

    function handleText()
    {
    // code
    }

    function handleRadio()
    {
    // code
    }

    function handlePassword()
    {
    // code
    }

    Vorteil: nur EIN event-handler pro Form, daher MEINER MEINUG NACH wenig speicher*hungrig und daher auch effizienter, u.a.

    Nachteil: weniger Modular, daher evtl. schlechter wart/erweiterbar, u.a.

    1. Hi,

      obiges ist alels ungetestet ... typos etc. möglich. Such im Self wenn du Fehlermeldungen kriegst, sollte vom Konzept her funktionieren.

      Viel Erfolg

    2. Vorteil: nur EIN event-handler pro Form, daher MEINER MEINUG NACH wenig speicher*hungrig und daher auch effizienter, u.a.

      Das ist keine Frage der Meinung, sondern der Tatsachen.

      Die mehrfache Registrierung von Handler legt nur Referenzen auf Funktionen an, d.h. eine Eigenschaft, die ohnehin schon existiert, wird mit einer Speicherstelle gefüllt. Es ist daher nicht nennenswert speicherhungriger.

      Effizienter ist es unter Umständen, aber weniger aus diesem Grund. Man muss keine riesigen Knotenlisten abfragen und durchlaufen. Allerdings tritt ein kleiner Overhead auf, dass bei jedem Klick die Erkennung durchlaufen werden muss, wenn man alle Klick-Events an zentraler Stelle verarbeitet.

      Beides muss man einfach abwägen und testen.

      Mathias

  3. Hi, nochmal ich ...

    for( var i=0; i < document.foo.elements.length; i++ )
    {
        document.getElementsByName("myFoo")[i].onClick = barNow;
    }

      
    Bist du sicher dass das hier so stimmt ?!?!?  
      
    Die Indizes von document.foo.elements (= alle Form-Elemente) und document.getElementsByName("myFoo") (= alle Form-Elemente namens "MyFoo") sind, meines Erachtens, höchstens zufällig identisch ...  
      
    Wenn bei dir jedes Element den gleichen Namen hat dann rennts, oder wenn die Elemente die du berücksichtigen willst alle "am Anfang" stehen, aber trotzdem rufst du für jedes Element in deinem Form einmal getElementsByName() mit immer dem gleichen Parameter auf, änderst nur den Index ... ich kann mir nicht vorstellen dass du das willst ... evtl. noch so ...  
      
    ~~~javascript
      
    for( var i=0; i < document.foo.elements.length; i++ )  
    {  
       if(myConditionIsMet)  
         document.foo.elements[i].onClick = barNow;  
    }  
    
    

    Servus

    1. for( var i=0; i < document.foo.elements.length; i++ )
      {
         if(myConditionIsMet)
           document.foo.elements[i].onClick = barNow;
      }

        
      Das ist falsch! Da passiert nichts, warum hat [Mathias](https://forum.selfhtml.org/?t=184682&m=1224567) bereits gesagt.  
        
      Struppi.
      
      1. Hi,

        Das ist falsch! Da passiert nichts, warum hat Mathias bereits gesagt.

        Ich denke du beziehst dich auf das "onClick" das "onclick" heißen sollte, bzw. besser, "onchange" ... oder?

        point taken - Typo, bzw. copy&paste vom Thread-Starter.

        Aus was ich aber eigentlich raus wollte ist, dass der Code vom Thread-Starter mir "falsch" vorkommt ...

        Ein Loop über document.foo.elements wo on jeder Iteration document.getElementsByName() mit identischem Parameter aufgerufen wird ... das will kein Mensch so, wenn er weiß was er tut ...

        Ich denke der Thread-Starter sollte das wissen ... das war das anliegen meines Postings ... leider meldet er sich nimma und sitzt nun evtl. auf "falschem" Code ...

        Naja, so long ...