Stefan: onclick Event Handler

Hallo alle zusammen :)
Ich habe folgendes Problem:

Ich habe eine tabelle mit einem onclick versehen.
Besser gesagt eine Zeile.

  
<table>  
<tr onclick="blab();">  
<td>  
</td>  
</tr>  
</table>  

Jedoch befinden sich in dieser Zelle auch Links:

  
<table>  
<tr onclick="blab();">  
<td>  
<a href="#">Link A</a><br>  
<a href="#">Link B</a><br>  
</td>  
</tr>  
</table>  

Wenn ich jetzt auf den Link klicke wird die onclick-Funktion auch mit ausgeführt.
Gibt es eine Möglichkeit die onclick-Funktion NUR dann auszuführen wenn ich in der Zelle nicht auf einen Link klicke?

Hoffen auf baldige Anwort,
Stefan

  1. Ahoi,

    entweder, in dem du den event mit einem Script zuweist nachdem die Seite geladen wurde (nach onload alle tr-Elemente daraufhin untersuchen, ob darin ein anker ist, und wenn nicht, dann tr.onload = blub zuweisen).

    oder innerhalb der funktion kommst du vielleicht an das callende Element heran.

    Dank und Gruß,

    frankx

    1. Ahoi,

      entweder, in dem du den event mit einem Script zuweist nachdem die Seite geladen wurde (nach onload alle tr-Elemente daraufhin untersuchen, ob darin ein anker ist, und wenn nicht, dann tr.onload = blub zuweisen).

      Ich will allerdings dann die onclick Funktion ausgeführt wird wenn ich ins <tr> Element klicke, jedoch nicht wenn ich auf den Link klicke (der sich leider innerhalb des Elements befindet)

      oder innerhalb der funktion kommst du vielleicht an das callende Element heran.

      Dank und Gruß,

      Möglich?

      1. Ahoi,

        ich weiß nicht, ob in der funktion der caller so mir-nichts-dir-nichts vorhanden ist. immerhin könntest du "this" übergeben:

          
        <table>  
        <tr id="test" onclick="alert(this.id + ' - ' + this.getElementsByTagName('a').length)"><td><p>blub</p></td></tr>  
        <tr id="test" onclick="alert(this.id + ' - ' + this.getElementsByTagName('a').length)"><td><a>blub</a></td></tr>  
        </table>  
        
        

        Dank und Gruß,

        frankx

  2. [latex]Mae  govannen![/latex]

    Wenn ich jetzt auf den Link klicke wird die onclick-Funktion auch mit ausgeführt.
    Gibt es eine Möglichkeit die onclick-Funktion NUR dann auszuführen wenn ich in der Zelle nicht auf einen Link klicke?

    Du kannst das geklickte Element ermitteln und wenn dieses ein a-element ist, das Eventbubbling verhindern

    Cü,

    Kai

    --
    „It's 106 miles to Chicago, we got a full tank of gas, half a pack of cigarettes, it's dark, and we're wearing sunglasses“.
    „Hit it!“
    Selfzeugs
    SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
    1. [latex]Mae  govannen![/latex]

      Du kannst das geklickte Element ermitteln und wenn dieses ein a-element ist, das Eventbubbling verhindern

      sollte

      ... und wenn dieses ein a-element ist, ...

      heißen ;)

      Cü,

      Kai

      --
      „It's 106 miles to Chicago, we got a full tank of gas, half a pack of cigarettes, it's dark, and we're wearing sunglasses“.
      „Hit it!“
      Selfzeugs
      SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
    2. Ahoi,

      Du kannst das geklickte Element ermitteln und wenn dieses ein a-element ist, das Eventbubbling verhindern

      Insofern ist also in der Funktion "this" das Element, in dem der Click ausgeführt wurde?

      Dank und Gruß,

      frankx

      1. [latex]Mae  govannen![/latex]

        Insofern ist also in der Funktion "this" das Element, in dem der Click ausgeführt wurde?

        Nein. Der Event-Listener ist ja dem tr-Element zugewiesen:

        <tr onclick="bla()"><td><a href="#">Link</a></td></tr>

        function bla() {  
          alert(this);  
        }
        

        hier würde this auf das globale Objekt (window) zeigen

        Wird this hingegen übergeben:

        <tr onclick="bla(this)"><td><a href="#">Link</a></td></tr>

        ist in der Funktion

        function bla(ref) {  
          alert(ref.nodeName);  
        }
        

        in ref immer die Referenz auf das tr-Element übergeben, egal, was innerhalb angeklickt wird.

        Also: so geht es nicht. Daher muß in der Funktion bla das geklickte Element mit target bzw. srcElement ermittelt werden:

        <tr onclick="bla()"><td><a href="#">Link</a></td></tr>

        function bla(e) {  
          if (!e) e = window.event;  
          var ref = e.target || e.srcElement;  
          alert(ref.nodeName);  
        }
        

        Cü,

        Kai

        --
        „It's 106 miles to Chicago, we got a full tank of gas, half a pack of cigarettes, it's dark, and we're wearing sunglasses“.
        „Hit it!“
        Selfzeugs
        SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
        1. Also: so geht es nicht. Daher muß in der Funktion bla das geklickte Element mit target bzw. srcElement ermittelt werden:

          <tr onclick="[code lang=javascript]bla()"><td><a href="#">Link</a></td></tr>[/code]

          function bla(e) {

          if (!e) e = window.event;
            var ref = e.target || e.srcElement;
            alert(ref.nodeName);
          }

            
          Du hast vergessen, das Ereignis zu übergeben:  
            
          `<tr onclick="[code lang=javascript]bla(arguments[0]);`{:.language-html}">...</tr>[/code]
          
          -- 
          Reden ist Silber, Schweigen ist Gold, meine Ausführungen sind Platin.  
            
          Self-Code: sh:( ch:? rl:( br:> n4:( ie:{ mo:) va:) de:> zu:} fl:| ss:| ls:~ js:| 
          
        2. Ahoi,

          »» Insofern ist also in der Funktion "this" das Element, in dem der Click ausgeführt wurde?

          Nein. Der Event-Listener ist ja dem tr-Element zugewiesen:

          <tr onclick="bla()"><td><a href="#">Link</a></td></tr>

          function bla() {

          alert(this);
          }

          
          >   
          > hier würde `this`{:.language-javascript} auf das globale Objekt (window) zeigen  
          >   
          >   
          > Wird `this`{:.language-javascript} hingegen übergeben:  
          >   
          > <tr onclick="bla(this)"><td><a href="#">Link</a></td></tr>  
          >   
          > ist in der Funktion  
          >   
          > ~~~javascript
          
          function bla(ref) {  
          
          >   alert(ref.nodeName);  
          > }
          
          

          in ref immer die Referenz auf das tr-Element übergeben, egal, was innerhalb angeklickt wird.

          Also: so geht es nicht. Daher muß in der Funktion bla das geklickte Element mit target bzw. srcElement ermittelt werden:

          <tr onclick="bla()"><td><a href="#">Link</a></td></tr>

          function bla(e) {

          if (!e) e = window.event;
            var ref = e.target || e.srcElement;
            alert(ref.nodeName);
          }

            
          mmh,  
          ~~~html
            
          <script type="text/javascript">  
          window.onload = function() {  
          	set_onclicks();  
          }  
            
          set_onclicks = function () {  
          	divs = document.getElementsByTagName("div");  
          	for(i=0;i<divs.length;i++) {  
          		divs[i].onclick = test_click;  
          	}  
          }  
            
          test_click = function () {  
          	alert(this.id);  
          }  
          </script>  
          <div id="div1id">div1id</div>  
          <div id="div2id">div2id mit Anker:<a id="anker_id" >Anker mit anker_id</a></div>  
            
          <table>  
          <tr id="test" onclick="alert(this.id + ' - ' + this.getElementsByTagName('a').length)"><td><p>blub</p></td></tr>  
          <tr id="test" onclick="alert(this.id + ' - ' + this.getElementsByTagName('a').length)"><td><a>blub</a></td></tr>  
          </table>  
          
          

          in o.g. Beispielen ist jeweils "this" das aufrufende Element. Sowohl beim div, dem nach onload das onclick zugewiesen wird, wie auch das alert direkt im Quelltext.

          --- Syntaxhighlight sieht komisch aus, ist aber getestet bzw. "funzt".

          Dank und Gruß,

          frankx

          1. [latex]Mae  govannen![/latex]

            <table>

            <tr id="test" onclick="alert(this.id + ' - ' + this.getElementsByTagName('a').length)"><td><p>blub</p></td></tr>
            <tr id="test" onclick="alert(this.id + ' - ' + this.getElementsByTagName('a').length)"><td><a>blub</a></td></tr>
            </table>

            
            >   
            > in o.g. Beispielen ist jeweils "this" das aufrufende Element. Sowohl beim div, dem nach onload das onclick zugewiesen wird, wie auch das alert direkt im Quelltext.  
              
            `this`{:.language-javascript} ist hier \_immer\_ das Element, an das die Eventverarbeitung angehängt wurde, nicht das Element, das tatsächlich geklickt wurde. Wenn du im obigen Beispiel this.id durch this.nodeName ersetzt, wirst du immer tr erhalten, egal, ob du in die Zelle td, den Absatz p oder den Anker a klickst. Um das zu unterscheiden, muß das eigentliche Element über die target bzw. sourceElement-Eigenschaft des Eventobjektes ermittelt werden.  
              
            Cü,  
              
            Kai
            
            -- 
            „It's 106 miles to Chicago, we got a full tank of gas, half a pack of cigarettes, it's dark, and we're wearing sunglasses“.  
            „Hit it!“  
            [Selfzeugs](http://kaichen.in/selfhtml/)  
            SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
            
          2. Ich glaube, ihr redet aneinander vorbei. Lies dir nochmal den Unterschied zwischen Zielelement und verarbeitenden Element durch:

            http://redaktion.selfhtml.org/selfhtml-preview/javascript/einbindung.html#bubbling
            http://redaktion.selfhtml.org/selfhtml-preview/javascript/einbindung.html#currenttarget-target

            Beispiel:

            <tr onclick>
               <td>
                  <p>blub</p>
               </td>
            </tr>

            Wenn man hier auf das p klickt und tr einen click-Handler hat, dann gilt:

            <tr onclick>        ← Verarbeitendes Element (in der Bubbling-Phase)
               <td>
                  <p>blub</p>   ← Zielelement
               </td>
            </tr>

            Im Handler kann man auf die beteiligten Elemente wie folgt zugreifen:

            <tr onclick>        ← this bzw. e.currentTarget gemäß DOM Events
               <td>
                  <p>blub</p>   ← e.target gemäß DOM Events bzw. e.srcElement im IE
               </td>
            </tr>

            Mathias

            1. Ahoi,

              Ich glaube, ihr redet aneinander vorbei. Lies dir nochmal den Unterschied zwischen Zielelement und verarbeitenden Element durch:

              http://redaktion.selfhtml.org/selfhtml-preview/javascript/einbindung.html#bubbling
              http://redaktion.selfhtml.org/selfhtml-preview/javascript/einbindung.html#currenttarget-target

              Beispiel:

              <tr onclick>
                 <td>
                    <p>blub</p>
                 </td>
              </tr>

              Wenn man hier auf das p klickt und tr einen click-Handler hat, dann gilt:

              <tr onclick>        ← Verarbeitendes Element (in der Bubbling-Phase)
                 <td>
                    <p>blub</p>   ← Zielelement
                 </td>
              </tr>

              Im Handler kann man auf die beteiligten Elemente wie folgt zugreifen:

              <tr onclick>        ← this bzw. e.currentTarget gemäß DOM Events
                 <td>
                    <p>blub</p>   ← e.target gemäß DOM Events bzw. e.srcElement im IE
                 </td>
              </tr>

              Wobei der Funktion das Event aber immer als "arguments[0]" übergeben werden muss?

              <tr onclick="blub(arguments[0])"> ?

              Dank und Gruß,

              frankx

              1. Wobei der Funktion das Event aber immer als "arguments[0]" übergeben werden muss?

                Wenn man mit Inline-Event-Handlern im HTML arbeitet: ja.
                Wenn man die Ereignis-Überwachung mit JavaScript vornimmt, siehe Zugriff auf das Event-Objekt.

                <tr onclick="blub(arguments[0])"> ?

                Ja, oder onclick="blub(event)". (Ich kenne das arguments[0] nur von Timo und würde event empfehlen. Im Prinzip sind sie identisch, event ist der Name des erste Parameters, den die Handlerfunktion, die durch den Inline-Event-Handler erzeugt wurde, entgegennimmt.)

                Mathias

  3. <tr onclick="blab(event)">

    function blab (e) {
       var target = e.target || e.srcElement;
       if (target.nodeName == "A") return;
       // verarbeite Ereignis
    }

    oder wie gesagt die Handler-Registrierung aus dem HTML auslagern:

    window.onload = function () {
       document.getElementById("bla").onclick = function (e) {
          var e = e || window.event;
          // weiter wie oben
       };
    };

    Mathias

    1. Hi

      der Ansatz ist gut, aber es könnte noch eine Schwachstelle geben. Wenn der Link weitere Kindnoten enthält, und diese angeklickt werden, wird der Code trotzdem ausgeführt. Man müsste also in einer Schleife alle Knoten die dazwischen liegen durchgehen.

        
      function blab (e)  
      {  
        var el = e.target || e.srcElement;  
        while(el!=this)  
        {  
          if(el.nodeName == "A")  
            return;  
          el = el.parentNode;  
        }  
        // verarbeite Ereignis  
      }  
      
      

      mfg
      Felix