Ale×: Prüfen ob außerhalb eines bestimmten Bereiches geklickt wurde

Hallo,

ich möchte feststellen, ob außerhalb eines Elementes geklickt wurde. Das funktioniert soweit auch:

function mausklick(e)  
 {  
  var obj = e.target || e.srcElement;  
  if(obj.id!='kasten')  
   {  
    alert('Außerhalb des Kastens geklickt!');  
   }  
 }  
document.onmousedown = mausklick;

Das Problem ist nun: wenn in dem Kasten weitere Elemente vorkommen (<div>, <p>, <a> usw.) und auf diese geklickt wird, wird natürlich auch der alert ausgeführt.

Eine Möglichkeit wäre nun, nach dem parentNode und dessen parentNode usw. zu schauen, es können ja beliebig viele Verschachtelungen enthalten sein:

if(obj.id!='kasten' && obj.parentNode.id!='kasten' && obj.parentNode.parentNode.id!='kasten' && obj.parentNode.parentNode.parentNode.id!='kasten' && ... && ...)

Meine Frage ist nun, ob man das elegant und allgemeingültig formulieren kann ohne jede Ebene einzeln abzufragen.

Ale×

  1. im event die absoluten koordinaten des seiten klicks abfragen, dann die absoluten koordinaten des kastens ermitteln*, offsetwidth und offsetheight drauf addieren und schauen ob die mouseklicks innerhalb des bereiches passiert sind! :)

    *offsetparent ist dein freund

    1. Hallo zaphod1984,

      im event die absoluten koordinaten des seiten klicks abfragen, dann die absoluten koordinaten des kastens ermitteln*, offsetwidth und offsetheight drauf addieren und schauen ob die mouseklicks innerhalb des bereiches passiert sind! :)

      OK, eine ganz andere Herangehensweise... aber eine gute Idee!

      So sieht's aus:

      function mausklick(e)  
       {  
        // Klickposition ermitteln:  
        if(!e) e = window.event;  
        posX  = e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);  
        posY = e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);  
        // Position des Kastens ermitteln:  
        var obj = e.target || e.srcElement;  
        var boxX = document.getElementById('kasten').offsetLeft;  
        var boxY = document.getElementById('kasten').offsetTop;  
        var boxWidth = document.getElementById('kasten').offsetWidth;  
        var boxHeight = document.getElementById('kasten').offsetHeight;  
        // Prüfen, on außerhalb des Kastens geklickt wurde:  
        if(posX < boxX || posY > (boxX+boxWidth) || posY < boxY || posY > (boxY+boxHeight))  
         {  
          alert('Außerhalb des Kastens geklickt!');  
         }  
       }  
      document.onmousedown = mausklick;
      

      Ale×

      1. leider geht es nicht ganz so leicht, offsetTop gibt dir nur den vertikalen abstand zum ELTERNelement zurück.
        d.h. du musst de ganzen baum durchlatschen und die abstände aufaddieren:

          
           var returnAbsoluteTop = function (obj) {  
            var gesamtL = 0;  
            if (obj) {  
             gesamtL = obj.offsetTop;  
             if (obj.offsetParent) {  
              var e = obj.offsetParent;  
              while (e) {  
               gesamtL = gesamtL + e.offsetTop;  
               e = e.offsetParent;  
              }  
             }  
            }  
            return gesamtL;  
           }  
        
        
        --
        for your security, this text has been encrypted by ROT13 twice.
        1. analog dazu natürlich mit left.
          könnte man in der gleichen funktion unterbringen und zusammen z.B. als array zurück geben oder so.

          --
          for your security, this text has been encrypted by ROT13 twice.
        2. leider geht es nicht ganz so leicht, offsetTop gibt dir nur den vertikalen abstand zum ELTERNelement zurück.
          d.h. du musst de ganzen baum durchlatschen und die abstände aufaddieren...

          OK, in meinem Fall ist das Elternelement <body>, da stimmt es also.

          Hier die Demonstration - Klick auf blendet ein <div> ein, Klick außerhalb des <div>s schließt es wieder.

          Danke für den Tipp!
          Ale×

          1. Hier die Demonstration - Klick auf blendet ein <div> ein, Klick außerhalb des <div>s schließt es wieder.

            alles klar, du wolltest also verhinden dass ein klick auf die box die box schließt?

            dann hätte es folgender code auch getan:

              
              
            box.onclick = function (event) { event.cancelBubble = true; };  
              
            document.onmousedown = function () { box.style.display = 'none'; };  
              
            
            

            ungetestet!
            natürlich muss box noch irgendwo instanziiert werden.
            aber vom prinzip her verhinder das event.cancelBubble dass der klickevent an das document weitergegeben wird!

            --
            for your security, this text has been encrypted by ROT13 twice.
            1. alles klar, du wolltest also verhinden dass ein klick auf die box die box schließt?

              Nein, dass sie bei Klick außerhalb geschlossen wird! ;-)

              Ale×

              1. äh ja mein ich ja... ;)
                cancelBubble verhindert die weitergabe an den document-eventhandler.

                --
                for your security, this text has been encrypted by ROT13 twice.
                1. äh ja mein ich ja... ;)
                  cancelBubble verhindert die weitergabe an den document-eventhandler.

                  Aber nur im IE, ansonsten https://developer.mozilla.org/en/DOM/event.preventDefault

                  Struppi.

                  1. Aber nur im IE, ansonsten https://developer.mozilla.org/en/DOM/event.preventDefault

                    stimmt, laut standard und allen quellen schon, in allen tests die ich mit allen browsern durchgeführt habe sind die events aber immer gebubbelt, nicht entsprechend dem capturemodel oder dem w3c-model ausgeführt worden...

                    warum auch immer.

                    --
                    for your security, this text has been encrypted by ROT13 twice.
                    1. Aber nur im IE, ansonsten https://developer.mozilla.org/en/DOM/event.preventDefault

                      stimmt, laut standard und allen quellen schon, in allen tests die ich mit allen browsern durchgeführt habe sind die events aber immer gebubbelt, nicht entsprechend dem capturemodel oder dem w3c-model ausgeführt worden...

                      warum auch immer.

                      Argh, mein Fehler - das bubbeln stopt diese Funktion https://developer.mozilla.org/en/DOM/event.stopPropagation

                      Struppi.

  2. Hi,

    Das Problem ist nun: wenn in dem Kasten weitere Elemente vorkommen (<div>, <p>, <a> usw.) und auf diese geklickt wird, wird natürlich auch der alert ausgeführt.

    Eine Möglichkeit wäre nun, nach dem parentNode und dessen parentNode usw. zu schauen, es können ja beliebig viele Verschachtelungen enthalten sein:

    Meine Frage ist nun, ob man das elegant und allgemeingültig formulieren kann ohne jede Ebene einzeln abzufragen.

    Der IE und einige andere Browser kennen element.contains() - und fuer die, die es nicht kennen, ist eine Methode, die die Ermittlung rekursiv vornimmt und als prototype allen HTMLElementObject-Objekten hinzugefuegt wird, leicht selber zu erstellen (oder zu ergooglen).

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“