parseHint("Pro"): Drag&Drop: Browser-Unterschiede bei onmousemove?

Hallo,

folgendes Problem mit meinem drag&drop-Script:
 -> anscheinend werden bei FF mehr Maus-Bewegungen registriert als bei IE (?)

Ich habe eine div, darin das Bild eines Dia-Streifens (vertikal), wobei die
div einen niedrigeren height-Wert hat als das Bild (-> overflow: hidden;).
Über der div (also höherer z-index) liegt ein Bild von einem Dia-Rahmen.
Nun soll man mit drag&drop den Dia-Rahmen über den Dia-Streifen "schieben",
wobei in einem anderen Bereich immer das Bild zu sehen sein soll, über dessen
Dia-Streifen-Abschnitt sich gerade der Dia-Rahmen befindet.
Wenn der Rahmen an die obere bzw. untere Kante der div kommt, so soll das
Dia-Streifen-Bild entsprechend nach unten bzw. oben verschoben werden.
eine kl. Skizze:
-------
| [1] |    -> [1] dies ist der Streifen (in dem die Bilder 1-6 zu
| [2] |       [2] sehen sind  (wobei es sich aber nur um ein image
|{[3]}|       ... handelt
| [4] |
-------       der gestrichelte Rahmen ist die div,
  [5]         {   } ist das Dia-Rahmen-Bild
  [6]
der (vereinfachte) HTML-Schnippsel hierzu sieht so aus:

  
<div><img src="bilder/diastrip.png" id="strip" /></div>  
<div onmousedown="javascript:dragStart(this)"><img src="bilder/diarahmen.png" /></div>  
<div id="bildbox"><img src="bilder/strip1.jpg" /></div>  

das script:

  
function IDy(id) {  
       return  document.getElementById(id).style;  
}  
  
function ID(id) {  
       return document.getElementById(id);  
}  
  
var dragObjekt = false;  
  
var dragX = 0;  
var dragY = 0;  
  
var posX = 0;  
var posY = 0;  
  
var stripY;  
  
document.onmousemove = drag;  
document.onmouseup = new Function("dragObjekt=false");  
document.onmousedown = new Function("return false");  
  
function dragStart(element) {  
	dragObjekt = element;  
	dragX = posX - dragObjekt.offsetLeft;  
	dragY = posY - dragObjekt.offsetTop;  
}  
  
function drag(e) {  
  posX = document.all ? window.event.clientX : e.pageX;  
  posY = document.all ? window.event.clientY : e.pageY;  
  stripY = parseInt(IDy('strip').top);  
  if (dragObjekt != false) {  
// 116 = Oberkante der div; 477 = Unterkante der div minus height des Rahmens  
	if ((posY - dragY) > 116 && (posY - dragY) < 477) {  
		dragObjekt.style.top = (posY - dragY) + "px";  
	}  
	else if ((posY - dragY) <= 116) {  
		dragObjekt.style.top = "116px";  
		stripDown();  
	}  
	else if ((posY - dragY) >= 477) {  
		dragObjekt.style.top = "477px";  
		stripUp();  
	}  
// auf dem Streifen sind 10 Bildchen zu sehen, je von einer height von ca 52px  
	var stripMapTop = new Array(472, 420, 367, 315, 262, 210, 157, 105, 52, 0);  
	var stripMapBottom = new Array(523, 471, 419, 366, 314, 261, 209, 156, 104, 51);  
	var bild = ID('bildbox');  
	for (i=0; i<10; i++) {  
		if ((dragObjekt.offsetTop - 120) >= (stripMapTop[i] + stripY - 25) &&  
                   (dragObjekt.offsetTop - 120) <= (stripMapBottom[i] + stripY - 25)) {  
			bild.src = imgs[i].src;  
		}  
	}  
	return false;  
  }  
}  
  
function stripDown() {  
	if (dragObjekt == false) {return;}  
	stripY = parseInt(IDy('strip').top);  
	if (stripY < 0) {  
		IDy('strip').top = stripY + 1 + 'px';  
		setTimeout('stripDown()', 10);  
	}  
}  
  
function stripUp() {  
	if (dragObjekt == false) {return;}  
	stripY = parseInt(IDy('strip').top);  
	if (stripY > -103) {  
		IDy('strip').top = stripY - 1 + 'px';  
		setTimeout('stripUp()', 10);  
	}  
}  
	  
var imgs = new Array();  
  
function preloadImgs() {  
	for (i=0;i<10;i++) {  
		imgs[i] = new Image();  
		imgs[i].src = "bilder/strip"+(i+1)+".jpg";  
	}  
}  
  
preloadImgs();  

Bestimmt ist der Weg, wie ich über stripUp()/Down() die vertikale Bewegung
des Dia-Streifens handle, sehr stümperhaft - bin noch js-Anfäger...
Wenn mir jemand sagen kann, wie ich
(1) einen besseren Lösungsweg dafür finde, das Streifen-Bild zu bewegen,
    wenn der Rahmen die obere/untere Kante der div erreicht, und/oder
(2) es bewerkstellige, dass sich der Streife in allen Browsern
    gleichschnell bewegt, und/oder
(3) es erreichen kann, dass die Funktion drag() es sofort "schnallt", wenn
    sich durch stripUp()/Down() die top-Koordinate des Streifen-Bildes ver-
    ändert hat und dementsprechend mit dem Anzeigen des nun unter dem Rahmen-
    Bildes befindlichen Bildchens in der "bildbox" reagiert,
dann wäre ich sehr, sehr dankbar!

Bin mal gespannt, ob sich überhaupt jemand durch diese Nachricht gewühlt hat :D

lieben Gruß

  1. Hallo nochmal,

    ich befürchte, mein Posting war zu wirr oder zu lang :-(
    ich will hier jetzt nicht pushen, sondern meinen Fragen-Komplex abspecken
    und einfach nur wissen, ob mir jemand sagen kann, was ich machen muss,
    damit sich das drag-Objekt exakt in einem definierten Bereich draggen lässt -
    und nicht etwa ab und zu nur bis 5px vor den Rand.
    Hat das etwas mit der Schnelligkeit der Mausbewegung zu tun? Z.B., dass
    vielleicht onmousemove aufhört zu feuern, wenn der Cursor für kurze Zeit nicht
    über dem drag-Objekt ist?
    Und weiß jemand, wieso ich, wenn ich mir die Offset-Positionen des drag-Objektes
    in eine Tabelle schreiben lasse, von FF wesentlich mehr Einträge als von IE
    bekomme?

    Vielen Dank im Voraus für Deine Antwort!

    Lieben Gruß

    1. ich befürchte, mein Posting war zu wirr oder zu lang :-(

      z.T. ja. Die Beschreibung ist schwer nachvollziebar und ich müßte sie jetzt mehrmals lesen um zu verstehen, was dein Problem sein könnte, wozu ich aber ehrlich gesagt nicht viel Lust habe.

      Einfacher wäre es, wenn du eine Beispielseite bauen würdest, wo man das Problem nachvollziehen kann.

      Struppi.

      1. ich befürchte, mein Posting war zu wirr oder zu lang :-(

        z.T. ja. Die Beschreibung ist schwer nachvollziebar und ich müßte sie jetzt mehrmals lesen um zu verstehen, was dein Problem sein könnte, wozu ich aber ehrlich gesagt nicht viel Lust habe.

        Einfacher wäre es, wenn du eine Beispielseite bauen würdest, wo man das Problem nachvollziehen kann.

        Struppi.

        Hallo Struppi,
        danke Dir für Deine Antwort!
        Habe jetzt eine Beispielseite gebaut. Den Code kann man, so wie er ist,
        komplett übernehmen, um sich die Sache anzuschauen. Habe alles etwas ver-
        einfacht: keine Bilder, nur divs; statt beim draggen .src von Bildern zu ändern,
        ändert sich hier die background-color (eine Farbe entspricht in meinem eigentlichen
        Code einem Abschnitt des Dia-Streifen-images).

        das Javascript habe ich seit gestern schon abgeändert, s.d. es jetzt einiger-
        maßen funktioniert - auch wenn es wahrscheinlich alles andere als gut
        geschrieben ist...

        hier die Beispielseite:

          
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/transitional.dtd">  
        <html><head><title>Bildauswahl durch drag-drop</title>  
          
        <script type="text/javascript">  
          
        function IDy(id) {  
        	return  document.getElementById(id).style;  
        }  
          
        function ID(id) {  
        	return document.getElementById(id);  
        }  
          
        var dragObjekt = false;  
        var dragY = 0;  
        var posY = 0;  
        var stripY;  
        var aktuellePos;  
        var stripDownBusy = false;  
        var stripUpBusy = false;  
          
        document.onmousemove = drag;  
        document.onmouseup = new Function("dragObjekt=false");  
        document.onmousedown = new Function("return false"); // FF-internes D&D unterbinden  
          
        function dragStart(element) {  
        	dragObjekt = element;  
        	dragY = posY - dragObjekt.offsetTop;  
        }  
          
        function drag(e) {  
          posY = document.all ? (window.event.clientY + document.body.scrollTop  - document.body.clientTop) : e.pageY;  
          stripY = ID('diaStrip').offsetTop;  
          if (dragObjekt != false) {  
        	if ((posY - dragY) > 50 && (posY - dragY) < 200) {  
        		dragObjekt.style.top = (posY - dragY) + "px";  
        	}  
        	else if ((posY - dragY) <= 50) {  
        		dragObjekt.style.top = "50px";  
        		if (stripDownBusy == false) {  
        			stripDown();  
        		}  
        	}  
        	else if ((posY - dragY) >= 200) {  
        		dragObjekt.style.top = "200px";  
        		if (stripUpBusy == false) {  
        			stripUp();  
        		}  
        	}  
        	aktuellePos = posY - dragY;  
        	aktualisiereBild();  
        	return false;  
          }  
        }  
          
        function aktualisiereBild() {  
        	var stripMapTop = new Array(0, 100, 200, 300);  
        	var stripMapBottom = new Array(100, 200, 300, 400);  
        	var bgColors = new Array("blue", "green", "yellow", "orange");  
        	var bild = IDy('bildBox');  
        	for (i=0; i<4; i++) {  
        		if ((dragObjekt.offsetTop - 50) >= (stripMapTop[i] + stripY - 40) && (dragObjekt.offsetTop - 50) <= (stripMapBottom[i] + stripY - 40)) {  
        			bild.backgroundColor = bgColors[i];  
        		}  
        	}  
        }  
          
        function stripDown() {  
        	stripDownBusy = true;  
        	if (dragObjekt == false) {  
        		stripDownBusy = false;  
        		return;  
        	}  
        	stripY = ID('diaStrip').offsetTop;  
        	if (stripY < 0 && aktuellePos <= 50) {  
        		IDy('diaStrip').top = stripY + 2 + 'px';  
        		aktualisiereBild();  
        		setTimeout('stripDown()', 1);  
        	}  
        	else {stripDownBusy = false;}  
        }  
          
        function stripUp() {  
        	stripUpBusy = true;  
        	if (dragObjekt == false) {  
        		stripUpBusy = false;  
        		return;  
        	}  
        	stripY = ID('diaStrip').offsetTop;  
        	if (stripY > -150 && aktuellePos >= 200) {  
        		IDy('diaStrip').top = stripY - 2 + 'px';  
        		aktualisiereBild();  
        		setTimeout('stripUp()', 1);  
        	}  
        	else {stripUpBusy = false;}  
        }  
        /*	  
        var imgs = new Array();  
          
        function preloadImgs() {  
        	for (i=0;i<10;i++) {  
        		imgs[i] = new Image();  
        		imgs[i].src = "bilder/strip"+(i+1)+".jpg";  
        	}  
        }  
          
        preloadImgs();*/  
        </script>  
        	  
        <style type="text/css">  
        #diaStripBox {position: absolute; top: 50px; left: 50px; width: 100px; height: 250px; overflow: hidden; border: 1px solid black;}  
        #diaStrip {position: absolute; top: 0px; left: 0px; width: 100px; height: 500px;}  
        #abschnitt1 {height: 100px; background-color: blue;}  
        #abschnitt2 {height: 100px; background-color: green;}  
        #abschnitt3 {height: 100px; background-color: yellow;}  
        #abschnitt4 {height: 100px; background-color: orange;}  
        #diaRahmen {position: absolute; top: 170px; left: 45px; width: 110px; height: 100px; border: 3px solid grey; cursor: move; z-index: 2;}  
        #bildBox {position: absolute; top: 50px; left: 250px; width: 300px; height: 300px; border: 3px solid black; background-color: green;}  
        </style>  
          
        </head><body>  
        <div id="diaStripBox">  
        	<div id="diaStrip">  
        		<div id="abschnitt1"></div>  
        		<div id="abschnitt2"></div>  
        		<div id="abschnitt3"></div>  
        		<div id="abschnitt4"></div>  
        	</div>  
        </div>  
        <div id="diaRahmen" onmousedown="javascript:dragStart(this)"></div>  
        <div id="bildBox"></div>  
        </body></html>  
        
        
        1. Liebe(r) parseHint("Pro"),

          Habe alles etwas ver-
          einfacht: keine Bilder, nur divs; statt beim draggen .src von Bildern zu
          ändern, ändert sich hier die background-color (eine Farbe entspricht in
          meinem eigentlichen Code einem Abschnitt des Dia-Streifen-images).

          damit hast Du aber die Problemstellung entscheidend verändert! Die Browser bieten bei Bildern ein zusätzliches Drag&Drop-Verhalten an, welches bei <div>-Elementen so nicht einsetzt. Oder kannst Du (ohne vorheriges Markieren!) durch einfaches Drag&Drop den Inhalt eines <div>-Elements aus dem Browser in ein Verzeichnis (z.B. Desktop) kopieren?

          Um das browserseitige Drag&Drop bei Grafiken zu deaktivieren braucht es ein paar Tricks. Ich verwende folgende Funktion, um (im IE) dieses "Extra-Drag&Drop" zu unterbinden:

          	Quiz.antiMarkierungsModusFuerIE = function (schalter) {  
          		if (schalter) {  
          			// Anti-Markierungs-Effekt für IE einschalten  
          			Quiz.oldDocOnSelectStart = window.document.onselectstart;  
          			Quiz.oldDocOnDragStart = window.document.ondragstart;  
          			window.document.onselectstart = function () { return false;};  
          			window.document.ondragstart = function () { return false;};  
            
          		} else {  
          			// Anti-Markier-Effekt für IE beenden  
          			if (Quiz.oldDocOnSelectStart || typeof(window.document.onselectstart) == "function")  
          				window.document.onselectstart = Quiz.oldDocOnSelectStart;  
            
          			if (Quiz.oldDocOnDragStart || typeof(window.document.ondragstart) == "function")  
          				window.document.ondragstart = Quiz.oldDocOnDragStart;  
          		}  
          	};
          

          Obige Funktion ist aus meinem Quiz-Framework entnommen, daher das globale Quiz-Objekt. Du kannst es aber anders machen...

          Liebe Grüße,

          Felix Riesterer.

          --
          ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
          1. damit hast Du aber die Problemstellung entscheidend verändert

            Lieber Felix,

            ich danke Dir sehr für Deine Antwort.
            Die Beispielseite sollte nur der Veranschaulichung dienen, damit jemand (z.B.
            Struppi) sich das kopieren und auf seinem Browser laufen lassen kann. Hierbei
            kam es darauf an, zu zeigen, was ich mit dem wechselseitgen Verhalten der
            Funktionen drag() und stripUp()/Down() meinte.
            Dass es da so einige Problemchen gibt, wenn man z.B. Bilder in einer div
            draggen will, hatte ich bemerkt, und ich freue mich über den Codeschnippsel von
            Dir, den ich auch gleich einsetzen werden :-}

            Im Großen und Ganzen erfüllt mittlerweile mein Script seine Zwecke - auch wenn
            mir professionellere Methoden lieber gewesen wären - ist jetzt halt alles etwas
            stümperhaft zusammengekleistert; insbesondere die Regulierung des Zusammenspiels
            der drag- und der strip-Funktionen mittels der Variablen stripUpBusy bzw.
            stripDownBusy.
            Außerdem verstehe ich immer noch nicht ganz, warum die Funktion drag() bei
            FF anscheinend öfter durchlaufen wird als bei IE.
            Aber besser ein funktionierendes Noobie-Script als ein nicht
            funktionierender Profi-Script-Versuch ;}

            Liebe Grüße und danke für Deine Hilfe,
            (der) parseHint("pro")