René: onclick, ondblclick, setTimeout und Opera

Hallo,

folgendes Problem mit dem Opera. Auf einem Link liegen zwei Funktionen eine wird per onclick und die andere per ondblclick ausgelöst. Damit das funktioniert ist ein setTimeout in der Funktion die bei onclick aufgerufen wird enthalten und in der Funktion die bei ondblclick aufgerufen wird dieser wieder gelöscht.

Das funktioniert im IE, Firefox, SeaMonkey baer nicht mit dem Opera. Das setTimeout wird trotz löschen im Opera ausgeführt. Wo liegt hier der Fehler?

var is_timer = null;  
  
/**/  
  
function box_checked()  
{  
 if (is_timer != null)  
  alert('box_checked | ' + typeof(is_timer) + ' | ' + is_timer);  
}  
  
function box_checked_timer(frm, nam)  
{  
 is_timer = window.setTimeout('box_checked();', 400);  
}  
  
function all_action()  
{  
 window.clearTimeout(is_timer);  
 delete is_timer; // funktioniert garnicht  
 is_timer = null; // ohne bleibt typeof = number  
  
 alert('all_action | ' + typeof(is_timer) + ' | ' + is_timer);  
}

<a href="javascript:void(0);" onclick="box_checked_timer();" ondblclick="all_action();">Testlink</a>

  1. Hallo,

    Bei einem Doppelklick feuert Opera folgende Events in folgender Reihenfolge:

    1. click
    2. dblclick
    3. click

    Firefox z.B. hingegen:

    1. click
    2. click
    3. dblclick

    Wenn nur der click-Handler den Timeout startet und der dblclick-Handler den Timeout abschaltet, so ist es klar, dass der Timeout im Opera *nicht* abgeschaltet wird, denn am Ende wird nochmal der click-Handler ausgeführt.

    Gut, jetzt sitzt du natürlich arg in der Tinte: Wie kann man im Opera Klick und Doppelklick unterscheiden? Etwas besseres als eine Timestamp-Lösung fällt mir nicht ein. Ich wüsste nicht, wie man sonst beim zweiten click-Ereignis feststellt, dass es zum vorigen dblclick-Ereignis gehört. Leider unterstützt Opera Eventobjekt.timeStamp nicht, aber man kann sich selbst etwas basteln. Ein anderes Indiz als die zeitliche Nähe wäre die räumliche.

    <style type="text/css">  
    [code lang=css]#p { width:200px; height:100px; background-color:red;}
    

    </style>
    <script type="text/javascript">

    function click (e) {  
     var timestamp = new Date().getTime();  
     anzeige.innerHTML += "click      " + timestamp + "<br>";  
     anzeige.innerHTML += "    <strong>clicked</strong> | " + this.click_timeout + "<br>";  
     this.click_timeout = null;  
    }  
    function clickstart (e) {  
     var timestamp = new Date().getTime();  
     anzeige.innerHTML += "clickstart " + timestamp + " | " + this.click_timeout + "<br>";  
     if (this.click_timeout) {  
      anzeige.innerHTML += "    click-Timeout laeuft bereits, beende<br>";  
      return;  
     }  
     if (this.last_doubleclick) {  
      anzeige.innerHTML += "    Vergleiche den Timestamp mit dem des letzten Doppelklicks<br>";  
      var differenz = timestamp - this.last_doubleclick;  
      anzeige.innerHTML += "    Timestamp-Differenz: " + differenz + "<br>";  
      if (differenz < 10) {  
       anzeige.innerHTML += "    Timestamp-Differenz nicht gross genug, beende<br>";  
       return;  
      }  
     }  
     anzeige.innerHTML += "    setTimeout<br>";  
     var obj = this;  
     this.click_timeout = window.setTimeout(function () { click.apply(obj, [e]); }, 400);  
    }  
      
    function dblclick (e) {  
     var timestamp = new Date().getTime();  
     this.last_doubleclick = timestamp;  
     anzeige.innerHTML += "dblclick   " + timestamp + "<br>";  
     if (this.click_timeout) {  
      anzeige.innerHTML += "   clearTimeout<br>";  
      window.clearTimeout(this.click_timeout);  
      this.click_timeout = null;  
     }  
     anzeige.innerHTML += "    <strong>dblclick</strong> | " + this.click_timeout + "<br>";  
    }  
      
    window.onload = function () {  
     anzeige = document.getElementById("anzeige");  
     var p = document.getElementById("p");  
     p.onclick = clickstart;  
     p.ondblclick = dblclick;  
    };
    

    </script>

    <p id="p"></a>

    <pre id="anzeige"></pre>[/code]

    Mathias