JavaScript Tutorial/Drag Drop/Drag Drop

Материал из Web эксперт
Перейти к: навигация, поиск

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>


System Drag And Drop between two text boxes

<html>
    <head>
        <title>System Drag And Drop between two text boxes</title>
        <script type="text/javascript">
            function handleDragDropEvent(oEvent) {
                var oTextbox = document.getElementById("txt1");
                oTextbox.value +=  oEvent.type + "\n";
            }
        </script>
    </head>
    <body>
        <P>Try dragging the text from the left textbox to the right one.</p>
        <P>
        <input type="text" value="drag this text"
                  ondragstart="handleDragDropEvent(event)"
                  ondrag="handleDragDropEvent(event)"
                  ondragend="handleDragDropEvent(event)" />
        <input type="text"
               ondragenter="handleDragDropEvent(event)"
               ondragover="handleDragDropEvent(event)"
               ondragleave="handleDragDropEvent(event)"
               ondrop="handleDragDropEvent(event)" />
        </p>
        <P><textarea rows="10" cols="25" readonly="readonly" id="txt1"></textarea></p>
    </body>
</html>