Wie geht das mit dem Drag-and-Drop

Saturday, 15. April, 2006

Drag-and-Drop ist einer der wichtigsten Komponenten auf BunteSuppe.de. Dieses Tutorium beschreibt eine simple Methode, wie man die Drag-and-Drop Funktionalität auf einer Webseite mit Hilfe von JavaScript einbaut.

Das Set-Up

Wir müssen ein paar Dinge vorbereiten, bevor wir uns um den eigentlichen Drag-and-Drop Code kümmern können. Wir brauchen zuerst einmal ein Objekt, dass gedraggt oder gezogen werden soll. In unserem Beispiel wird es nur ein ziehbares Objekt geben, aber es kann auch auf eine unbeschränkte Anzahl an Objekten erweitert werden. Wir verwenden ein div Element, aber man könnte auch jedes andere sichtbare Element wie beispielsweise ein img Element verwenden.

Zuerst braucht das Objekt ein CSS Styling. Für dieses Demo haben wir ihm einen grünen Hintergrund und einen netten abgeschrägten Border gegeben. Es muss außerdem in position:absolute; gesetzt werden, so dass es frei ist von der Cascade des Dokuments und es überall im Browser Window positioniert werden kann.

Es müssen auch ein paar Sachen in JavaScript bei der Page Load passieren. Wir bestimmen document.onmousemove und document.onmouseup, damit unsere Funktionen laufen, wenn jedes der Ereignisse ausgelöst wird. Diese Funktionen werden kurz beschrieben.

Wir müssen auch einige Globals setzen und eine Initialisierungs-Funktion laufen lassen. Die Position des Zieh-Objekts wird in dieser Funktion gesetzt, so dass die linken und oberen Eigenschaften initialisiert werden. Du könntest es auch im CSS positionieren, aber dann könntest Du diese Werte nicht via JavaScript aufrufen.

Das Objekt ist nun auf display:none im CSS und auf display:block in JavaScript gesetzt. Das ist deshalb so, damit es unsichtbar ist, bis es für’s Draggen bereit ist.

Die ondrag und onselectstart Einstellungen sind dafür da, um ein falsches Verhalten im Internet Explorer zu stoppen. Das sind IE spezifische Methoden, die das Verhalten von Click-and-Drag Aktionen beeinflussen. Indem wir sie als leere Funktionen setzen, sind sie ausgeschalten. Ansonsten würde der Internet Explorer glauben, dass Du einen Text markieren willst und er würde alles highlighten.

var dragObject, offsetX, offsetY, isDragging=false;
window.onload = init;
document.onmousemove = mM;
document.onmouseup = mU;

function init() {
	var ob = document.getElementById("dragObject");

	ob.ondrag=function(){return false;};
	ob.onselectstart=function(){return false;};

	ob.style.left="100px";
	ob.style.top="100px";
	ob.style.display="block";
}

Mouse Down Event

Wenn Du das alles vorbereitet hast, wird das Drag-and-Drop von drei DOM Events bestimmt: onmousedown, onmousemove und onmouseup. Zuerst einmal wollen wird das onmousedown auf dem Objekt ermitteln. Unsere eigene Funktion wird diesem Objekt zugeteilt, um dann zu laufen, wenn die Maus gedrückt wird.

Es gibt verschiedene Arten, um eine Funktion diesem Ereignis zuzuordnen. Der einfachste Weg ist der Gebrauch des onmousedown Attributes, das in HTML definiert werden kann:

<div onmousedown="javascript: mD(this,event);"></div>

Das this Argument ist ein Pointer zum Objekt, das angeklickt worden ist. Das event Argument läuft durch eine Refernenz zum event Objekt selbst. Das enthält alle möglichen Daten, die Teil des Mouse Down Events sind. Der Internet Explorer macht das auf seine eigene Art und Weise, indem er das Objekt via window.event abruft.

function mD(dragObject, e) {
	if (window.event) e=window.event;
	//mouse down handling...
}

Wir müssen die Position der Maus und die Position des Drag Objekts kennen. Die Position der Maus ist im Event Objekt als clientX und clientY enthalten. Die Position des Drag Objekts kann über style.left und style.top abgerufen werden, welche wir von Strings in Integer umwandeln, indem wir parseInt verwenden. Mit diesen vier Werten berechnen wir die Distanz zwischen der Maus und dem Top-Left des Drag Objekts.

Wir setzen ebenfalls die Global isDragging auf wahr. Das zeigt den anderen Funktionen, dass ein Drag durchgeführt wird.

Wir beenden jeden der Mouse Handler mit return false. Das bedeutet, dass das Ereignis angehalten wurde und kein anderes Verhalten vom Browser oder Betriebssystem auftreten wird.

function mD(ob,e) {
	dragObject = ob;

	if (window.event) e=window.event;

	var dragX = parseInt(dragObject.style.left);
	var dragY = parseInt(dragObject.style.top);

	var mouseX = e.clientX;
	var mouseY = e.clientY;

	offsetX = mouseX - dragX;
	offsetY = mouseY - dragY;

	isDragging = true;

	return false;
}

Mouse Move Event

Die mM Funktion läuft jedes Mal, wenn die Maus bewegt wird. Wir wollen nur, das etwas passiert, wenn das Objekt bewegt wird. Wir beenden die Funktion, wenn gerade kein Dragging, also Ziehen, stattfindet, indem wir return sagen.

Wenn das Objekt gezogen wird, wollen wir es unter dem Maus Pointer repositionieren. Noch einmal rufen wir die Mausposition mittels event.clientX und event.clientY auf. Indem wir die räumliche Verschiebung (die Offsets) verwenden, die in mD berechnet worden sind, repositionieren wir unser Drag Objekt:

function mM(e) {
	if (!isDragging) return;

	if (window.event) e=window.event;

	var newX = e.clientX - offsetX;
	var newY = e.clientY - offsetY;

	dragObject.style.left = newX + "px";
	dragObject.style.top = newY + "px";

	return false;
}

Mouse Up Event

Das Ziehen muss gestoppt werden beim mouseup. Alles was wir tun müssen, ist isDragging auf falsch setzen und das Ziehen wird beendet.

function mU() {
	if (!isDragging) return;
	isDragging = false;
	return false;
}

Beispiel

Klick hier, um das ganze JavaScript Dragging Beispiel in Action zu sehen. Gerne kannst Du den Code verwenden!