# Yahoo! UI Library

### Drag and Drop 2.7.0

Yahoo! UI Library > dragdrop > DD.js (source view)
Search:
Filters Show Private Show Protected Show Deprecated

    /**
     * A DragDrop implementation where the linked element follows the
     * mouse cursor during a drag.
     * @class DD
     * @extends YAHOO.util.DragDrop
     * @constructor
     * @param {String} id the id of the linked element
     * @param {String} sGroup the group of related DragDrop items
     * @param {object} config an object containing configurable attributes
     *                Valid properties for DD:
     *                    scroll
     */
    YAHOO.util.DD = function(id, sGroup, config) {
        if (id) {
            this.init(id, sGroup, config);
        }
    };

    YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, {

        /**
         * When set to true, the utility automatically tries to scroll the browser
         * window when a drag and drop element is dragged near the viewport boundary.
         * Defaults to true.
         * @property scroll
         * @type boolean
         */
        scroll: true,

        /**
         * Sets the pointer offset to the distance between the linked element's top
         * left corner and the location the element was clicked
         * @method autoOffset
         * @param {int} iPageX the X coordinate of the click
         * @param {int} iPageY the Y coordinate of the click
         */
        autoOffset: function(iPageX, iPageY) {
            var x = iPageX - this.startPageX;
            var y = iPageY - this.startPageY;
            this.setDelta(x, y);
            // this.logger.log("autoOffset el pos: " + aCoord + ", delta: " + x + "," + y);
        },

        /**
         * Sets the pointer offset.  You can call this directly to force the
         * offset to be in a particular location (e.g., pass in 0,0 to set it
         * to the center of the object, as done in YAHOO.widget.Slider)
         * @method setDelta
         * @param {int} iDeltaX the distance from the left
         * @param {int} iDeltaY the distance from the top
         */
        setDelta: function(iDeltaX, iDeltaY) {
            this.deltaX = iDeltaX;
            this.deltaY = iDeltaY;
            this.logger.log("deltaX:" + this.deltaX + ", deltaY:" + this.deltaY);
        },

        /**
         * Sets the drag element to the location of the mousedown or click event,
         * maintaining the cursor location relative to the location on the element
         * that was clicked.  Override this if you want to place the element in a
         * location other than where the cursor is.
         * @method setDragElPos
         * @param {int} iPageX the X coordinate of the mousedown or drag event
         * @param {int} iPageY the Y coordinate of the mousedown or drag event
         */
        setDragElPos: function(iPageX, iPageY) {
            // the first time we do this, we are going to check to make sure
            // the element has css positioning

            var el = this.getDragEl();
            this.alignElWithMouse(el, iPageX, iPageY);
        },

        /**
         * Sets the element to the location of the mousedown or click event,
         * maintaining the cursor location relative to the location on the element
         * that was clicked.  Override this if you want to place the element in a
         * location other than where the cursor is.
         * @method alignElWithMouse
         * @param {HTMLElement} el the element to move
         * @param {int} iPageX the X coordinate of the mousedown or drag event
         * @param {int} iPageY the Y coordinate of the mousedown or drag event
         */
        alignElWithMouse: function(el, iPageX, iPageY) {
            var oCoord = this.getTargetCoord(iPageX, iPageY);
            // this.logger.log("****alignElWithMouse : " + el.id + ", " + aCoord + ", " + el.style.display);

            if (!this.deltaSetXY) {
                var aCoord = [oCoord.x, oCoord.y];
                YAHOO.util.Dom.setXY(el, aCoord);

                var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
                var newTop  = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );

                this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
            } else {
                YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px");
                YAHOO.util.Dom.setStyle(el, "top",  (oCoord.y + this.deltaSetXY[1]) + "px");
            }

            this.cachePosition(oCoord.x, oCoord.y);
            var self = this;
            setTimeout(function() {
                self.autoScroll.call(self, oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
            }, 0);
        },

        /**
         * Saves the most recent position so that we can reset the constraints and
         * tick marks on-demand.  We need to know this so that we can calculate the
         * number of pixels the element is offset from its original position.
         * @method cachePosition
         * @param iPageX the current x position (optional, this just makes it so we
         * don't have to look it up again)
         * @param iPageY the current y position (optional, this just makes it so we
         * don't have to look it up again)
         */
        cachePosition: function(iPageX, iPageY) {
            if (iPageX) {
                this.lastPageX = iPageX;
                this.lastPageY = iPageY;
            } else {
                var aCoord = YAHOO.util.Dom.getXY(this.getEl());
                this.lastPageX = aCoord[0];
                this.lastPageY = aCoord[1];
            }
        },

        /**
         * Auto-scroll the window if the dragged object has been moved beyond the
         * visible window boundary.
         * @method autoScroll
         * @param {int} x the drag element's x position
         * @param {int} y the drag element's y position
         * @param {int} h the height of the drag element
         * @param {int} w the width of the drag element
         * @private
         */
        autoScroll: function(x, y, h, w) {

            if (this.scroll) {
                // The client height
                var clientH = this.DDM.getClientHeight();

                // The client width
                var clientW = this.DDM.getClientWidth();

                // The amt scrolled down
                var st = this.DDM.getScrollTop();

                // The amt scrolled right
                var sl = this.DDM.getScrollLeft();

                // Location of the bottom of the element
                var bot = h + y;

                // Location of the right of the element
                var right = w + x;

                // The distance from the cursor to the bottom of the visible area,
                // adjusted so that we don't scroll if the cursor is beyond the
                // element drag constraints
                var toBot = (clientH + st - y - this.deltaY);

                // The distance from the cursor to the right of the visible area
                var toRight = (clientW + sl - x - this.deltaX);

                // this.logger.log( " x: " + x + " y: " + y + " h: " + h +
                // " clientH: " + clientH + " clientW: " + clientW +
                // " st: " + st + " sl: " + sl + " bot: " + bot +
                // " right: " + right + " toBot: " + toBot + " toRight: " + toRight);

                // How close to the edge the cursor must be before we scroll
                // var thresh = (document.all) ? 100 : 40;
                var thresh = 40;

                // How many pixels to scroll per autoscroll op.  This helps to reduce
                // clunky scrolling. IE is more sensitive about this ... it needs this
                // value to be higher.
                var scrAmt = (document.all) ? 80 : 30;

                // Scroll down if we are near the bottom of the visible page and the
                // obj extends below the crease
                if ( bot > clientH && toBot < thresh ) {
                    window.scrollTo(sl, st + scrAmt);
                }

                // Scroll up if the window is scrolled down and the top of the object
                // goes above the top border
                if ( y < st && st > 0 && y - st < thresh ) {
                    window.scrollTo(sl, st - scrAmt);
                }

                // Scroll right if the obj is beyond the right border and the cursor is
                // near the border.
                if ( right > clientW && toRight < thresh ) {
                    window.scrollTo(sl + scrAmt, st);
                }

                // Scroll left if the window has been scrolled to the right and the obj
                // extends past the left border
                if ( x < sl && sl > 0 && x - sl < thresh ) {
                    window.scrollTo(sl - scrAmt, st);
                }
            }
        },

        /*
         * Sets up config options specific to this class. Overrides
         * YAHOO.util.DragDrop, but all versions of this method through the
         * inheritance chain are called
         */
        applyConfig: function() {
            YAHOO.util.DD.superclass.applyConfig.call(this);
            this.scroll = (this.config.scroll !== false);
        },

        /*
         * Event that fires prior to the onMouseDown event.  Overrides
         * YAHOO.util.DragDrop.
         */
        b4MouseDown: function(e) {
            this.setStartPosition();
            // this.resetConstraints();
            this.autoOffset(YAHOO.util.Event.getPageX(e),
                                YAHOO.util.Event.getPageY(e));
        },

        /*
         * Event that fires prior to the onDrag event.  Overrides
         * YAHOO.util.DragDrop.
         */
        b4Drag: function(e) {
            this.setDragElPos(YAHOO.util.Event.getPageX(e),
                                YAHOO.util.Event.getPageY(e));
        },

        toString: function() {
            return ("DD " + this.id);
        }

        //////////////////////////////////////////////////////////////////////////
        // Debugging ygDragDrop events that can be overridden
        //////////////////////////////////////////////////////////////////////////
        /*
        startDrag: function(x, y) {
            this.logger.log(this.id.toString()  + " startDrag");
        },

        onDrag: function(e) {
            this.logger.log(this.id.toString() + " onDrag");
        },

        onDragEnter: function(e, id) {
            this.logger.log(this.id.toString() + " onDragEnter: " + id);
        },

        onDragOver: function(e, id) {
            this.logger.log(this.id.toString() + " onDragOver: " + id);
        },

        onDragOut: function(e, id) {
            this.logger.log(this.id.toString() + " onDragOut: " + id);
        },

        onDragDrop: function(e, id) {
            this.logger.log(this.id.toString() + " onDragDrop: " + id);
        },

        endDrag: function(e) {
            this.logger.log(this.id.toString() + " endDrag");
        }

        */

    /**
    * @event mouseDownEvent
    * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event b4MouseDownEvent
    * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event mouseUpEvent
    * @description Fired from inside DragDropMgr when the drag operation is finished.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event b4StartDragEvent
    * @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event startDragEvent
    * @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event b4EndDragEvent
    * @description Fires before the endDragEvent. Returning false will cancel.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event endDragEvent
    * @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */

    /**
    * @event dragEvent
    * @description Occurs every mousemove event while dragging.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event b4DragEvent
    * @description Fires before the dragEvent.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event invalidDropEvent
    * @description Fires when the dragged objects is dropped in a location that contains no drop targets.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event b4DragOutEvent
    * @description Fires before the dragOutEvent
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event dragOutEvent
    * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event dragEnterEvent
    * @description Occurs when the dragged object first interacts with another targettable drag and drop object.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event b4DragOverEvent
    * @description Fires before the dragOverEvent.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event dragOverEvent
    * @description Fires every mousemove event while over a drag and drop object.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event b4DragDropEvent
    * @description Fires before the dragDropEvent
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    /**
    * @event dragDropEvent
    * @description Fires when the dragged objects is dropped on another.
    * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
    */
    });

Copyright © 2009 Yahoo! Inc. All rights reserved.