Mega Code Archive

 
Categories / JavaScript Tutorial / Drag Drop
 

Simulated Drag And Drop with zEvents Library and zDragDrop Library

< html>     <head>         <title>Simulated Drag And Drop Example</title>         <script type="text/javascript">         /*------------------------------------------------------------------------------  * JavaScript zEvents Library  * Version 1.1  * by Nicholas C. Zakas, http://www.nczonline.net/  * Copyright (c) 2004-2005 Nicholas C. Zakas. All Rights Reserved.  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU Lesser General Public License as published by  * the Free Software Foundation; either version 2.1 of the License, or  * (at your option) any later version.  *  * This program is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * GNU Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *------------------------------------------------------------------------------  */   /**  * Encapsulates information about an event.  * @scope public  * @class  */ function zEvent() {     /**      * The type of event.      * @scope public      */     this.type /*: String */   = null;          /**      * The object that caused the event.      * @scope public      */     this.target /*: zEventTarget */ = null;          /**      * A secondary object related to the event.      * @scope public      */     this.relatedTarget /*: zEventTarget */ = null;          /**      * Indicates whether or not the event can be canceled.      * @scope public      */     this.cancelable /*: boolean */ = false;          /**      * The time that the event occurred.      * @scope public      */     this.timeStamp /*: long */ = null;          /*      * Set to false to cancel event.      * @scope public      */     this.returnValue /*: boolean */ = true;     } /**  * Initializes the event object with information for the event.  * @scope public  * @param sType The type of event encapsulated by the object.  * @param bCancelable True if the event can be cancelled.  */ zEvent.prototype.initEvent = function (sType /*: String */,                                        bCancelable /*: boolean */) {     this.type = sType;     this.cancelable = bCancelable;     this.timeStamp = (new Date()).getTime(); }; /**  * Prevents the default behavior for an event.  * @scope public  */ zEvent.prototype.preventDefault = function () {     if (this.cancelable) {         this.returnValue = false;     } }; /**  * Any class that wants to support events should inherit from this.  * @class  * @scope public  */ function zEventTarget() {     /**      * Array of event handlers.      * @scope private      */     this.eventhandlers /*: Object */ = new Object(); } /**  * Adds an event listener function to handle the type of event.  * @scope public  * @param sType The type of event to handle (i.e., "mousemove", not "onmousemove").  * @param fnListener The listener function for the event.  */ zEventTarget.prototype.addEventListener = function (sType /*: String */,                                                     fnListener /*: Function */) {     if (typeof this.eventhandlers[sType] == "undefined") {         this.eventhandlers[sType] = new Array;     }             this.eventhandlers[sType][this.eventhandlers[sType].length] = fnListener;                                                     }; /**  * Causes an event to fire.  * @scope public  * @param oEvent The event object containing information about the event to fire.  * @return True if the event should continue, false if not.  */ zEventTarget.prototype.dispatchEvent = function (oEvent /*: zEvent */) /*: boolean */ {     /*      * Set the target of the event.      */     oEvent.target = this;     /*      * Call each event handler and pass in the event object.      */     if (typeof this.eventhandlers[oEvent.type] != "undefined") {         for (var i=0; i < this.eventhandlers[oEvent.type].length; i++) {                 this.eventhandlers[oEvent.type][i](oEvent);         }     }     /*      * Return the value of returnValue, which is changed to false      * when preventDefault() is called.      */     return oEvent.returnValue;                                                    }; /**  * Removes an event listener function from handling the type of event.  * @scope public  * @param sType The type of event to remove from (i.e., "mousemove", not "onmousemove").  * @param fnListener The listener function to remove.  */ zEventTarget.prototype.removeEventListener = function (sType /*: String */,                                                        fnListener /*: Function */) {     if (typeof this.eventhandlers[sType] != "undefined") {         var arrTemp = new Array;         for (var i=0; i < this.eventhandlers[sType].length; i++) {             if (this.eventhandlers[sType][i] != fnListener) {                 arrTemp[arrTemp.length] = this.eventhandlers[sType][i];             }         }         this.eventhandlers[sType] = arrTemp;     }                                                        };         </script>                          <script type="text/javascript"> /*------------------------------------------------------------------------------  * JavaScript zDragDrop Library  * Version 1.1  * by Nicholas C. Zakas, http://www.nczonline.net/  * Copyright (c) 2004-2005 Nicholas C. Zakas. All Rights Reserved.  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU Lesser General Public License as published by  * the Free Software Foundation; either version 2.1 of the License, or  * (at your option) any later version.  *  * This program is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * GNU Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *------------------------------------------------------------------------------  */   /*  * This library requires the free zEvents library available from   * http://www.nczonline.net/.  */ /**  * Contains global settings and methods for drag and drop functionality.  * @scope public  */ function zDrag() {} /**  * The item currently being dragged.  * @scope private  */ zDrag.current /*: zDraggable */ = null; /**  * Indicates whether or not an item is being dragged.  * @scope private  */ zDrag.dragging /*: boolean */ = false; /**  * Returns true if an item is being dragged.  * @scope public  * @return True if an item is being dragged, false if not.  * @type boolean  */ zDrag.isDragging = function () /*: boolean */ {     return this.dragging; }; /**  * Sets the item being dragged.  * @scope protected  * @param {zDraggable} oDraggable The draggable item.  * @type void  */ zDrag.setCurrent = function (oDraggable /*: zDraggable */) {     this.current = oDraggable;     this.dragging = true; }; /**  * Returns the currently dragged item.  * @scope public  * @return The currently dragged item.  * @type zDraggable  */ zDrag.getCurrent = function () /*: zDraggable */ {     return this.current; }; /**  * Clears the currently dragged item from memory and sets the dragging  * flag to false.  * @scope protected  * @type void  */ zDrag.clearCurrent = function () {     this.current = null;     this.dragging = false; }; /**  * Encapsulates the functionality for a draggable element.  * @scope public  * @extends zEventTarget  * @class  */ function zDraggable(oElement, iConstraints) {          /*      * Inherit properties from zEventTarget.      */     zEventTarget.call(this);          /*      * Call constructor.      */     this.construct(oElement, iConstraints);            /**      * The difference between the x cursor position and left edge of the element.      * @scope private      * @type int      */       this.diffX /*: int */ = 0;          /**      * The difference between the y cursor position and top edge of the element.      * @scope private      * @type int      */       this.diffY /*: int */ = 0;          /**      * Collection of drop targets for this item.      * @scope private      * @type Array      */     this.targets /*: Array */ = []; } /*  * Inherit methods from zEventTarget.  */ zDraggable.prototype = new zEventTarget; /**  * Indicates the dragged item can be dragged along the X axis.  * @scope public  * @type int  * @final  */ zDraggable.DRAG_X /*: int */ = 1; /**  * Indicates the dragged item can be dragged along the Y axis.  * @scope public  * @type int  * @final  */ zDraggable.DRAG_Y /*: int */ = 2; /**  * Adds a new drop target to the draggable item.  * @scope public  * @param {zDropTarget} oDropTarget The drop target to register for this item.  * @type void  */ zDraggable.prototype.addDropTarget = function (oDropTarget /*: zDropTarget */) {     this.targets.push(oDropTarget); }; /**  * Creates a new instance based on the given element and the constraints.  * @scope private  * @constructor  * @param {HTMLElement} oElement The DOM element to make draggable.  * @param {int} iConstraints The rules for dragging.  */ zDraggable.prototype.construct = function (oElement /*: HTMLElement */,                                             iConstraints /*: int */) {     /**      * The element to make draggable.      * @scope private      * @type HTMLElement      */     this.element /*: HTMLElement */ = oElement;          /**      * The constraints indicating the rules for dragging.      * @scope private      * @type int      */     this.constraints /*: int */ = iConstraints;          /*      * Create a pointer to this object.      */     var oThis = this;          /*      * Create a temporary function named fnTemp.      */     var fnTemp = function () {              /*          * Create a dragstart event and fire it.          */         var oDragStartEvent = new zDragDropEvent();         oDragStartEvent.initDragDropEvent("dragstart", true);                  /*          * If the event isn't cancelled, proceed.          */         if (oThis.dispatchEvent(oDragStartEvent)) {             /*              * Get the event objects, which is either the first              * argument (for DOM-compliant browsers and Netscape 4.x)              * or window.event (for IE).              */                 var oEvent = arguments[0] || window.event;                      /*              * Get the difference between the clientX and clientY              * and the position of the element.              */             oThis.diffX = oEvent.clientX - oThis.element.offsetLeft;             oThis.diffY = oEvent.clientY - oThis.element.offsetTop;               /*              * Add all DOM event handlers              */             oThis.attachEventHandlers();                              /*              * Set the currently dragged item.              */             zDrag.setCurrent(oThis);                 }       };          /*      * Determine which method to use to add the event handler.      */     if (this.element.addEventListener) {         this.element.addEventListener("mousedown", fnTemp, false);     } else if (this.element.attachEvent) {         this.element.attachEvent("onmousedown", fnTemp);     } else {         throw new Error("zDrag not supported in this browser.");     } }; /**  * Attaches event handlers for the mousemove and mouseup events.  * @scope private  * @private  * @type void  */ zDraggable.prototype.attachEventHandlers = function () {          /*      * Create a pointer to this object.      */     var oThis = this;          /*      * Create a temporary function named tempMouseMove.      */     this.tempMouseMove = function () {              /*          * Get the event objects, which is either the first          * argument (for DOM-compliant browsers and Netscape 4.x)          * or window.event (for IE).          */         var oEvent = arguments[0] || window.event;                  /*          * Get the new x and y coordinates for the dragged element by          * subtracting the difference in the x and y direction from           * the mouse position on the screen (clientX and clientY).          */         var iNewX = oEvent.clientX - oThis.diffX;         var iNewY = oEvent.clientY - oThis.diffY;                  /*          * Move the x coordinate if zDraggable.DRAG_X is an option.          */         if (oThis.constraints & zDraggable.DRAG_X) {             oThis.element.style.left = iNewX + "px";         }                  /*          * Move the y coordinate if zDraggable.DRAG_Y is an option.          */         if (oThis.constraints & zDraggable.DRAG_Y) {             oThis.element.style.top = iNewY + "px";         }                  /*          * Create and fire a drag event.          */         var oDragEvent = new zDragDropEvent();         oDragEvent.initDragDropEvent("drag", false);         oThis.dispatchEvent(oDragEvent);     };          /*      * Create a temporary function for the mouseup event.      */     oThis.tempMouseUp = function () {                 /*          * Get the event object.          */         var oEvent = arguments[0] || window.event;                  /*          * Determine if the mouse is over a drop target.          */         var oDropTarget = oThis.getDropTarget(oEvent.clientX, oEvent.clientY);         if (oDropTarget != null) {                      /*              * Fire the drop event.              */             var oDropEvent = new zDragDropEvent();             oDropEvent.initDragDropEvent("drop", false, oThis);             oDropTarget.dispatchEvent(oDropEvent);         }             /*          * Create and fire a dragend event.          */         var oDragEndEvent = new zDragDropEvent();         oDragEndEvent.initDragDropEvent("dragend", false);         oThis.dispatchEvent(oDragEndEvent);                      /*          * Clear the currently dragged item.          */          zDrag.clearCurrent();                          /*          * Detach all of the event handlers.          */         oThis.detachEventHandlers();     };          /*      * Determine which method to use to add the event handlers for      * the mousemove and mouseup events.      */     if (document.addEventListener) {         document.addEventListener("mousemove", this.tempMouseMove, false);         document.addEventListener("mouseup", this.tempMouseUp, false);     } else if (document.body.attachEvent) {         document.body.attachEvent("onmousemove", this.tempMouseMove);         document.body.attachEvent("onmouseup", this.tempMouseUp);     } else {         throw new Error("zDrag doesn't support this browser.");     }      }; /**  * Detaches event handlers for the mousemove and mouseup events.  * @scope private  */ zDraggable.prototype.detachEventHandlers = function () {     /*      * Determine the method for removing the event handlers for the      * mousemove and mouseup events.      */     if (document.removeEventListener) {         document.removeEventListener("mousemove", this.tempMouseMove, false);         document.removeEventListener("mouseup", this.tempMouseUp, false);     } else if (document.body.detachEvent) {         document.body.detachEvent("onmousemove", this.tempMouseMove);         document.body.detachEvent("onmouseup", this.tempMouseUp);     } else {         throw new Error("zDrag doesn't support this browser.");     } }; /**  * Determines the drop target that the mouse is over.  * @scope private  * @param iX The x-coordinate of the mouse.  * @param iY The y-coordinate of the mouse.  * @return The drop target if the mouse is over one, null otherwise.  */ zDraggable.prototype.getDropTarget = function (iX /*: int */,                                                 iY /*: int */) /*: zDropTarget */ {     for (var i=0; i < this.targets.length; i++) {         if (this.targets[i].isOver(iX, iY)) {             return this.targets[i];         }     }          return null; }; /**  * Moves the draggable element to a given position.  * @scope public  * @param iX The x-coordinate to move to.  * @param iY The y-coordinate to move to.  */ zDraggable.prototype.moveTo = function (iX /*: int */, iY /*: int */) {     this.element.style.left = iX + "px";     this.element.style.top = iY + "px"; }; /**  * Returns the left coordinate of the element.  * @scope public  * @return The left coordinate of the element.  */ zDraggable.prototype.getLeft = function () /*: int */ {     return this.element.offsetLeft; }; /**  * Returns the top coordinate of the element.  * @scope public  * @return The top coordinate of the element.  */ zDraggable.prototype.getTop = function () /*: int */ {     return this.element.offsetTop; }; /**  * Encapsulates information about a drag drop event.  * @class  * @scope public  * @extends zEvent  */ function zDragDropEvent() {     /*      * Inherit properties from zEvent.      */     zEvent.call(this); }  /*  * Inherit methods from zEvent.  */ zDragDropEvent.prototype = new zEvent(); /**  * Initializes the event object with information for the event.  * @scope public  * @param sType The type of event encapsulated by the object.  * @param bCancelable True if the event can be cancelled.  * @param oRelatedTarget The alternate target related to the event.  */ zDragDropEvent.prototype.initDragDropEvent = function(sType /*: String */,                                                       bCancelable /*: boolean */,                                                       oRelatedTarget /*: zEventTarget */) {     /*      * Call inherited method initEvent().      */     this.initEvent(sType, bCancelable);          /*      * Assign related target (may be null).      */     this.relatedTarget = oRelatedTarget; } /**  * A target for a zDraggable to be dropped.  * @scope public  * @class  * @extends zEventTarget  */ function zDropTarget(oElement) {     /*      * Inherit properties from zEventTarget.      */     zEventTarget.call(this);     /*      * Call constructor.      */     this.construct(oElement); } /*  * Inherit methods from zEventTarget.  */ zDropTarget.prototype = new zEventTarget; /**  * Creates a new instance based on the given DOM element.  * @constructor  * @scope public  * @param oElement The DOM element to make into a drop target.  */ zDropTarget.prototype.construct = function (oElement /*: HTMLElement */) {     /**      * The DOM element to use as a drop target.      * @scope private      */     this.element = oElement;      }; /**  * Determines if a given set of coordinates is over the element.  * @scope protected  * @param iX The x-coordinate to check.  * @param iY The y-coordinate to check.  * @return True if the coordinates are over the element, false if not.  */ zDropTarget.prototype.isOver = function (iX /*: int */, iY /*: int */) /*: boolean */ {     var iX1 = this.element.offsetLeft;     var iX2 = iX1 + this.element.offsetWidth;     var iY1 = this.element.offsetTop;     var iY2 = iY1 + this.element.offsetHeight;     return (iX >= iX1 && iX <= iX2 && iY >= iY1 && iY <= iY2); }; /**  * Returns the left coordinate of the drop target.  * @scope public  * @return The left coordinate of the drop target.  */ zDropTarget.prototype.getLeft = function () /*: int */ {     return this.element.offsetLeft; }; /**  * Returns the top coordinate of the drop target.  * @scope public  * @return The top coordinate of the drop target.  */ zDropTarget.prototype.getTop = function () /*: int */{     return this.element.offsetTop; }; /**  * Returns the height of the drop target.  * @scope public  * @return The height of the drop target.  */ zDropTarget.prototype.getHeight = function () /*: int */{     return this.element.offsetHeight; }; /**  * Returns the width of the drop target.  * @scope public  * @return The width of the drop target.  */ zDropTarget.prototype.getWidth = function () /*: int */{     return this.element.offsetWidth; };                 </script>         <script type="text/javascript">               function doLoad() {                 var oDraggable = new zDraggable(document.getElementById("div1"), zDraggable.DRAG_X | zDraggable.DRAG_Y);                 var oDropTarget = new zDropTarget(document.getElementById("divDropTarget"));                 oDraggable.addDropTarget(oDropTarget);                 oDropTarget.addEventListener("drop", function (oEvent) {                      oEvent.relatedTarget.moveTo(oDropTarget.getLeft(), oDropTarget.getTop());                 });             }                      </script>         <style type="text/css">             #div1 {                 background-color: red;                 height: 100px;                 width: 100px;                 position: absolute;                 z-index: 10;             }                          #divDropTarget {                 background-color: blue;                 height: 200px;                 width: 200px;                 position: absolute;                 left: 300px;                             }         </style>     </head>     <body onload="doLoad()">         <P>Try dragging the red square onto the blue square.</p>         <div id="div1"></div>         <div id="divDropTarget"></div>     </body> </html>