[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 YUI.add('yui2-dragdrop', function(Y) { 2 var YAHOO = Y.YUI2; 3 /* 4 Copyright (c) 2011, Yahoo! Inc. All rights reserved. 5 Code licensed under the BSD License: 6 http://developer.yahoo.com/yui/license.html 7 version: 2.9.0 8 */ 9 /** 10 * The drag and drop utility provides a framework for building drag and drop 11 * applications. In addition to enabling drag and drop for specific elements, 12 * the drag and drop elements are tracked by the manager class, and the 13 * interactions between the various elements are tracked during the drag and 14 * the implementing code is notified about these important moments. 15 * @module dragdrop 16 * @title Drag and Drop 17 * @requires yahoo,dom,event 18 * @namespace YAHOO.util 19 */ 20 21 // Only load the library once. Rewriting the manager class would orphan 22 // existing drag and drop instances. 23 if (!YAHOO.util.DragDropMgr) { 24 25 /** 26 * DragDropMgr is a singleton that tracks the element interaction for 27 * all DragDrop items in the window. Generally, you will not call 28 * this class directly, but it does have helper methods that could 29 * be useful in your DragDrop implementations. 30 * @class DragDropMgr 31 * @static 32 */ 33 YAHOO.util.DragDropMgr = function() { 34 35 var Event = YAHOO.util.Event, 36 Dom = YAHOO.util.Dom; 37 38 return { 39 /** 40 * This property is used to turn on global use of the shim element on all DragDrop instances, defaults to false for backcompat. (Use: YAHOO.util.DDM.useShim = true) 41 * @property useShim 42 * @type Boolean 43 * @static 44 */ 45 useShim: false, 46 /** 47 * This property is used to determine if the shim is active over the screen, default false. 48 * @private 49 * @property _shimActive 50 * @type Boolean 51 * @static 52 */ 53 _shimActive: false, 54 /** 55 * This property is used when useShim is set on a DragDrop object to store the current state of DDM.useShim so it can be reset when a drag operation is done. 56 * @private 57 * @property _shimState 58 * @type Boolean 59 * @static 60 */ 61 _shimState: false, 62 /** 63 * This property is used when useShim is set to true, it will set the opacity on the shim to .5 for debugging. Use: (YAHOO.util.DDM._debugShim = true;) 64 * @private 65 * @property _debugShim 66 * @type Boolean 67 * @static 68 */ 69 _debugShim: false, 70 /** 71 * This method will create a shim element (giving it the id of yui-ddm-shim), it also attaches the mousemove and mouseup listeners to it and attaches a scroll listener on the window 72 * @private 73 * @method _sizeShim 74 * @static 75 */ 76 _createShim: function() { 77 YAHOO.log('Creating Shim Element', 'info', 'DragDropMgr'); 78 var s = document.createElement('div'); 79 s.id = 'yui-ddm-shim'; 80 if (document.body.firstChild) { 81 document.body.insertBefore(s, document.body.firstChild); 82 } else { 83 document.body.appendChild(s); 84 } 85 s.style.display = 'none'; 86 s.style.backgroundColor = 'red'; 87 s.style.position = 'absolute'; 88 s.style.zIndex = '99999'; 89 Dom.setStyle(s, 'opacity', '0'); 90 this._shim = s; 91 Event.on(s, "mouseup", this.handleMouseUp, this, true); 92 Event.on(s, "mousemove", this.handleMouseMove, this, true); 93 Event.on(window, 'scroll', this._sizeShim, this, true); 94 }, 95 /** 96 * This method will size the shim, called from activate and on window scroll event 97 * @private 98 * @method _sizeShim 99 * @static 100 */ 101 _sizeShim: function() { 102 if (this._shimActive) { 103 YAHOO.log('Sizing Shim', 'info', 'DragDropMgr'); 104 var s = this._shim; 105 s.style.height = Dom.getDocumentHeight() + 'px'; 106 s.style.width = Dom.getDocumentWidth() + 'px'; 107 s.style.top = '0'; 108 s.style.left = '0'; 109 } 110 }, 111 /** 112 * This method will create the shim element if needed, then show the shim element, size the element and set the _shimActive property to true 113 * @private 114 * @method _activateShim 115 * @static 116 */ 117 _activateShim: function() { 118 if (this.useShim) { 119 YAHOO.log('Activating Shim', 'info', 'DragDropMgr'); 120 if (!this._shim) { 121 this._createShim(); 122 } 123 this._shimActive = true; 124 var s = this._shim, 125 o = '0'; 126 if (this._debugShim) { 127 o = '.5'; 128 } 129 Dom.setStyle(s, 'opacity', o); 130 this._sizeShim(); 131 s.style.display = 'block'; 132 } 133 }, 134 /** 135 * This method will hide the shim element and set the _shimActive property to false 136 * @private 137 * @method _deactivateShim 138 * @static 139 */ 140 _deactivateShim: function() { 141 YAHOO.log('Deactivating Shim', 'info', 'DragDropMgr'); 142 this._shim.style.display = 'none'; 143 this._shimActive = false; 144 }, 145 /** 146 * The HTML element created to use as a shim over the document to track mouse movements 147 * @private 148 * @property _shim 149 * @type HTMLElement 150 * @static 151 */ 152 _shim: null, 153 /** 154 * Two dimensional Array of registered DragDrop objects. The first 155 * dimension is the DragDrop item group, the second the DragDrop 156 * object. 157 * @property ids 158 * @type {string: string} 159 * @private 160 * @static 161 */ 162 ids: {}, 163 164 /** 165 * Array of element ids defined as drag handles. Used to determine 166 * if the element that generated the mousedown event is actually the 167 * handle and not the html element itself. 168 * @property handleIds 169 * @type {string: string} 170 * @private 171 * @static 172 */ 173 handleIds: {}, 174 175 /** 176 * the DragDrop object that is currently being dragged 177 * @property dragCurrent 178 * @type DragDrop 179 * @private 180 * @static 181 **/ 182 dragCurrent: null, 183 184 /** 185 * the DragDrop object(s) that are being hovered over 186 * @property dragOvers 187 * @type Array 188 * @private 189 * @static 190 */ 191 dragOvers: {}, 192 193 /** 194 * the X distance between the cursor and the object being dragged 195 * @property deltaX 196 * @type int 197 * @private 198 * @static 199 */ 200 deltaX: 0, 201 202 /** 203 * the Y distance between the cursor and the object being dragged 204 * @property deltaY 205 * @type int 206 * @private 207 * @static 208 */ 209 deltaY: 0, 210 211 /** 212 * Flag to determine if we should prevent the default behavior of the 213 * events we define. By default this is true, but this can be set to 214 * false if you need the default behavior (not recommended) 215 * @property preventDefault 216 * @type boolean 217 * @static 218 */ 219 preventDefault: true, 220 221 /** 222 * Flag to determine if we should stop the propagation of the events 223 * we generate. This is true by default but you may want to set it to 224 * false if the html element contains other features that require the 225 * mouse click. 226 * @property stopPropagation 227 * @type boolean 228 * @static 229 */ 230 stopPropagation: true, 231 232 /** 233 * Internal flag that is set to true when drag and drop has been 234 * initialized 235 * @property initialized 236 * @private 237 * @static 238 */ 239 initialized: false, 240 241 /** 242 * All drag and drop can be disabled. 243 * @property locked 244 * @private 245 * @static 246 */ 247 locked: false, 248 249 /** 250 * Provides additional information about the the current set of 251 * interactions. Can be accessed from the event handlers. It 252 * contains the following properties: 253 * 254 * out: onDragOut interactions 255 * enter: onDragEnter interactions 256 * over: onDragOver interactions 257 * drop: onDragDrop interactions 258 * point: The location of the cursor 259 * draggedRegion: The location of dragged element at the time 260 * of the interaction 261 * sourceRegion: The location of the source elemtn at the time 262 * of the interaction 263 * validDrop: boolean 264 * @property interactionInfo 265 * @type object 266 * @static 267 */ 268 interactionInfo: null, 269 270 /** 271 * Called the first time an element is registered. 272 * @method init 273 * @private 274 * @static 275 */ 276 init: function() { 277 this.initialized = true; 278 }, 279 280 /** 281 * In point mode, drag and drop interaction is defined by the 282 * location of the cursor during the drag/drop 283 * @property POINT 284 * @type int 285 * @static 286 * @final 287 */ 288 POINT: 0, 289 290 /** 291 * In intersect mode, drag and drop interaction is defined by the 292 * cursor position or the amount of overlap of two or more drag and 293 * drop objects. 294 * @property INTERSECT 295 * @type int 296 * @static 297 * @final 298 */ 299 INTERSECT: 1, 300 301 /** 302 * In intersect mode, drag and drop interaction is defined only by the 303 * overlap of two or more drag and drop objects. 304 * @property STRICT_INTERSECT 305 * @type int 306 * @static 307 * @final 308 */ 309 STRICT_INTERSECT: 2, 310 311 /** 312 * The current drag and drop mode. Default: POINT 313 * @property mode 314 * @type int 315 * @static 316 */ 317 mode: 0, 318 319 /** 320 * Runs method on all drag and drop objects 321 * @method _execOnAll 322 * @private 323 * @static 324 */ 325 _execOnAll: function(sMethod, args) { 326 for (var i in this.ids) { 327 for (var j in this.ids[i]) { 328 var oDD = this.ids[i][j]; 329 if (! this.isTypeOfDD(oDD)) { 330 continue; 331 } 332 oDD[sMethod].apply(oDD, args); 333 } 334 } 335 }, 336 337 /** 338 * Drag and drop initialization. Sets up the global event handlers 339 * @method _onLoad 340 * @private 341 * @static 342 */ 343 _onLoad: function() { 344 345 this.init(); 346 347 YAHOO.log("DragDropMgr onload", "info", "DragDropMgr"); 348 Event.on(document, "mouseup", this.handleMouseUp, this, true); 349 Event.on(document, "mousemove", this.handleMouseMove, this, true); 350 Event.on(window, "unload", this._onUnload, this, true); 351 Event.on(window, "resize", this._onResize, this, true); 352 // Event.on(window, "mouseout", this._test); 353 354 }, 355 356 /** 357 * Reset constraints on all drag and drop objs 358 * @method _onResize 359 * @private 360 * @static 361 */ 362 _onResize: function(e) { 363 YAHOO.log("window resize", "info", "DragDropMgr"); 364 this._execOnAll("resetConstraints", []); 365 }, 366 367 /** 368 * Lock all drag and drop functionality 369 * @method lock 370 * @static 371 */ 372 lock: function() { this.locked = true; }, 373 374 /** 375 * Unlock all drag and drop functionality 376 * @method unlock 377 * @static 378 */ 379 unlock: function() { this.locked = false; }, 380 381 /** 382 * Is drag and drop locked? 383 * @method isLocked 384 * @return {boolean} True if drag and drop is locked, false otherwise. 385 * @static 386 */ 387 isLocked: function() { return this.locked; }, 388 389 /** 390 * Location cache that is set for all drag drop objects when a drag is 391 * initiated, cleared when the drag is finished. 392 * @property locationCache 393 * @private 394 * @static 395 */ 396 locationCache: {}, 397 398 /** 399 * Set useCache to false if you want to force object the lookup of each 400 * drag and drop linked element constantly during a drag. 401 * @property useCache 402 * @type boolean 403 * @static 404 */ 405 useCache: true, 406 407 /** 408 * The number of pixels that the mouse needs to move after the 409 * mousedown before the drag is initiated. Default=3; 410 * @property clickPixelThresh 411 * @type int 412 * @static 413 */ 414 clickPixelThresh: 3, 415 416 /** 417 * The number of milliseconds after the mousedown event to initiate the 418 * drag if we don't get a mouseup event. Default=1000 419 * @property clickTimeThresh 420 * @type int 421 * @static 422 */ 423 clickTimeThresh: 1000, 424 425 /** 426 * Flag that indicates that either the drag pixel threshold or the 427 * mousdown time threshold has been met 428 * @property dragThreshMet 429 * @type boolean 430 * @private 431 * @static 432 */ 433 dragThreshMet: false, 434 435 /** 436 * Timeout used for the click time threshold 437 * @property clickTimeout 438 * @type Object 439 * @private 440 * @static 441 */ 442 clickTimeout: null, 443 444 /** 445 * The X position of the mousedown event stored for later use when a 446 * drag threshold is met. 447 * @property startX 448 * @type int 449 * @private 450 * @static 451 */ 452 startX: 0, 453 454 /** 455 * The Y position of the mousedown event stored for later use when a 456 * drag threshold is met. 457 * @property startY 458 * @type int 459 * @private 460 * @static 461 */ 462 startY: 0, 463 464 /** 465 * Flag to determine if the drag event was fired from the click timeout and 466 * not the mouse move threshold. 467 * @property fromTimeout 468 * @type boolean 469 * @private 470 * @static 471 */ 472 fromTimeout: false, 473 474 /** 475 * Each DragDrop instance must be registered with the DragDropMgr. 476 * This is executed in DragDrop.init() 477 * @method regDragDrop 478 * @param {DragDrop} oDD the DragDrop object to register 479 * @param {String} sGroup the name of the group this element belongs to 480 * @static 481 */ 482 regDragDrop: function(oDD, sGroup) { 483 if (!this.initialized) { this.init(); } 484 485 if (!this.ids[sGroup]) { 486 this.ids[sGroup] = {}; 487 } 488 this.ids[sGroup][oDD.id] = oDD; 489 }, 490 491 /** 492 * Removes the supplied dd instance from the supplied group. Executed 493 * by DragDrop.removeFromGroup, so don't call this function directly. 494 * @method removeDDFromGroup 495 * @private 496 * @static 497 */ 498 removeDDFromGroup: function(oDD, sGroup) { 499 if (!this.ids[sGroup]) { 500 this.ids[sGroup] = {}; 501 } 502 503 var obj = this.ids[sGroup]; 504 if (obj && obj[oDD.id]) { 505 delete obj[oDD.id]; 506 } 507 }, 508 509 /** 510 * Unregisters a drag and drop item. This is executed in 511 * DragDrop.unreg, use that method instead of calling this directly. 512 * @method _remove 513 * @private 514 * @static 515 */ 516 _remove: function(oDD) { 517 for (var g in oDD.groups) { 518 if (g) { 519 var item = this.ids[g]; 520 if (item && item[oDD.id]) { 521 delete item[oDD.id]; 522 } 523 } 524 525 } 526 delete this.handleIds[oDD.id]; 527 }, 528 529 /** 530 * Each DragDrop handle element must be registered. This is done 531 * automatically when executing DragDrop.setHandleElId() 532 * @method regHandle 533 * @param {String} sDDId the DragDrop id this element is a handle for 534 * @param {String} sHandleId the id of the element that is the drag 535 * handle 536 * @static 537 */ 538 regHandle: function(sDDId, sHandleId) { 539 if (!this.handleIds[sDDId]) { 540 this.handleIds[sDDId] = {}; 541 } 542 this.handleIds[sDDId][sHandleId] = sHandleId; 543 }, 544 545 /** 546 * Utility function to determine if a given element has been 547 * registered as a drag drop item. 548 * @method isDragDrop 549 * @param {String} id the element id to check 550 * @return {boolean} true if this element is a DragDrop item, 551 * false otherwise 552 * @static 553 */ 554 isDragDrop: function(id) { 555 return ( this.getDDById(id) ) ? true : false; 556 }, 557 558 /** 559 * Returns the drag and drop instances that are in all groups the 560 * passed in instance belongs to. 561 * @method getRelated 562 * @param {DragDrop} p_oDD the obj to get related data for 563 * @param {boolean} bTargetsOnly if true, only return targetable objs 564 * @return {DragDrop[]} the related instances 565 * @static 566 */ 567 getRelated: function(p_oDD, bTargetsOnly) { 568 var oDDs = []; 569 for (var i in p_oDD.groups) { 570 for (var j in this.ids[i]) { 571 var dd = this.ids[i][j]; 572 if (! this.isTypeOfDD(dd)) { 573 continue; 574 } 575 if (!bTargetsOnly || dd.isTarget) { 576 oDDs[oDDs.length] = dd; 577 } 578 } 579 } 580 581 return oDDs; 582 }, 583 584 /** 585 * Returns true if the specified dd target is a legal target for 586 * the specifice drag obj 587 * @method isLegalTarget 588 * @param {DragDrop} the drag obj 589 * @param {DragDrop} the target 590 * @return {boolean} true if the target is a legal target for the 591 * dd obj 592 * @static 593 */ 594 isLegalTarget: function (oDD, oTargetDD) { 595 var targets = this.getRelated(oDD, true); 596 for (var i=0, len=targets.length;i<len;++i) { 597 if (targets[i].id == oTargetDD.id) { 598 return true; 599 } 600 } 601 602 return false; 603 }, 604 605 /** 606 * My goal is to be able to transparently determine if an object is 607 * typeof DragDrop, and the exact subclass of DragDrop. typeof 608 * returns "object", oDD.constructor.toString() always returns 609 * "DragDrop" and not the name of the subclass. So for now it just 610 * evaluates a well-known variable in DragDrop. 611 * @method isTypeOfDD 612 * @param {Object} the object to evaluate 613 * @return {boolean} true if typeof oDD = DragDrop 614 * @static 615 */ 616 isTypeOfDD: function (oDD) { 617 return (oDD && oDD.__ygDragDrop); 618 }, 619 620 /** 621 * Utility function to determine if a given element has been 622 * registered as a drag drop handle for the given Drag Drop object. 623 * @method isHandle 624 * @param {String} id the element id to check 625 * @return {boolean} true if this element is a DragDrop handle, false 626 * otherwise 627 * @static 628 */ 629 isHandle: function(sDDId, sHandleId) { 630 return ( this.handleIds[sDDId] && 631 this.handleIds[sDDId][sHandleId] ); 632 }, 633 634 /** 635 * Returns the DragDrop instance for a given id 636 * @method getDDById 637 * @param {String} id the id of the DragDrop object 638 * @return {DragDrop} the drag drop object, null if it is not found 639 * @static 640 */ 641 getDDById: function(id) { 642 for (var i in this.ids) { 643 if (this.ids[i][id]) { 644 return this.ids[i][id]; 645 } 646 } 647 return null; 648 }, 649 650 /** 651 * Fired after a registered DragDrop object gets the mousedown event. 652 * Sets up the events required to track the object being dragged 653 * @method handleMouseDown 654 * @param {Event} e the event 655 * @param oDD the DragDrop object being dragged 656 * @private 657 * @static 658 */ 659 handleMouseDown: function(e, oDD) { 660 //this._activateShim(); 661 662 this.currentTarget = YAHOO.util.Event.getTarget(e); 663 664 this.dragCurrent = oDD; 665 666 var el = oDD.getEl(); 667 668 // track start position 669 this.startX = YAHOO.util.Event.getPageX(e); 670 this.startY = YAHOO.util.Event.getPageY(e); 671 672 this.deltaX = this.startX - el.offsetLeft; 673 this.deltaY = this.startY - el.offsetTop; 674 675 this.dragThreshMet = false; 676 677 this.clickTimeout = setTimeout( 678 function() { 679 var DDM = YAHOO.util.DDM; 680 DDM.startDrag(DDM.startX, DDM.startY); 681 DDM.fromTimeout = true; 682 }, 683 this.clickTimeThresh ); 684 }, 685 686 /** 687 * Fired when either the drag pixel threshold or the mousedown hold 688 * time threshold has been met. 689 * @method startDrag 690 * @param x {int} the X position of the original mousedown 691 * @param y {int} the Y position of the original mousedown 692 * @static 693 */ 694 startDrag: function(x, y) { 695 if (this.dragCurrent && this.dragCurrent.useShim) { 696 this._shimState = this.useShim; 697 this.useShim = true; 698 } 699 this._activateShim(); 700 YAHOO.log("firing drag start events", "info", "DragDropMgr"); 701 clearTimeout(this.clickTimeout); 702 var dc = this.dragCurrent; 703 if (dc && dc.events.b4StartDrag) { 704 dc.b4StartDrag(x, y); 705 dc.fireEvent('b4StartDragEvent', { x: x, y: y }); 706 } 707 if (dc && dc.events.startDrag) { 708 dc.startDrag(x, y); 709 dc.fireEvent('startDragEvent', { x: x, y: y }); 710 } 711 this.dragThreshMet = true; 712 }, 713 714 /** 715 * Internal function to handle the mouseup event. Will be invoked 716 * from the context of the document. 717 * @method handleMouseUp 718 * @param {Event} e the event 719 * @private 720 * @static 721 */ 722 handleMouseUp: function(e) { 723 if (this.dragCurrent) { 724 clearTimeout(this.clickTimeout); 725 726 if (this.dragThreshMet) { 727 YAHOO.log("mouseup detected - completing drag", "info", "DragDropMgr"); 728 if (this.fromTimeout) { 729 YAHOO.log('fromTimeout is true (mouse didn\'t move), call handleMouseMove so we can get the dragOver event', 'info', 'DragDropMgr'); 730 this.fromTimeout = false; 731 this.handleMouseMove(e); 732 } 733 this.fromTimeout = false; 734 this.fireEvents(e, true); 735 } else { 736 YAHOO.log("drag threshold not met", "info", "DragDropMgr"); 737 } 738 739 this.stopDrag(e); 740 741 this.stopEvent(e); 742 } 743 }, 744 745 /** 746 * Utility to stop event propagation and event default, if these 747 * features are turned on. 748 * @method stopEvent 749 * @param {Event} e the event as returned by this.getEvent() 750 * @static 751 */ 752 stopEvent: function(e) { 753 if (this.stopPropagation) { 754 YAHOO.util.Event.stopPropagation(e); 755 } 756 757 if (this.preventDefault) { 758 YAHOO.util.Event.preventDefault(e); 759 } 760 }, 761 762 /** 763 * Ends the current drag, cleans up the state, and fires the endDrag 764 * and mouseUp events. Called internally when a mouseup is detected 765 * during the drag. Can be fired manually during the drag by passing 766 * either another event (such as the mousemove event received in onDrag) 767 * or a fake event with pageX and pageY defined (so that endDrag and 768 * onMouseUp have usable position data.). Alternatively, pass true 769 * for the silent parameter so that the endDrag and onMouseUp events 770 * are skipped (so no event data is needed.) 771 * 772 * @method stopDrag 773 * @param {Event} e the mouseup event, another event (or a fake event) 774 * with pageX and pageY defined, or nothing if the 775 * silent parameter is true 776 * @param {boolean} silent skips the enddrag and mouseup events if true 777 * @static 778 */ 779 stopDrag: function(e, silent) { 780 // YAHOO.log("mouseup - removing event handlers"); 781 var dc = this.dragCurrent; 782 // Fire the drag end event for the item that was dragged 783 if (dc && !silent) { 784 if (this.dragThreshMet) { 785 YAHOO.log("firing endDrag events", "info", "DragDropMgr"); 786 if (dc.events.b4EndDrag) { 787 dc.b4EndDrag(e); 788 dc.fireEvent('b4EndDragEvent', { e: e }); 789 } 790 if (dc.events.endDrag) { 791 dc.endDrag(e); 792 dc.fireEvent('endDragEvent', { e: e }); 793 } 794 } 795 if (dc.events.mouseUp) { 796 YAHOO.log("firing dragdrop onMouseUp event", "info", "DragDropMgr"); 797 dc.onMouseUp(e); 798 dc.fireEvent('mouseUpEvent', { e: e }); 799 } 800 } 801 802 if (this._shimActive) { 803 this._deactivateShim(); 804 if (this.dragCurrent && this.dragCurrent.useShim) { 805 this.useShim = this._shimState; 806 this._shimState = false; 807 } 808 } 809 810 this.dragCurrent = null; 811 this.dragOvers = {}; 812 }, 813 814 /** 815 * Internal function to handle the mousemove event. Will be invoked 816 * from the context of the html element. 817 * 818 * @TODO figure out what we can do about mouse events lost when the 819 * user drags objects beyond the window boundary. Currently we can 820 * detect this in internet explorer by verifying that the mouse is 821 * down during the mousemove event. Firefox doesn't give us the 822 * button state on the mousemove event. 823 * @method handleMouseMove 824 * @param {Event} e the event 825 * @private 826 * @static 827 */ 828 handleMouseMove: function(e) { 829 //YAHOO.log("handlemousemove"); 830 831 var dc = this.dragCurrent; 832 if (dc) { 833 // YAHOO.log("no current drag obj"); 834 835 // var button = e.which || e.button; 836 // YAHOO.log("which: " + e.which + ", button: "+ e.button); 837 838 // check for IE < 9 mouseup outside of page boundary 839 if (YAHOO.env.ua.ie && (YAHOO.env.ua.ie < 9) && !e.button) { 840 YAHOO.log("button failure", "info", "DragDropMgr"); 841 this.stopEvent(e); 842 return this.handleMouseUp(e); 843 } else { 844 if (e.clientX < 0 || e.clientY < 0) { 845 //This will stop the element from leaving the viewport in FF, Opera & Safari 846 //Not turned on yet 847 //YAHOO.log("Either clientX or clientY is negative, stop the event.", "info", "DragDropMgr"); 848 //this.stopEvent(e); 849 //return false; 850 } 851 } 852 853 if (!this.dragThreshMet) { 854 var diffX = Math.abs(this.startX - YAHOO.util.Event.getPageX(e)); 855 var diffY = Math.abs(this.startY - YAHOO.util.Event.getPageY(e)); 856 // YAHOO.log("diffX: " + diffX + "diffY: " + diffY); 857 if (diffX > this.clickPixelThresh || 858 diffY > this.clickPixelThresh) { 859 YAHOO.log("pixel threshold met", "info", "DragDropMgr"); 860 this.startDrag(this.startX, this.startY); 861 } 862 } 863 864 if (this.dragThreshMet) { 865 if (dc && dc.events.b4Drag) { 866 dc.b4Drag(e); 867 dc.fireEvent('b4DragEvent', { e: e}); 868 } 869 if (dc && dc.events.drag) { 870 dc.onDrag(e); 871 dc.fireEvent('dragEvent', { e: e}); 872 } 873 if (dc) { 874 this.fireEvents(e, false); 875 } 876 } 877 878 this.stopEvent(e); 879 } 880 }, 881 882 /** 883 * Iterates over all of the DragDrop elements to find ones we are 884 * hovering over or dropping on 885 * @method fireEvents 886 * @param {Event} e the event 887 * @param {boolean} isDrop is this a drop op or a mouseover op? 888 * @private 889 * @static 890 */ 891 fireEvents: function(e, isDrop) { 892 var dc = this.dragCurrent; 893 894 // If the user did the mouse up outside of the window, we could 895 // get here even though we have ended the drag. 896 // If the config option dragOnly is true, bail out and don't fire the events 897 if (!dc || dc.isLocked() || dc.dragOnly) { 898 return; 899 } 900 901 var x = YAHOO.util.Event.getPageX(e), 902 y = YAHOO.util.Event.getPageY(e), 903 pt = new YAHOO.util.Point(x,y), 904 pos = dc.getTargetCoord(pt.x, pt.y), 905 el = dc.getDragEl(), 906 events = ['out', 'over', 'drop', 'enter'], 907 curRegion = new YAHOO.util.Region( pos.y, 908 pos.x + el.offsetWidth, 909 pos.y + el.offsetHeight, 910 pos.x ), 911 912 oldOvers = [], // cache the previous dragOver array 913 inGroupsObj = {}, 914 b4Results = {}, 915 inGroups = [], 916 data = { 917 outEvts: [], 918 overEvts: [], 919 dropEvts: [], 920 enterEvts: [] 921 }; 922 923 924 // Check to see if the object(s) we were hovering over is no longer 925 // being hovered over so we can fire the onDragOut event 926 for (var i in this.dragOvers) { 927 928 var ddo = this.dragOvers[i]; 929 930 if (! this.isTypeOfDD(ddo)) { 931 continue; 932 } 933 if (! this.isOverTarget(pt, ddo, this.mode, curRegion)) { 934 data.outEvts.push( ddo ); 935 } 936 937 oldOvers[i] = true; 938 delete this.dragOvers[i]; 939 } 940 941 for (var sGroup in dc.groups) { 942 // YAHOO.log("Processing group " + sGroup); 943 944 if ("string" != typeof sGroup) { 945 continue; 946 } 947 948 for (i in this.ids[sGroup]) { 949 var oDD = this.ids[sGroup][i]; 950 if (! this.isTypeOfDD(oDD)) { 951 continue; 952 } 953 954 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) { 955 if (this.isOverTarget(pt, oDD, this.mode, curRegion)) { 956 inGroupsObj[sGroup] = true; 957 // look for drop interactions 958 if (isDrop) { 959 data.dropEvts.push( oDD ); 960 // look for drag enter and drag over interactions 961 } else { 962 963 // initial drag over: dragEnter fires 964 if (!oldOvers[oDD.id]) { 965 data.enterEvts.push( oDD ); 966 // subsequent drag overs: dragOver fires 967 } else { 968 data.overEvts.push( oDD ); 969 } 970 971 this.dragOvers[oDD.id] = oDD; 972 } 973 } 974 } 975 } 976 } 977 978 this.interactionInfo = { 979 out: data.outEvts, 980 enter: data.enterEvts, 981 over: data.overEvts, 982 drop: data.dropEvts, 983 point: pt, 984 draggedRegion: curRegion, 985 sourceRegion: this.locationCache[dc.id], 986 validDrop: isDrop 987 }; 988 989 990 for (var inG in inGroupsObj) { 991 inGroups.push(inG); 992 } 993 994 // notify about a drop that did not find a target 995 if (isDrop && !data.dropEvts.length) { 996 YAHOO.log(dc.id + " dropped, but not on a target", "info", "DragDropMgr"); 997 this.interactionInfo.validDrop = false; 998 if (dc.events.invalidDrop) { 999 dc.onInvalidDrop(e); 1000 dc.fireEvent('invalidDropEvent', { e: e }); 1001 } 1002 } 1003 for (i = 0; i < events.length; i++) { 1004 var tmp = null; 1005 if (data[events[i] + 'Evts']) { 1006 tmp = data[events[i] + 'Evts']; 1007 } 1008 if (tmp && tmp.length) { 1009 var type = events[i].charAt(0).toUpperCase() + events[i].substr(1), 1010 ev = 'onDrag' + type, 1011 b4 = 'b4Drag' + type, 1012 cev = 'drag' + type + 'Event', 1013 check = 'drag' + type; 1014 if (this.mode) { 1015 YAHOO.log(dc.id + ' ' + ev + ': ' + tmp, "info", "DragDropMgr"); 1016 if (dc.events[b4]) { 1017 dc[b4](e, tmp, inGroups); 1018 b4Results[ev] = dc.fireEvent(b4 + 'Event', { event: e, info: tmp, group: inGroups }); 1019 1020 } 1021 if (dc.events[check] && (b4Results[ev] !== false)) { 1022 dc[ev](e, tmp, inGroups); 1023 dc.fireEvent(cev, { event: e, info: tmp, group: inGroups }); 1024 } 1025 } else { 1026 for (var b = 0, len = tmp.length; b < len; ++b) { 1027 YAHOO.log(dc.id + ' ' + ev + ': ' + tmp[b].id, "info", "DragDropMgr"); 1028 if (dc.events[b4]) { 1029 dc[b4](e, tmp[b].id, inGroups[0]); 1030 b4Results[ev] = dc.fireEvent(b4 + 'Event', { event: e, info: tmp[b].id, group: inGroups[0] }); 1031 } 1032 if (dc.events[check] && (b4Results[ev] !== false)) { 1033 dc[ev](e, tmp[b].id, inGroups[0]); 1034 dc.fireEvent(cev, { event: e, info: tmp[b].id, group: inGroups[0] }); 1035 } 1036 } 1037 } 1038 } 1039 } 1040 }, 1041 1042 /** 1043 * Helper function for getting the best match from the list of drag 1044 * and drop objects returned by the drag and drop events when we are 1045 * in INTERSECT mode. It returns either the first object that the 1046 * cursor is over, or the object that has the greatest overlap with 1047 * the dragged element. 1048 * @method getBestMatch 1049 * @param {DragDrop[]} dds The array of drag and drop objects 1050 * targeted 1051 * @return {DragDrop} The best single match 1052 * @static 1053 */ 1054 getBestMatch: function(dds) { 1055 var winner = null; 1056 1057 var len = dds.length; 1058 1059 if (len == 1) { 1060 winner = dds[0]; 1061 } else { 1062 // Loop through the targeted items 1063 for (var i=0; i<len; ++i) { 1064 var dd = dds[i]; 1065 // If the cursor is over the object, it wins. If the 1066 // cursor is over multiple matches, the first one we come 1067 // to wins. 1068 if (this.mode == this.INTERSECT && dd.cursorIsOver) { 1069 winner = dd; 1070 break; 1071 // Otherwise the object with the most overlap wins 1072 } else { 1073 if (!winner || !winner.overlap || (dd.overlap && 1074 winner.overlap.getArea() < dd.overlap.getArea())) { 1075 winner = dd; 1076 } 1077 } 1078 } 1079 } 1080 1081 return winner; 1082 }, 1083 1084 /** 1085 * Refreshes the cache of the top-left and bottom-right points of the 1086 * drag and drop objects in the specified group(s). This is in the 1087 * format that is stored in the drag and drop instance, so typical 1088 * usage is: 1089 * <code> 1090 * YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups); 1091 * </code> 1092 * Alternatively: 1093 * <code> 1094 * YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true}); 1095 * </code> 1096 * @TODO this really should be an indexed array. Alternatively this 1097 * method could accept both. 1098 * @method refreshCache 1099 * @param {Object} groups an associative array of groups to refresh 1100 * @static 1101 */ 1102 refreshCache: function(groups) { 1103 YAHOO.log("refreshing element location cache", "info", "DragDropMgr"); 1104 1105 // refresh everything if group array is not provided 1106 var g = groups || this.ids; 1107 1108 for (var sGroup in g) { 1109 if ("string" != typeof sGroup) { 1110 continue; 1111 } 1112 for (var i in this.ids[sGroup]) { 1113 var oDD = this.ids[sGroup][i]; 1114 1115 if (this.isTypeOfDD(oDD)) { 1116 var loc = this.getLocation(oDD); 1117 if (loc) { 1118 this.locationCache[oDD.id] = loc; 1119 } else { 1120 delete this.locationCache[oDD.id]; 1121 YAHOO.log("Could not get the loc for " + oDD.id, "warn", "DragDropMgr"); 1122 } 1123 } 1124 } 1125 } 1126 }, 1127 1128 /** 1129 * This checks to make sure an element exists and is in the DOM. The 1130 * main purpose is to handle cases where innerHTML is used to remove 1131 * drag and drop objects from the DOM. IE provides an 'unspecified 1132 * error' when trying to access the offsetParent of such an element 1133 * @method verifyEl 1134 * @param {HTMLElement} el the element to check 1135 * @return {boolean} true if the element looks usable 1136 * @static 1137 */ 1138 verifyEl: function(el) { 1139 try { 1140 if (el) { 1141 var parent = el.offsetParent; 1142 if (parent) { 1143 return true; 1144 } 1145 } 1146 } catch(e) { 1147 YAHOO.log("detected problem with an element", "info", "DragDropMgr"); 1148 } 1149 1150 return false; 1151 }, 1152 1153 /** 1154 * Returns a Region object containing the drag and drop element's position 1155 * and size, including the padding configured for it 1156 * @method getLocation 1157 * @param {DragDrop} oDD the drag and drop object to get the 1158 * location for 1159 * @return {YAHOO.util.Region} a Region object representing the total area 1160 * the element occupies, including any padding 1161 * the instance is configured for. 1162 * @static 1163 */ 1164 getLocation: function(oDD) { 1165 if (! this.isTypeOfDD(oDD)) { 1166 YAHOO.log(oDD + " is not a DD obj", "info", "DragDropMgr"); 1167 return null; 1168 } 1169 1170 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l; 1171 1172 try { 1173 pos= YAHOO.util.Dom.getXY(el); 1174 } catch (e) { } 1175 1176 if (!pos) { 1177 YAHOO.log("getXY failed", "info", "DragDropMgr"); 1178 return null; 1179 } 1180 1181 x1 = pos[0]; 1182 x2 = x1 + el.offsetWidth; 1183 y1 = pos[1]; 1184 y2 = y1 + el.offsetHeight; 1185 1186 t = y1 - oDD.padding[0]; 1187 r = x2 + oDD.padding[1]; 1188 b = y2 + oDD.padding[2]; 1189 l = x1 - oDD.padding[3]; 1190 1191 return new YAHOO.util.Region( t, r, b, l ); 1192 }, 1193 1194 /** 1195 * Checks the cursor location to see if it over the target 1196 * @method isOverTarget 1197 * @param {YAHOO.util.Point} pt The point to evaluate 1198 * @param {DragDrop} oTarget the DragDrop object we are inspecting 1199 * @param {boolean} intersect true if we are in intersect mode 1200 * @param {YAHOO.util.Region} pre-cached location of the dragged element 1201 * @return {boolean} true if the mouse is over the target 1202 * @private 1203 * @static 1204 */ 1205 isOverTarget: function(pt, oTarget, intersect, curRegion) { 1206 // use cache if available 1207 var loc = this.locationCache[oTarget.id]; 1208 if (!loc || !this.useCache) { 1209 YAHOO.log("cache not populated", "info", "DragDropMgr"); 1210 loc = this.getLocation(oTarget); 1211 this.locationCache[oTarget.id] = loc; 1212 1213 YAHOO.log("cache: " + loc, "info", "DragDropMgr"); 1214 } 1215 1216 if (!loc) { 1217 YAHOO.log("could not get the location of the element", "info", "DragDropMgr"); 1218 return false; 1219 } 1220 1221 //YAHOO.log("loc: " + loc + ", pt: " + pt); 1222 oTarget.cursorIsOver = loc.contains( pt ); 1223 1224 // DragDrop is using this as a sanity check for the initial mousedown 1225 // in this case we are done. In POINT mode, if the drag obj has no 1226 // contraints, we are done. Otherwise we need to evaluate the 1227 // region the target as occupies to determine if the dragged element 1228 // overlaps with it. 1229 1230 var dc = this.dragCurrent; 1231 if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) { 1232 1233 //if (oTarget.cursorIsOver) { 1234 //YAHOO.log("over " + oTarget + ", " + loc + ", " + pt, "warn"); 1235 //} 1236 return oTarget.cursorIsOver; 1237 } 1238 1239 oTarget.overlap = null; 1240 1241 1242 // Get the current location of the drag element, this is the 1243 // location of the mouse event less the delta that represents 1244 // where the original mousedown happened on the element. We 1245 // need to consider constraints and ticks as well. 1246 1247 if (!curRegion) { 1248 var pos = dc.getTargetCoord(pt.x, pt.y); 1249 var el = dc.getDragEl(); 1250 curRegion = new YAHOO.util.Region( pos.y, 1251 pos.x + el.offsetWidth, 1252 pos.y + el.offsetHeight, 1253 pos.x ); 1254 } 1255 1256 var overlap = curRegion.intersect(loc); 1257 1258 if (overlap) { 1259 oTarget.overlap = overlap; 1260 return (intersect) ? true : oTarget.cursorIsOver; 1261 } else { 1262 return false; 1263 } 1264 }, 1265 1266 /** 1267 * unload event handler 1268 * @method _onUnload 1269 * @private 1270 * @static 1271 */ 1272 _onUnload: function(e, me) { 1273 this.unregAll(); 1274 }, 1275 1276 /** 1277 * Cleans up the drag and drop events and objects. 1278 * @method unregAll 1279 * @private 1280 * @static 1281 */ 1282 unregAll: function() { 1283 YAHOO.log("unregister all", "info", "DragDropMgr"); 1284 1285 if (this.dragCurrent) { 1286 this.stopDrag(); 1287 this.dragCurrent = null; 1288 } 1289 1290 this._execOnAll("unreg", []); 1291 1292 //for (var i in this.elementCache) { 1293 //delete this.elementCache[i]; 1294 //} 1295 //this.elementCache = {}; 1296 1297 this.ids = {}; 1298 }, 1299 1300 /** 1301 * A cache of DOM elements 1302 * @property elementCache 1303 * @private 1304 * @static 1305 * @deprecated elements are not cached now 1306 */ 1307 elementCache: {}, 1308 1309 /** 1310 * Get the wrapper for the DOM element specified 1311 * @method getElWrapper 1312 * @param {String} id the id of the element to get 1313 * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element 1314 * @private 1315 * @deprecated This wrapper isn't that useful 1316 * @static 1317 */ 1318 getElWrapper: function(id) { 1319 var oWrapper = this.elementCache[id]; 1320 if (!oWrapper || !oWrapper.el) { 1321 oWrapper = this.elementCache[id] = 1322 new this.ElementWrapper(YAHOO.util.Dom.get(id)); 1323 } 1324 return oWrapper; 1325 }, 1326 1327 /** 1328 * Returns the actual DOM element 1329 * @method getElement 1330 * @param {String} id the id of the elment to get 1331 * @return {Object} The element 1332 * @deprecated use YAHOO.util.Dom.get instead 1333 * @static 1334 */ 1335 getElement: function(id) { 1336 return YAHOO.util.Dom.get(id); 1337 }, 1338 1339 /** 1340 * Returns the style property for the DOM element (i.e., 1341 * document.getElById(id).style) 1342 * @method getCss 1343 * @param {String} id the id of the elment to get 1344 * @return {Object} The style property of the element 1345 * @deprecated use YAHOO.util.Dom instead 1346 * @static 1347 */ 1348 getCss: function(id) { 1349 var el = YAHOO.util.Dom.get(id); 1350 return (el) ? el.style : null; 1351 }, 1352 1353 /** 1354 * Inner class for cached elements 1355 * @class DragDropMgr.ElementWrapper 1356 * @for DragDropMgr 1357 * @private 1358 * @deprecated 1359 */ 1360 ElementWrapper: function(el) { 1361 /** 1362 * The element 1363 * @property el 1364 */ 1365 this.el = el || null; 1366 /** 1367 * The element id 1368 * @property id 1369 */ 1370 this.id = this.el && el.id; 1371 /** 1372 * A reference to the style property 1373 * @property css 1374 */ 1375 this.css = this.el && el.style; 1376 }, 1377 1378 /** 1379 * Returns the X position of an html element 1380 * @method getPosX 1381 * @param el the element for which to get the position 1382 * @return {int} the X coordinate 1383 * @for DragDropMgr 1384 * @deprecated use YAHOO.util.Dom.getX instead 1385 * @static 1386 */ 1387 getPosX: function(el) { 1388 return YAHOO.util.Dom.getX(el); 1389 }, 1390 1391 /** 1392 * Returns the Y position of an html element 1393 * @method getPosY 1394 * @param el the element for which to get the position 1395 * @return {int} the Y coordinate 1396 * @deprecated use YAHOO.util.Dom.getY instead 1397 * @static 1398 */ 1399 getPosY: function(el) { 1400 return YAHOO.util.Dom.getY(el); 1401 }, 1402 1403 /** 1404 * Swap two nodes. In IE, we use the native method, for others we 1405 * emulate the IE behavior 1406 * @method swapNode 1407 * @param n1 the first node to swap 1408 * @param n2 the other node to swap 1409 * @static 1410 */ 1411 swapNode: function(n1, n2) { 1412 if (n1.swapNode) { 1413 n1.swapNode(n2); 1414 } else { 1415 var p = n2.parentNode; 1416 var s = n2.nextSibling; 1417 1418 if (s == n1) { 1419 p.insertBefore(n1, n2); 1420 } else if (n2 == n1.nextSibling) { 1421 p.insertBefore(n2, n1); 1422 } else { 1423 n1.parentNode.replaceChild(n2, n1); 1424 p.insertBefore(n1, s); 1425 } 1426 } 1427 }, 1428 1429 /** 1430 * Returns the current scroll position 1431 * @method getScroll 1432 * @private 1433 * @static 1434 */ 1435 getScroll: function () { 1436 var t, l, dde=document.documentElement, db=document.body; 1437 if (dde && (dde.scrollTop || dde.scrollLeft)) { 1438 t = dde.scrollTop; 1439 l = dde.scrollLeft; 1440 } else if (db) { 1441 t = db.scrollTop; 1442 l = db.scrollLeft; 1443 } else { 1444 YAHOO.log("could not get scroll property", "info", "DragDropMgr"); 1445 } 1446 return { top: t, left: l }; 1447 }, 1448 1449 /** 1450 * Returns the specified element style property 1451 * @method getStyle 1452 * @param {HTMLElement} el the element 1453 * @param {string} styleProp the style property 1454 * @return {string} The value of the style property 1455 * @deprecated use YAHOO.util.Dom.getStyle 1456 * @static 1457 */ 1458 getStyle: function(el, styleProp) { 1459 return YAHOO.util.Dom.getStyle(el, styleProp); 1460 }, 1461 1462 /** 1463 * Gets the scrollTop 1464 * @method getScrollTop 1465 * @return {int} the document's scrollTop 1466 * @static 1467 */ 1468 getScrollTop: function () { return this.getScroll().top; }, 1469 1470 /** 1471 * Gets the scrollLeft 1472 * @method getScrollLeft 1473 * @return {int} the document's scrollTop 1474 * @static 1475 */ 1476 getScrollLeft: function () { return this.getScroll().left; }, 1477 1478 /** 1479 * Sets the x/y position of an element to the location of the 1480 * target element. 1481 * @method moveToEl 1482 * @param {HTMLElement} moveEl The element to move 1483 * @param {HTMLElement} targetEl The position reference element 1484 * @static 1485 */ 1486 moveToEl: function (moveEl, targetEl) { 1487 var aCoord = YAHOO.util.Dom.getXY(targetEl); 1488 YAHOO.log("moveToEl: " + aCoord, "info", "DragDropMgr"); 1489 YAHOO.util.Dom.setXY(moveEl, aCoord); 1490 }, 1491 1492 /** 1493 * Gets the client height 1494 * @method getClientHeight 1495 * @return {int} client height in px 1496 * @deprecated use YAHOO.util.Dom.getViewportHeight instead 1497 * @static 1498 */ 1499 getClientHeight: function() { 1500 return YAHOO.util.Dom.getViewportHeight(); 1501 }, 1502 1503 /** 1504 * Gets the client width 1505 * @method getClientWidth 1506 * @return {int} client width in px 1507 * @deprecated use YAHOO.util.Dom.getViewportWidth instead 1508 * @static 1509 */ 1510 getClientWidth: function() { 1511 return YAHOO.util.Dom.getViewportWidth(); 1512 }, 1513 1514 /** 1515 * Numeric array sort function 1516 * @method numericSort 1517 * @static 1518 */ 1519 numericSort: function(a, b) { return (a - b); }, 1520 1521 /** 1522 * Internal counter 1523 * @property _timeoutCount 1524 * @private 1525 * @static 1526 */ 1527 _timeoutCount: 0, 1528 1529 /** 1530 * Trying to make the load order less important. Without this we get 1531 * an error if this file is loaded before the Event Utility. 1532 * @method _addListeners 1533 * @private 1534 * @static 1535 */ 1536 _addListeners: function() { 1537 var DDM = YAHOO.util.DDM; 1538 if ( YAHOO.util.Event && document ) { 1539 DDM._onLoad(); 1540 } else { 1541 if (DDM._timeoutCount > 2000) { 1542 YAHOO.log("DragDrop requires the Event Utility", "error", "DragDropMgr"); 1543 } else { 1544 setTimeout(DDM._addListeners, 10); 1545 if (document && document.body) { 1546 DDM._timeoutCount += 1; 1547 } 1548 } 1549 } 1550 }, 1551 1552 /** 1553 * Recursively searches the immediate parent and all child nodes for 1554 * the handle element in order to determine wheter or not it was 1555 * clicked. 1556 * @method handleWasClicked 1557 * @param node the html element to inspect 1558 * @static 1559 */ 1560 handleWasClicked: function(node, id) { 1561 if (this.isHandle(id, node.id)) { 1562 YAHOO.log("clicked node is a handle", "info", "DragDropMgr"); 1563 return true; 1564 } else { 1565 // check to see if this is a text node child of the one we want 1566 var p = node.parentNode; 1567 // YAHOO.log("p: " + p); 1568 1569 while (p) { 1570 if (this.isHandle(id, p.id)) { 1571 return true; 1572 } else { 1573 YAHOO.log(p.id + " is not a handle", "info", "DragDropMgr"); 1574 p = p.parentNode; 1575 } 1576 } 1577 } 1578 1579 return false; 1580 } 1581 1582 }; 1583 1584 }(); 1585 1586 // shorter alias, save a few bytes 1587 YAHOO.util.DDM = YAHOO.util.DragDropMgr; 1588 YAHOO.util.DDM._addListeners(); 1589 1590 } 1591 1592 (function() { 1593 1594 var Event=YAHOO.util.Event; 1595 var Dom=YAHOO.util.Dom; 1596 1597 /** 1598 * Defines the interface and base operation of items that that can be 1599 * dragged or can be drop targets. It was designed to be extended, overriding 1600 * the event handlers for startDrag, onDrag, onDragOver, onDragOut. 1601 * Up to three html elements can be associated with a DragDrop instance: 1602 * <ul> 1603 * <li>linked element: the element that is passed into the constructor. 1604 * This is the element which defines the boundaries for interaction with 1605 * other DragDrop objects.</li> 1606 * <li>handle element(s): The drag operation only occurs if the element that 1607 * was clicked matches a handle element. By default this is the linked 1608 * element, but there are times that you will want only a portion of the 1609 * linked element to initiate the drag operation, and the setHandleElId() 1610 * method provides a way to define this.</li> 1611 * <li>drag element: this represents an the element that would be moved along 1612 * with the cursor during a drag operation. By default, this is the linked 1613 * element itself as in {@link YAHOO.util.DD}. setDragElId() lets you define 1614 * a separate element that would be moved, as in {@link YAHOO.util.DDProxy} 1615 * </li> 1616 * </ul> 1617 * This class should not be instantiated until the onload event to ensure that 1618 * the associated elements are available. 1619 * The following would define a DragDrop obj that would interact with any 1620 * other DragDrop obj in the "group1" group: 1621 * <pre> 1622 * dd = new YAHOO.util.DragDrop("div1", "group1"); 1623 * </pre> 1624 * Since none of the event handlers have been implemented, nothing would 1625 * actually happen if you were to run the code above. Normally you would 1626 * override this class or one of the default implementations, but you can 1627 * also override the methods you want on an instance of the class... 1628 * <pre> 1629 * dd.onDragDrop = function(e, id) { 1630 * alert("dd was dropped on " + id); 1631 * } 1632 * </pre> 1633 * @namespace YAHOO.util 1634 * @class DragDrop 1635 * @constructor 1636 * @param {String} id of the element that is linked to this instance 1637 * @param {String} sGroup the group of related DragDrop objects 1638 * @param {object} config an object containing configurable attributes 1639 * Valid properties for DragDrop: 1640 * padding, isTarget, maintainOffset, primaryButtonOnly, 1641 */ 1642 YAHOO.util.DragDrop = function(id, sGroup, config) { 1643 if (id) { 1644 this.init(id, sGroup, config); 1645 } 1646 }; 1647 1648 YAHOO.util.DragDrop.prototype = { 1649 /** 1650 * An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop 1651 * By setting any of these to false, then event will not be fired. 1652 * @property events 1653 * @type object 1654 */ 1655 events: null, 1656 /** 1657 * @method on 1658 * @description Shortcut for EventProvider.subscribe, see <a href="YAHOO.util.EventProvider.html#subscribe">YAHOO.util.EventProvider.subscribe</a> 1659 */ 1660 on: function() { 1661 this.subscribe.apply(this, arguments); 1662 }, 1663 /** 1664 * The id of the element associated with this object. This is what we 1665 * refer to as the "linked element" because the size and position of 1666 * this element is used to determine when the drag and drop objects have 1667 * interacted. 1668 * @property id 1669 * @type String 1670 */ 1671 id: null, 1672 1673 /** 1674 * Configuration attributes passed into the constructor 1675 * @property config 1676 * @type object 1677 */ 1678 config: null, 1679 1680 /** 1681 * The id of the element that will be dragged. By default this is same 1682 * as the linked element , but could be changed to another element. Ex: 1683 * YAHOO.util.DDProxy 1684 * @property dragElId 1685 * @type String 1686 * @private 1687 */ 1688 dragElId: null, 1689 1690 /** 1691 * the id of the element that initiates the drag operation. By default 1692 * this is the linked element, but could be changed to be a child of this 1693 * element. This lets us do things like only starting the drag when the 1694 * header element within the linked html element is clicked. 1695 * @property handleElId 1696 * @type String 1697 * @private 1698 */ 1699 handleElId: null, 1700 1701 /** 1702 * An associative array of HTML tags that will be ignored if clicked. 1703 * @property invalidHandleTypes 1704 * @type {string: string} 1705 */ 1706 invalidHandleTypes: null, 1707 1708 /** 1709 * An associative array of ids for elements that will be ignored if clicked 1710 * @property invalidHandleIds 1711 * @type {string: string} 1712 */ 1713 invalidHandleIds: null, 1714 1715 /** 1716 * An indexted array of css class names for elements that will be ignored 1717 * if clicked. 1718 * @property invalidHandleClasses 1719 * @type string[] 1720 */ 1721 invalidHandleClasses: null, 1722 1723 /** 1724 * The linked element's absolute X position at the time the drag was 1725 * started 1726 * @property startPageX 1727 * @type int 1728 * @private 1729 */ 1730 startPageX: 0, 1731 1732 /** 1733 * The linked element's absolute X position at the time the drag was 1734 * started 1735 * @property startPageY 1736 * @type int 1737 * @private 1738 */ 1739 startPageY: 0, 1740 1741 /** 1742 * The group defines a logical collection of DragDrop objects that are 1743 * related. Instances only get events when interacting with other 1744 * DragDrop object in the same group. This lets us define multiple 1745 * groups using a single DragDrop subclass if we want. 1746 * @property groups 1747 * @type {string: string} 1748 */ 1749 groups: null, 1750 1751 /** 1752 * Individual drag/drop instances can be locked. This will prevent 1753 * onmousedown start drag. 1754 * @property locked 1755 * @type boolean 1756 * @private 1757 */ 1758 locked: false, 1759 1760 /** 1761 * Lock this instance 1762 * @method lock 1763 */ 1764 lock: function() { this.locked = true; }, 1765 1766 /** 1767 * Unlock this instace 1768 * @method unlock 1769 */ 1770 unlock: function() { this.locked = false; }, 1771 1772 /** 1773 * By default, all instances can be a drop target. This can be disabled by 1774 * setting isTarget to false. 1775 * @property isTarget 1776 * @type boolean 1777 */ 1778 isTarget: true, 1779 1780 /** 1781 * The padding configured for this drag and drop object for calculating 1782 * the drop zone intersection with this object. 1783 * @property padding 1784 * @type int[] 1785 */ 1786 padding: null, 1787 /** 1788 * If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping) 1789 * @property dragOnly 1790 * @type Boolean 1791 */ 1792 dragOnly: false, 1793 1794 /** 1795 * If this flag is true, a shim will be placed over the screen/viewable area to track mouse events. Should help with dragging elements over iframes and other controls. 1796 * @property useShim 1797 * @type Boolean 1798 */ 1799 useShim: false, 1800 1801 /** 1802 * Cached reference to the linked element 1803 * @property _domRef 1804 * @private 1805 */ 1806 _domRef: null, 1807 1808 /** 1809 * Internal typeof flag 1810 * @property __ygDragDrop 1811 * @private 1812 */ 1813 __ygDragDrop: true, 1814 1815 /** 1816 * Set to true when horizontal contraints are applied 1817 * @property constrainX 1818 * @type boolean 1819 * @private 1820 */ 1821 constrainX: false, 1822 1823 /** 1824 * Set to true when vertical contraints are applied 1825 * @property constrainY 1826 * @type boolean 1827 * @private 1828 */ 1829 constrainY: false, 1830 1831 /** 1832 * The left constraint 1833 * @property minX 1834 * @type int 1835 * @private 1836 */ 1837 minX: 0, 1838 1839 /** 1840 * The right constraint 1841 * @property maxX 1842 * @type int 1843 * @private 1844 */ 1845 maxX: 0, 1846 1847 /** 1848 * The up constraint 1849 * @property minY 1850 * @type int 1851 * @type int 1852 * @private 1853 */ 1854 minY: 0, 1855 1856 /** 1857 * The down constraint 1858 * @property maxY 1859 * @type int 1860 * @private 1861 */ 1862 maxY: 0, 1863 1864 /** 1865 * The difference between the click position and the source element's location 1866 * @property deltaX 1867 * @type int 1868 * @private 1869 */ 1870 deltaX: 0, 1871 1872 /** 1873 * The difference between the click position and the source element's location 1874 * @property deltaY 1875 * @type int 1876 * @private 1877 */ 1878 deltaY: 0, 1879 1880 /** 1881 * Maintain offsets when we resetconstraints. Set to true when you want 1882 * the position of the element relative to its parent to stay the same 1883 * when the page changes 1884 * 1885 * @property maintainOffset 1886 * @type boolean 1887 */ 1888 maintainOffset: false, 1889 1890 /** 1891 * Array of pixel locations the element will snap to if we specified a 1892 * horizontal graduation/interval. This array is generated automatically 1893 * when you define a tick interval. 1894 * @property xTicks 1895 * @type int[] 1896 */ 1897 xTicks: null, 1898 1899 /** 1900 * Array of pixel locations the element will snap to if we specified a 1901 * vertical graduation/interval. This array is generated automatically 1902 * when you define a tick interval. 1903 * @property yTicks 1904 * @type int[] 1905 */ 1906 yTicks: null, 1907 1908 /** 1909 * By default the drag and drop instance will only respond to the primary 1910 * button click (left button for a right-handed mouse). Set to true to 1911 * allow drag and drop to start with any mouse click that is propogated 1912 * by the browser 1913 * @property primaryButtonOnly 1914 * @type boolean 1915 */ 1916 primaryButtonOnly: true, 1917 1918 /** 1919 * The availabe property is false until the linked dom element is accessible. 1920 * @property available 1921 * @type boolean 1922 */ 1923 available: false, 1924 1925 /** 1926 * By default, drags can only be initiated if the mousedown occurs in the 1927 * region the linked element is. This is done in part to work around a 1928 * bug in some browsers that mis-report the mousedown if the previous 1929 * mouseup happened outside of the window. This property is set to true 1930 * if outer handles are defined. 1931 * 1932 * @property hasOuterHandles 1933 * @type boolean 1934 * @default false 1935 */ 1936 hasOuterHandles: false, 1937 1938 /** 1939 * Property that is assigned to a drag and drop object when testing to 1940 * see if it is being targeted by another dd object. This property 1941 * can be used in intersect mode to help determine the focus of 1942 * the mouse interaction. DDM.getBestMatch uses this property first to 1943 * determine the closest match in INTERSECT mode when multiple targets 1944 * are part of the same interaction. 1945 * @property cursorIsOver 1946 * @type boolean 1947 */ 1948 cursorIsOver: false, 1949 1950 /** 1951 * Property that is assigned to a drag and drop object when testing to 1952 * see if it is being targeted by another dd object. This is a region 1953 * that represents the area the draggable element overlaps this target. 1954 * DDM.getBestMatch uses this property to compare the size of the overlap 1955 * to that of other targets in order to determine the closest match in 1956 * INTERSECT mode when multiple targets are part of the same interaction. 1957 * @property overlap 1958 * @type YAHOO.util.Region 1959 */ 1960 overlap: null, 1961 1962 /** 1963 * Code that executes immediately before the startDrag event 1964 * @method b4StartDrag 1965 * @private 1966 */ 1967 b4StartDrag: function(x, y) { }, 1968 1969 /** 1970 * Abstract method called after a drag/drop object is clicked 1971 * and the drag or mousedown time thresholds have beeen met. 1972 * @method startDrag 1973 * @param {int} X click location 1974 * @param {int} Y click location 1975 */ 1976 startDrag: function(x, y) { /* override this */ }, 1977 1978 /** 1979 * Code that executes immediately before the onDrag event 1980 * @method b4Drag 1981 * @private 1982 */ 1983 b4Drag: function(e) { }, 1984 1985 /** 1986 * Abstract method called during the onMouseMove event while dragging an 1987 * object. 1988 * @method onDrag 1989 * @param {Event} e the mousemove event 1990 */ 1991 onDrag: function(e) { /* override this */ }, 1992 1993 /** 1994 * Abstract method called when this element fist begins hovering over 1995 * another DragDrop obj 1996 * @method onDragEnter 1997 * @param {Event} e the mousemove event 1998 * @param {String|DragDrop[]} id In POINT mode, the element 1999 * id this is hovering over. In INTERSECT mode, an array of one or more 2000 * dragdrop items being hovered over. 2001 */ 2002 onDragEnter: function(e, id) { /* override this */ }, 2003 2004 /** 2005 * Code that executes immediately before the onDragOver event 2006 * @method b4DragOver 2007 * @private 2008 */ 2009 b4DragOver: function(e) { }, 2010 2011 /** 2012 * Abstract method called when this element is hovering over another 2013 * DragDrop obj 2014 * @method onDragOver 2015 * @param {Event} e the mousemove event 2016 * @param {String|DragDrop[]} id In POINT mode, the element 2017 * id this is hovering over. In INTERSECT mode, an array of dd items 2018 * being hovered over. 2019 */ 2020 onDragOver: function(e, id) { /* override this */ }, 2021 2022 /** 2023 * Code that executes immediately before the onDragOut event 2024 * @method b4DragOut 2025 * @private 2026 */ 2027 b4DragOut: function(e) { }, 2028 2029 /** 2030 * Abstract method called when we are no longer hovering over an element 2031 * @method onDragOut 2032 * @param {Event} e the mousemove event 2033 * @param {String|DragDrop[]} id In POINT mode, the element 2034 * id this was hovering over. In INTERSECT mode, an array of dd items 2035 * that the mouse is no longer over. 2036 */ 2037 onDragOut: function(e, id) { /* override this */ }, 2038 2039 /** 2040 * Code that executes immediately before the onDragDrop event 2041 * @method b4DragDrop 2042 * @private 2043 */ 2044 b4DragDrop: function(e) { }, 2045 2046 /** 2047 * Abstract method called when this item is dropped on another DragDrop 2048 * obj 2049 * @method onDragDrop 2050 * @param {Event} e the mouseup event 2051 * @param {String|DragDrop[]} id In POINT mode, the element 2052 * id this was dropped on. In INTERSECT mode, an array of dd items this 2053 * was dropped on. 2054 */ 2055 onDragDrop: function(e, id) { /* override this */ }, 2056 2057 /** 2058 * Abstract method called when this item is dropped on an area with no 2059 * drop target 2060 * @method onInvalidDrop 2061 * @param {Event} e the mouseup event 2062 */ 2063 onInvalidDrop: function(e) { /* override this */ }, 2064 2065 /** 2066 * Code that executes immediately before the endDrag event 2067 * @method b4EndDrag 2068 * @private 2069 */ 2070 b4EndDrag: function(e) { }, 2071 2072 /** 2073 * Fired when we are done dragging the object 2074 * @method endDrag 2075 * @param {Event} e the mouseup event 2076 */ 2077 endDrag: function(e) { /* override this */ }, 2078 2079 /** 2080 * Code executed immediately before the onMouseDown event 2081 * @method b4MouseDown 2082 * @param {Event} e the mousedown event 2083 * @private 2084 */ 2085 b4MouseDown: function(e) { }, 2086 2087 /** 2088 * Event handler that fires when a drag/drop obj gets a mousedown 2089 * @method onMouseDown 2090 * @param {Event} e the mousedown event 2091 */ 2092 onMouseDown: function(e) { /* override this */ }, 2093 2094 /** 2095 * Event handler that fires when a drag/drop obj gets a mouseup 2096 * @method onMouseUp 2097 * @param {Event} e the mouseup event 2098 */ 2099 onMouseUp: function(e) { /* override this */ }, 2100 2101 /** 2102 * Override the onAvailable method to do what is needed after the initial 2103 * position was determined. 2104 * @method onAvailable 2105 */ 2106 onAvailable: function () { 2107 //this.logger.log("onAvailable (base)"); 2108 }, 2109 2110 /** 2111 * Returns a reference to the linked element 2112 * @method getEl 2113 * @return {HTMLElement} the html element 2114 */ 2115 getEl: function() { 2116 if (!this._domRef) { 2117 this._domRef = Dom.get(this.id); 2118 } 2119 2120 return this._domRef; 2121 }, 2122 2123 /** 2124 * Returns a reference to the actual element to drag. By default this is 2125 * the same as the html element, but it can be assigned to another 2126 * element. An example of this can be found in YAHOO.util.DDProxy 2127 * @method getDragEl 2128 * @return {HTMLElement} the html element 2129 */ 2130 getDragEl: function() { 2131 return Dom.get(this.dragElId); 2132 }, 2133 2134 /** 2135 * Sets up the DragDrop object. Must be called in the constructor of any 2136 * YAHOO.util.DragDrop subclass 2137 * @method init 2138 * @param id the id of the linked element 2139 * @param {String} sGroup the group of related items 2140 * @param {object} config configuration attributes 2141 */ 2142 init: function(id, sGroup, config) { 2143 this.initTarget(id, sGroup, config); 2144 Event.on(this._domRef || this.id, "mousedown", 2145 this.handleMouseDown, this, true); 2146 2147 // Event.on(this.id, "selectstart", Event.preventDefault); 2148 for (var i in this.events) { 2149 this.createEvent(i + 'Event'); 2150 } 2151 2152 }, 2153 2154 /** 2155 * Initializes Targeting functionality only... the object does not 2156 * get a mousedown handler. 2157 * @method initTarget 2158 * @param id the id of the linked element 2159 * @param {String} sGroup the group of related items 2160 * @param {object} config configuration attributes 2161 */ 2162 initTarget: function(id, sGroup, config) { 2163 2164 // configuration attributes 2165 this.config = config || {}; 2166 2167 this.events = {}; 2168 2169 // create a local reference to the drag and drop manager 2170 this.DDM = YAHOO.util.DDM; 2171 2172 // initialize the groups object 2173 this.groups = {}; 2174 2175 // assume that we have an element reference instead of an id if the 2176 // parameter is not a string 2177 if (typeof id !== "string") { 2178 YAHOO.log("id is not a string, assuming it is an HTMLElement"); 2179 this._domRef = id; 2180 id = Dom.generateId(id); 2181 } 2182 2183 // set the id 2184 this.id = id; 2185 2186 // add to an interaction group 2187 this.addToGroup((sGroup) ? sGroup : "default"); 2188 2189 // We don't want to register this as the handle with the manager 2190 // so we just set the id rather than calling the setter. 2191 this.handleElId = id; 2192 2193 Event.onAvailable(id, this.handleOnAvailable, this, true); 2194 2195 // create a logger instance 2196 this.logger = (YAHOO.widget.LogWriter) ? 2197 new YAHOO.widget.LogWriter(this.toString()) : YAHOO; 2198 2199 // the linked element is the element that gets dragged by default 2200 this.setDragElId(id); 2201 2202 // by default, clicked anchors will not start drag operations. 2203 // @TODO what else should be here? Probably form fields. 2204 this.invalidHandleTypes = { A: "A" }; 2205 this.invalidHandleIds = {}; 2206 this.invalidHandleClasses = []; 2207 2208 this.applyConfig(); 2209 }, 2210 2211 /** 2212 * Applies the configuration parameters that were passed into the constructor. 2213 * This is supposed to happen at each level through the inheritance chain. So 2214 * a DDProxy implentation will execute apply config on DDProxy, DD, and 2215 * DragDrop in order to get all of the parameters that are available in 2216 * each object. 2217 * @method applyConfig 2218 */ 2219 applyConfig: function() { 2220 this.events = { 2221 mouseDown: true, 2222 b4MouseDown: true, 2223 mouseUp: true, 2224 b4StartDrag: true, 2225 startDrag: true, 2226 b4EndDrag: true, 2227 endDrag: true, 2228 drag: true, 2229 b4Drag: true, 2230 invalidDrop: true, 2231 b4DragOut: true, 2232 dragOut: true, 2233 dragEnter: true, 2234 b4DragOver: true, 2235 dragOver: true, 2236 b4DragDrop: true, 2237 dragDrop: true 2238 }; 2239 2240 if (this.config.events) { 2241 for (var i in this.config.events) { 2242 if (this.config.events[i] === false) { 2243 this.events[i] = false; 2244 } 2245 } 2246 } 2247 2248 2249 // configurable properties: 2250 // padding, isTarget, maintainOffset, primaryButtonOnly 2251 this.padding = this.config.padding || [0, 0, 0, 0]; 2252 this.isTarget = (this.config.isTarget !== false); 2253 this.maintainOffset = (this.config.maintainOffset); 2254 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false); 2255 this.dragOnly = ((this.config.dragOnly === true) ? true : false); 2256 this.useShim = ((this.config.useShim === true) ? true : false); 2257 }, 2258 2259 /** 2260 * Executed when the linked element is available 2261 * @method handleOnAvailable 2262 * @private 2263 */ 2264 handleOnAvailable: function() { 2265 //this.logger.log("handleOnAvailable"); 2266 this.available = true; 2267 this.resetConstraints(); 2268 this.onAvailable(); 2269 }, 2270 2271 /** 2272 * Configures the padding for the target zone in px. Effectively expands 2273 * (or reduces) the virtual object size for targeting calculations. 2274 * Supports css-style shorthand; if only one parameter is passed, all sides 2275 * will have that padding, and if only two are passed, the top and bottom 2276 * will have the first param, the left and right the second. 2277 * @method setPadding 2278 * @param {int} iTop Top pad 2279 * @param {int} iRight Right pad 2280 * @param {int} iBot Bot pad 2281 * @param {int} iLeft Left pad 2282 */ 2283 setPadding: function(iTop, iRight, iBot, iLeft) { 2284 // this.padding = [iLeft, iRight, iTop, iBot]; 2285 if (!iRight && 0 !== iRight) { 2286 this.padding = [iTop, iTop, iTop, iTop]; 2287 } else if (!iBot && 0 !== iBot) { 2288 this.padding = [iTop, iRight, iTop, iRight]; 2289 } else { 2290 this.padding = [iTop, iRight, iBot, iLeft]; 2291 } 2292 }, 2293 2294 /** 2295 * Stores the initial placement of the linked element. 2296 * @method setInitialPosition 2297 * @param {int} diffX the X offset, default 0 2298 * @param {int} diffY the Y offset, default 0 2299 * @private 2300 */ 2301 setInitPosition: function(diffX, diffY) { 2302 var el = this.getEl(); 2303 2304 if (!this.DDM.verifyEl(el)) { 2305 if (el && el.style && (el.style.display == 'none')) { 2306 this.logger.log(this.id + " can not get initial position, element style is display: none"); 2307 } else { 2308 this.logger.log(this.id + " element is broken"); 2309 } 2310 return; 2311 } 2312 2313 var dx = diffX || 0; 2314 var dy = diffY || 0; 2315 2316 var p = Dom.getXY( el ); 2317 2318 this.initPageX = p[0] - dx; 2319 this.initPageY = p[1] - dy; 2320 2321 this.lastPageX = p[0]; 2322 this.lastPageY = p[1]; 2323 2324 this.logger.log(this.id + " initial position: " + this.initPageX + 2325 ", " + this.initPageY); 2326 2327 2328 this.setStartPosition(p); 2329 }, 2330 2331 /** 2332 * Sets the start position of the element. This is set when the obj 2333 * is initialized, the reset when a drag is started. 2334 * @method setStartPosition 2335 * @param pos current position (from previous lookup) 2336 * @private 2337 */ 2338 setStartPosition: function(pos) { 2339 var p = pos || Dom.getXY(this.getEl()); 2340 2341 this.deltaSetXY = null; 2342 2343 this.startPageX = p[0]; 2344 this.startPageY = p[1]; 2345 }, 2346 2347 /** 2348 * Add this instance to a group of related drag/drop objects. All 2349 * instances belong to at least one group, and can belong to as many 2350 * groups as needed. 2351 * @method addToGroup 2352 * @param sGroup {string} the name of the group 2353 */ 2354 addToGroup: function(sGroup) { 2355 this.groups[sGroup] = true; 2356 this.DDM.regDragDrop(this, sGroup); 2357 }, 2358 2359 /** 2360 * Remove's this instance from the supplied interaction group 2361 * @method removeFromGroup 2362 * @param {string} sGroup The group to drop 2363 */ 2364 removeFromGroup: function(sGroup) { 2365 this.logger.log("Removing from group: " + sGroup); 2366 if (this.groups[sGroup]) { 2367 delete this.groups[sGroup]; 2368 } 2369 2370 this.DDM.removeDDFromGroup(this, sGroup); 2371 }, 2372 2373 /** 2374 * Allows you to specify that an element other than the linked element 2375 * will be moved with the cursor during a drag 2376 * @method setDragElId 2377 * @param id {string} the id of the element that will be used to initiate the drag 2378 */ 2379 setDragElId: function(id) { 2380 this.dragElId = id; 2381 }, 2382 2383 /** 2384 * Allows you to specify a child of the linked element that should be 2385 * used to initiate the drag operation. An example of this would be if 2386 * you have a content div with text and links. Clicking anywhere in the 2387 * content area would normally start the drag operation. Use this method 2388 * to specify that an element inside of the content div is the element 2389 * that starts the drag operation. 2390 * @method setHandleElId 2391 * @param id {string} the id of the element that will be used to 2392 * initiate the drag. 2393 */ 2394 setHandleElId: function(id) { 2395 if (typeof id !== "string") { 2396 YAHOO.log("id is not a string, assuming it is an HTMLElement"); 2397 id = Dom.generateId(id); 2398 } 2399 this.handleElId = id; 2400 this.DDM.regHandle(this.id, id); 2401 }, 2402 2403 /** 2404 * Allows you to set an element outside of the linked element as a drag 2405 * handle 2406 * @method setOuterHandleElId 2407 * @param id the id of the element that will be used to initiate the drag 2408 */ 2409 setOuterHandleElId: function(id) { 2410 if (typeof id !== "string") { 2411 YAHOO.log("id is not a string, assuming it is an HTMLElement"); 2412 id = Dom.generateId(id); 2413 } 2414 this.logger.log("Adding outer handle event: " + id); 2415 Event.on(id, "mousedown", 2416 this.handleMouseDown, this, true); 2417 this.setHandleElId(id); 2418 2419 this.hasOuterHandles = true; 2420 }, 2421 2422 /** 2423 * Remove all drag and drop hooks for this element 2424 * @method unreg 2425 */ 2426 unreg: function() { 2427 this.logger.log("DragDrop obj cleanup " + this.id); 2428 Event.removeListener(this.id, "mousedown", 2429 this.handleMouseDown); 2430 this._domRef = null; 2431 this.DDM._remove(this); 2432 }, 2433 2434 /** 2435 * Returns true if this instance is locked, or the drag drop mgr is locked 2436 * (meaning that all drag/drop is disabled on the page.) 2437 * @method isLocked 2438 * @return {boolean} true if this obj or all drag/drop is locked, else 2439 * false 2440 */ 2441 isLocked: function() { 2442 return (this.DDM.isLocked() || this.locked); 2443 }, 2444 2445 /** 2446 * Fired when this object is clicked 2447 * @method handleMouseDown 2448 * @param {Event} e 2449 * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj) 2450 * @private 2451 */ 2452 handleMouseDown: function(e, oDD) { 2453 2454 var button = e.which || e.button; 2455 this.logger.log("button: " + button); 2456 2457 if (this.primaryButtonOnly && button > 1) { 2458 this.logger.log("Mousedown was not produced by the primary button"); 2459 return; 2460 } 2461 2462 if (this.isLocked()) { 2463 this.logger.log("Drag and drop is disabled, aborting"); 2464 return; 2465 } 2466 2467 this.logger.log("mousedown " + this.id); 2468 2469 this.logger.log("firing onMouseDown events"); 2470 2471 // firing the mousedown events prior to calculating positions 2472 var b4Return = this.b4MouseDown(e), 2473 b4Return2 = true; 2474 2475 if (this.events.b4MouseDown) { 2476 b4Return2 = this.fireEvent('b4MouseDownEvent', e); 2477 } 2478 var mDownReturn = this.onMouseDown(e), 2479 mDownReturn2 = true; 2480 if (this.events.mouseDown) { 2481 if (mDownReturn === false) { 2482 //Fixes #2528759 - Mousedown function returned false, don't fire the event and cancel everything. 2483 mDownReturn2 = false; 2484 } else { 2485 mDownReturn2 = this.fireEvent('mouseDownEvent', e); 2486 } 2487 } 2488 2489 if ((b4Return === false) || (mDownReturn === false) || (b4Return2 === false) || (mDownReturn2 === false)) { 2490 this.logger.log('b4MouseDown or onMouseDown returned false, exiting drag'); 2491 return; 2492 } 2493 2494 this.DDM.refreshCache(this.groups); 2495 // var self = this; 2496 // setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0); 2497 2498 // Only process the event if we really clicked within the linked 2499 // element. The reason we make this check is that in the case that 2500 // another element was moved between the clicked element and the 2501 // cursor in the time between the mousedown and mouseup events. When 2502 // this happens, the element gets the next mousedown event 2503 // regardless of where on the screen it happened. 2504 var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e)); 2505 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { 2506 this.logger.log("Click was not over the element: " + this.id); 2507 } else { 2508 if (this.clickValidator(e)) { 2509 2510 this.logger.log("click was a valid handle"); 2511 2512 // set the initial element position 2513 this.setStartPosition(); 2514 2515 // start tracking mousemove distance and mousedown time to 2516 // determine when to start the actual drag 2517 this.DDM.handleMouseDown(e, this); 2518 2519 // this mousedown is mine 2520 this.DDM.stopEvent(e); 2521 } else { 2522 2523 this.logger.log("clickValidator returned false, drag not initiated"); 2524 2525 } 2526 } 2527 }, 2528 2529 /** 2530 * @method clickValidator 2531 * @description Method validates that the clicked element 2532 * was indeed the handle or a valid child of the handle 2533 * @param {Event} e 2534 */ 2535 clickValidator: function(e) { 2536 var target = YAHOO.util.Event.getTarget(e); 2537 return ( this.isValidHandleChild(target) && 2538 (this.id == this.handleElId || 2539 this.DDM.handleWasClicked(target, this.id)) ); 2540 }, 2541 2542 /** 2543 * Finds the location the element should be placed if we want to move 2544 * it to where the mouse location less the click offset would place us. 2545 * @method getTargetCoord 2546 * @param {int} iPageX the X coordinate of the click 2547 * @param {int} iPageY the Y coordinate of the click 2548 * @return an object that contains the coordinates (Object.x and Object.y) 2549 * @private 2550 */ 2551 getTargetCoord: function(iPageX, iPageY) { 2552 2553 // this.logger.log("getTargetCoord: " + iPageX + ", " + iPageY); 2554 2555 var x = iPageX - this.deltaX; 2556 var y = iPageY - this.deltaY; 2557 2558 if (this.constrainX) { 2559 if (x < this.minX) { x = this.minX; } 2560 if (x > this.maxX) { x = this.maxX; } 2561 } 2562 2563 if (this.constrainY) { 2564 if (y < this.minY) { y = this.minY; } 2565 if (y > this.maxY) { y = this.maxY; } 2566 } 2567 2568 x = this.getTick(x, this.xTicks); 2569 y = this.getTick(y, this.yTicks); 2570 2571 // this.logger.log("getTargetCoord " + 2572 // " iPageX: " + iPageX + 2573 // " iPageY: " + iPageY + 2574 // " x: " + x + ", y: " + y); 2575 2576 return {x:x, y:y}; 2577 }, 2578 2579 /** 2580 * Allows you to specify a tag name that should not start a drag operation 2581 * when clicked. This is designed to facilitate embedding links within a 2582 * drag handle that do something other than start the drag. 2583 * @method addInvalidHandleType 2584 * @param {string} tagName the type of element to exclude 2585 */ 2586 addInvalidHandleType: function(tagName) { 2587 var type = tagName.toUpperCase(); 2588 this.invalidHandleTypes[type] = type; 2589 }, 2590 2591 /** 2592 * Lets you to specify an element id for a child of a drag handle 2593 * that should not initiate a drag 2594 * @method addInvalidHandleId 2595 * @param {string} id the element id of the element you wish to ignore 2596 */ 2597 addInvalidHandleId: function(id) { 2598 if (typeof id !== "string") { 2599 YAHOO.log("id is not a string, assuming it is an HTMLElement"); 2600 id = Dom.generateId(id); 2601 } 2602 this.invalidHandleIds[id] = id; 2603 }, 2604 2605 2606 /** 2607 * Lets you specify a css class of elements that will not initiate a drag 2608 * @method addInvalidHandleClass 2609 * @param {string} cssClass the class of the elements you wish to ignore 2610 */ 2611 addInvalidHandleClass: function(cssClass) { 2612 this.invalidHandleClasses.push(cssClass); 2613 }, 2614 2615 /** 2616 * Unsets an excluded tag name set by addInvalidHandleType 2617 * @method removeInvalidHandleType 2618 * @param {string} tagName the type of element to unexclude 2619 */ 2620 removeInvalidHandleType: function(tagName) { 2621 var type = tagName.toUpperCase(); 2622 // this.invalidHandleTypes[type] = null; 2623 delete this.invalidHandleTypes[type]; 2624 }, 2625 2626 /** 2627 * Unsets an invalid handle id 2628 * @method removeInvalidHandleId 2629 * @param {string} id the id of the element to re-enable 2630 */ 2631 removeInvalidHandleId: function(id) { 2632 if (typeof id !== "string") { 2633 YAHOO.log("id is not a string, assuming it is an HTMLElement"); 2634 id = Dom.generateId(id); 2635 } 2636 delete this.invalidHandleIds[id]; 2637 }, 2638 2639 /** 2640 * Unsets an invalid css class 2641 * @method removeInvalidHandleClass 2642 * @param {string} cssClass the class of the element(s) you wish to 2643 * re-enable 2644 */ 2645 removeInvalidHandleClass: function(cssClass) { 2646 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) { 2647 if (this.invalidHandleClasses[i] == cssClass) { 2648 delete this.invalidHandleClasses[i]; 2649 } 2650 } 2651 }, 2652 2653 /** 2654 * Checks the tag exclusion list to see if this click should be ignored 2655 * @method isValidHandleChild 2656 * @param {HTMLElement} node the HTMLElement to evaluate 2657 * @return {boolean} true if this is a valid tag type, false if not 2658 */ 2659 isValidHandleChild: function(node) { 2660 2661 var valid = true; 2662 // var n = (node.nodeName == "#text") ? node.parentNode : node; 2663 var nodeName; 2664 try { 2665 nodeName = node.nodeName.toUpperCase(); 2666 } catch(e) { 2667 nodeName = node.nodeName; 2668 } 2669 valid = valid && !this.invalidHandleTypes[nodeName]; 2670 valid = valid && !this.invalidHandleIds[node.id]; 2671 2672 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) { 2673 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]); 2674 } 2675 2676 this.logger.log("Valid handle? ... " + valid); 2677 2678 return valid; 2679 2680 }, 2681 2682 /** 2683 * Create the array of horizontal tick marks if an interval was specified 2684 * in setXConstraint(). 2685 * @method setXTicks 2686 * @private 2687 */ 2688 setXTicks: function(iStartX, iTickSize) { 2689 this.xTicks = []; 2690 this.xTickSize = iTickSize; 2691 2692 var tickMap = {}; 2693 2694 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) { 2695 if (!tickMap[i]) { 2696 this.xTicks[this.xTicks.length] = i; 2697 tickMap[i] = true; 2698 } 2699 } 2700 2701 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) { 2702 if (!tickMap[i]) { 2703 this.xTicks[this.xTicks.length] = i; 2704 tickMap[i] = true; 2705 } 2706 } 2707 2708 this.xTicks.sort(this.DDM.numericSort) ; 2709 this.logger.log("xTicks: " + this.xTicks.join()); 2710 }, 2711 2712 /** 2713 * Create the array of vertical tick marks if an interval was specified in 2714 * setYConstraint(). 2715 * @method setYTicks 2716 * @private 2717 */ 2718 setYTicks: function(iStartY, iTickSize) { 2719 // this.logger.log("setYTicks: " + iStartY + ", " + iTickSize 2720 // + ", " + this.initPageY + ", " + this.minY + ", " + this.maxY ); 2721 this.yTicks = []; 2722 this.yTickSize = iTickSize; 2723 2724 var tickMap = {}; 2725 2726 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) { 2727 if (!tickMap[i]) { 2728 this.yTicks[this.yTicks.length] = i; 2729 tickMap[i] = true; 2730 } 2731 } 2732 2733 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) { 2734 if (!tickMap[i]) { 2735 this.yTicks[this.yTicks.length] = i; 2736 tickMap[i] = true; 2737 } 2738 } 2739 2740 this.yTicks.sort(this.DDM.numericSort) ; 2741 this.logger.log("yTicks: " + this.yTicks.join()); 2742 }, 2743 2744 /** 2745 * By default, the element can be dragged any place on the screen. Use 2746 * this method to limit the horizontal travel of the element. Pass in 2747 * 0,0 for the parameters if you want to lock the drag to the y axis. 2748 * @method setXConstraint 2749 * @param {int} iLeft the number of pixels the element can move to the left 2750 * @param {int} iRight the number of pixels the element can move to the 2751 * right 2752 * @param {int} iTickSize optional parameter for specifying that the 2753 * element 2754 * should move iTickSize pixels at a time. 2755 */ 2756 setXConstraint: function(iLeft, iRight, iTickSize) { 2757 this.leftConstraint = parseInt(iLeft, 10); 2758 this.rightConstraint = parseInt(iRight, 10); 2759 2760 this.minX = this.initPageX - this.leftConstraint; 2761 this.maxX = this.initPageX + this.rightConstraint; 2762 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); } 2763 2764 this.constrainX = true; 2765 this.logger.log("initPageX:" + this.initPageX + " minX:" + this.minX + 2766 " maxX:" + this.maxX); 2767 }, 2768 2769 /** 2770 * Clears any constraints applied to this instance. Also clears ticks 2771 * since they can't exist independent of a constraint at this time. 2772 * @method clearConstraints 2773 */ 2774 clearConstraints: function() { 2775 this.logger.log("Clearing constraints"); 2776 this.constrainX = false; 2777 this.constrainY = false; 2778 this.clearTicks(); 2779 }, 2780 2781 /** 2782 * Clears any tick interval defined for this instance 2783 * @method clearTicks 2784 */ 2785 clearTicks: function() { 2786 this.logger.log("Clearing ticks"); 2787 this.xTicks = null; 2788 this.yTicks = null; 2789 this.xTickSize = 0; 2790 this.yTickSize = 0; 2791 }, 2792 2793 /** 2794 * By default, the element can be dragged any place on the screen. Set 2795 * this to limit the vertical travel of the element. Pass in 0,0 for the 2796 * parameters if you want to lock the drag to the x axis. 2797 * @method setYConstraint 2798 * @param {int} iUp the number of pixels the element can move up 2799 * @param {int} iDown the number of pixels the element can move down 2800 * @param {int} iTickSize optional parameter for specifying that the 2801 * element should move iTickSize pixels at a time. 2802 */ 2803 setYConstraint: function(iUp, iDown, iTickSize) { 2804 this.logger.log("setYConstraint: " + iUp + "," + iDown + "," + iTickSize); 2805 this.topConstraint = parseInt(iUp, 10); 2806 this.bottomConstraint = parseInt(iDown, 10); 2807 2808 this.minY = this.initPageY - this.topConstraint; 2809 this.maxY = this.initPageY + this.bottomConstraint; 2810 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); } 2811 2812 this.constrainY = true; 2813 2814 this.logger.log("initPageY:" + this.initPageY + " minY:" + this.minY + 2815 " maxY:" + this.maxY); 2816 }, 2817 2818 /** 2819 * resetConstraints must be called if you manually reposition a dd element. 2820 * @method resetConstraints 2821 */ 2822 resetConstraints: function() { 2823 2824 //this.logger.log("resetConstraints"); 2825 2826 // Maintain offsets if necessary 2827 if (this.initPageX || this.initPageX === 0) { 2828 //this.logger.log("init pagexy: " + this.initPageX + ", " + 2829 //this.initPageY); 2830 //this.logger.log("last pagexy: " + this.lastPageX + ", " + 2831 //this.lastPageY); 2832 // figure out how much this thing has moved 2833 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0; 2834 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0; 2835 2836 this.setInitPosition(dx, dy); 2837 2838 // This is the first time we have detected the element's position 2839 } else { 2840 this.setInitPosition(); 2841 } 2842 2843 if (this.constrainX) { 2844 this.setXConstraint( this.leftConstraint, 2845 this.rightConstraint, 2846 this.xTickSize ); 2847 } 2848 2849 if (this.constrainY) { 2850 this.setYConstraint( this.topConstraint, 2851 this.bottomConstraint, 2852 this.yTickSize ); 2853 } 2854 }, 2855 2856 /** 2857 * Normally the drag element is moved pixel by pixel, but we can specify 2858 * that it move a number of pixels at a time. This method resolves the 2859 * location when we have it set up like this. 2860 * @method getTick 2861 * @param {int} val where we want to place the object 2862 * @param {int[]} tickArray sorted array of valid points 2863 * @return {int} the closest tick 2864 * @private 2865 */ 2866 getTick: function(val, tickArray) { 2867 2868 if (!tickArray) { 2869 // If tick interval is not defined, it is effectively 1 pixel, 2870 // so we return the value passed to us. 2871 return val; 2872 } else if (tickArray[0] >= val) { 2873 // The value is lower than the first tick, so we return the first 2874 // tick. 2875 return tickArray[0]; 2876 } else { 2877 for (var i=0, len=tickArray.length; i<len; ++i) { 2878 var next = i + 1; 2879 if (tickArray[next] && tickArray[next] >= val) { 2880 var diff1 = val - tickArray[i]; 2881 var diff2 = tickArray[next] - val; 2882 return (diff2 > diff1) ? tickArray[i] : tickArray[next]; 2883 } 2884 } 2885 2886 // The value is larger than the last tick, so we return the last 2887 // tick. 2888 return tickArray[tickArray.length - 1]; 2889 } 2890 }, 2891 2892 /** 2893 * toString method 2894 * @method toString 2895 * @return {string} string representation of the dd obj 2896 */ 2897 toString: function() { 2898 return ("DragDrop " + this.id); 2899 } 2900 2901 }; 2902 YAHOO.augment(YAHOO.util.DragDrop, YAHOO.util.EventProvider); 2903 2904 /** 2905 * @event mouseDownEvent 2906 * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation. 2907 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2908 */ 2909 2910 /** 2911 * @event b4MouseDownEvent 2912 * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag. 2913 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2914 */ 2915 2916 /** 2917 * @event mouseUpEvent 2918 * @description Fired from inside DragDropMgr when the drag operation is finished. 2919 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2920 */ 2921 2922 /** 2923 * @event b4StartDragEvent 2924 * @description Fires before the startDragEvent, returning false will cancel the startDrag Event. 2925 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2926 */ 2927 2928 /** 2929 * @event startDragEvent 2930 * @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. 2931 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2932 */ 2933 2934 /** 2935 * @event b4EndDragEvent 2936 * @description Fires before the endDragEvent. Returning false will cancel. 2937 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2938 */ 2939 2940 /** 2941 * @event endDragEvent 2942 * @description Fires on the mouseup event after a drag has been initiated (startDrag fired). 2943 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2944 */ 2945 2946 /** 2947 * @event dragEvent 2948 * @description Occurs every mousemove event while dragging. 2949 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2950 */ 2951 /** 2952 * @event b4DragEvent 2953 * @description Fires before the dragEvent. 2954 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2955 */ 2956 /** 2957 * @event invalidDropEvent 2958 * @description Fires when the dragged objects is dropped in a location that contains no drop targets. 2959 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2960 */ 2961 /** 2962 * @event b4DragOutEvent 2963 * @description Fires before the dragOutEvent 2964 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2965 */ 2966 /** 2967 * @event dragOutEvent 2968 * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 2969 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2970 */ 2971 /** 2972 * @event dragEnterEvent 2973 * @description Occurs when the dragged object first interacts with another targettable drag and drop object. 2974 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2975 */ 2976 /** 2977 * @event b4DragOverEvent 2978 * @description Fires before the dragOverEvent. 2979 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2980 */ 2981 /** 2982 * @event dragOverEvent 2983 * @description Fires every mousemove event while over a drag and drop object. 2984 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2985 */ 2986 /** 2987 * @event b4DragDropEvent 2988 * @description Fires before the dragDropEvent 2989 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2990 */ 2991 /** 2992 * @event dragDropEvent 2993 * @description Fires when the dragged objects is dropped on another. 2994 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 2995 */ 2996 })(); 2997 /** 2998 * A DragDrop implementation where the linked element follows the 2999 * mouse cursor during a drag. 3000 * @class DD 3001 * @extends YAHOO.util.DragDrop 3002 * @constructor 3003 * @param {String} id the id of the linked element 3004 * @param {String} sGroup the group of related DragDrop items 3005 * @param {object} config an object containing configurable attributes 3006 * Valid properties for DD: 3007 * scroll 3008 */ 3009 YAHOO.util.DD = function(id, sGroup, config) { 3010 if (id) { 3011 this.init(id, sGroup, config); 3012 } 3013 }; 3014 3015 YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, { 3016 3017 /** 3018 * When set to true, the utility automatically tries to scroll the browser 3019 * window when a drag and drop element is dragged near the viewport boundary. 3020 * Defaults to true. 3021 * @property scroll 3022 * @type boolean 3023 */ 3024 scroll: true, 3025 3026 /** 3027 * Sets the pointer offset to the distance between the linked element's top 3028 * left corner and the location the element was clicked 3029 * @method autoOffset 3030 * @param {int} iPageX the X coordinate of the click 3031 * @param {int} iPageY the Y coordinate of the click 3032 */ 3033 autoOffset: function(iPageX, iPageY) { 3034 var x = iPageX - this.startPageX; 3035 var y = iPageY - this.startPageY; 3036 this.setDelta(x, y); 3037 // this.logger.log("autoOffset el pos: " + aCoord + ", delta: " + x + "," + y); 3038 }, 3039 3040 /** 3041 * Sets the pointer offset. You can call this directly to force the 3042 * offset to be in a particular location (e.g., pass in 0,0 to set it 3043 * to the center of the object, as done in YAHOO.widget.Slider) 3044 * @method setDelta 3045 * @param {int} iDeltaX the distance from the left 3046 * @param {int} iDeltaY the distance from the top 3047 */ 3048 setDelta: function(iDeltaX, iDeltaY) { 3049 this.deltaX = iDeltaX; 3050 this.deltaY = iDeltaY; 3051 this.logger.log("deltaX:" + this.deltaX + ", deltaY:" + this.deltaY); 3052 }, 3053 3054 /** 3055 * Sets the drag element to the location of the mousedown or click event, 3056 * maintaining the cursor location relative to the location on the element 3057 * that was clicked. Override this if you want to place the element in a 3058 * location other than where the cursor is. 3059 * @method setDragElPos 3060 * @param {int} iPageX the X coordinate of the mousedown or drag event 3061 * @param {int} iPageY the Y coordinate of the mousedown or drag event 3062 */ 3063 setDragElPos: function(iPageX, iPageY) { 3064 // the first time we do this, we are going to check to make sure 3065 // the element has css positioning 3066 3067 var el = this.getDragEl(); 3068 this.alignElWithMouse(el, iPageX, iPageY); 3069 }, 3070 3071 /** 3072 * Sets the element to the location of the mousedown or click event, 3073 * maintaining the cursor location relative to the location on the element 3074 * that was clicked. Override this if you want to place the element in a 3075 * location other than where the cursor is. 3076 * @method alignElWithMouse 3077 * @param {HTMLElement} el the element to move 3078 * @param {int} iPageX the X coordinate of the mousedown or drag event 3079 * @param {int} iPageY the Y coordinate of the mousedown or drag event 3080 */ 3081 alignElWithMouse: function(el, iPageX, iPageY) { 3082 var oCoord = this.getTargetCoord(iPageX, iPageY); 3083 // this.logger.log("****alignElWithMouse : " + el.id + ", " + aCoord + ", " + el.style.display); 3084 3085 if (!this.deltaSetXY) { 3086 var aCoord = [oCoord.x, oCoord.y]; 3087 YAHOO.util.Dom.setXY(el, aCoord); 3088 3089 var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); 3090 var newTop = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); 3091 3092 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ]; 3093 } else { 3094 YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px"); 3095 YAHOO.util.Dom.setStyle(el, "top", (oCoord.y + this.deltaSetXY[1]) + "px"); 3096 } 3097 3098 this.cachePosition(oCoord.x, oCoord.y); 3099 var self = this; 3100 setTimeout(function() { 3101 self.autoScroll.call(self, oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); 3102 }, 0); 3103 }, 3104 3105 /** 3106 * Saves the most recent position so that we can reset the constraints and 3107 * tick marks on-demand. We need to know this so that we can calculate the 3108 * number of pixels the element is offset from its original position. 3109 * @method cachePosition 3110 * @param iPageX the current x position (optional, this just makes it so we 3111 * don't have to look it up again) 3112 * @param iPageY the current y position (optional, this just makes it so we 3113 * don't have to look it up again) 3114 */ 3115 cachePosition: function(iPageX, iPageY) { 3116 if (iPageX) { 3117 this.lastPageX = iPageX; 3118 this.lastPageY = iPageY; 3119 } else { 3120 var aCoord = YAHOO.util.Dom.getXY(this.getEl()); 3121 this.lastPageX = aCoord[0]; 3122 this.lastPageY = aCoord[1]; 3123 } 3124 }, 3125 3126 /** 3127 * Auto-scroll the window if the dragged object has been moved beyond the 3128 * visible window boundary. 3129 * @method autoScroll 3130 * @param {int} x the drag element's x position 3131 * @param {int} y the drag element's y position 3132 * @param {int} h the height of the drag element 3133 * @param {int} w the width of the drag element 3134 * @private 3135 */ 3136 autoScroll: function(x, y, h, w) { 3137 3138 if (this.scroll) { 3139 // The client height 3140 var clientH = this.DDM.getClientHeight(); 3141 3142 // The client width 3143 var clientW = this.DDM.getClientWidth(); 3144 3145 // The amt scrolled down 3146 var st = this.DDM.getScrollTop(); 3147 3148 // The amt scrolled right 3149 var sl = this.DDM.getScrollLeft(); 3150 3151 // Location of the bottom of the element 3152 var bot = h + y; 3153 3154 // Location of the right of the element 3155 var right = w + x; 3156 3157 // The distance from the cursor to the bottom of the visible area, 3158 // adjusted so that we don't scroll if the cursor is beyond the 3159 // element drag constraints 3160 var toBot = (clientH + st - y - this.deltaY); 3161 3162 // The distance from the cursor to the right of the visible area 3163 var toRight = (clientW + sl - x - this.deltaX); 3164 3165 // this.logger.log( " x: " + x + " y: " + y + " h: " + h + 3166 // " clientH: " + clientH + " clientW: " + clientW + 3167 // " st: " + st + " sl: " + sl + " bot: " + bot + 3168 // " right: " + right + " toBot: " + toBot + " toRight: " + toRight); 3169 3170 // How close to the edge the cursor must be before we scroll 3171 // var thresh = (document.all) ? 100 : 40; 3172 var thresh = 40; 3173 3174 // How many pixels to scroll per autoscroll op. This helps to reduce 3175 // clunky scrolling. IE is more sensitive about this ... it needs this 3176 // value to be higher. 3177 var scrAmt = (document.all) ? 80 : 30; 3178 3179 // Scroll down if we are near the bottom of the visible page and the 3180 // obj extends below the crease 3181 if ( bot > clientH && toBot < thresh ) { 3182 window.scrollTo(sl, st + scrAmt); 3183 } 3184 3185 // Scroll up if the window is scrolled down and the top of the object 3186 // goes above the top border 3187 if ( y < st && st > 0 && y - st < thresh ) { 3188 window.scrollTo(sl, st - scrAmt); 3189 } 3190 3191 // Scroll right if the obj is beyond the right border and the cursor is 3192 // near the border. 3193 if ( right > clientW && toRight < thresh ) { 3194 window.scrollTo(sl + scrAmt, st); 3195 } 3196 3197 // Scroll left if the window has been scrolled to the right and the obj 3198 // extends past the left border 3199 if ( x < sl && sl > 0 && x - sl < thresh ) { 3200 window.scrollTo(sl - scrAmt, st); 3201 } 3202 } 3203 }, 3204 3205 /* 3206 * Sets up config options specific to this class. Overrides 3207 * YAHOO.util.DragDrop, but all versions of this method through the 3208 * inheritance chain are called 3209 */ 3210 applyConfig: function() { 3211 YAHOO.util.DD.superclass.applyConfig.call(this); 3212 this.scroll = (this.config.scroll !== false); 3213 }, 3214 3215 /* 3216 * Event that fires prior to the onMouseDown event. Overrides 3217 * YAHOO.util.DragDrop. 3218 */ 3219 b4MouseDown: function(e) { 3220 this.setStartPosition(); 3221 // this.resetConstraints(); 3222 this.autoOffset(YAHOO.util.Event.getPageX(e), 3223 YAHOO.util.Event.getPageY(e)); 3224 }, 3225 3226 /* 3227 * Event that fires prior to the onDrag event. Overrides 3228 * YAHOO.util.DragDrop. 3229 */ 3230 b4Drag: function(e) { 3231 this.setDragElPos(YAHOO.util.Event.getPageX(e), 3232 YAHOO.util.Event.getPageY(e)); 3233 }, 3234 3235 toString: function() { 3236 return ("DD " + this.id); 3237 } 3238 3239 ////////////////////////////////////////////////////////////////////////// 3240 // Debugging ygDragDrop events that can be overridden 3241 ////////////////////////////////////////////////////////////////////////// 3242 /* 3243 startDrag: function(x, y) { 3244 this.logger.log(this.id.toString() + " startDrag"); 3245 }, 3246 3247 onDrag: function(e) { 3248 this.logger.log(this.id.toString() + " onDrag"); 3249 }, 3250 3251 onDragEnter: function(e, id) { 3252 this.logger.log(this.id.toString() + " onDragEnter: " + id); 3253 }, 3254 3255 onDragOver: function(e, id) { 3256 this.logger.log(this.id.toString() + " onDragOver: " + id); 3257 }, 3258 3259 onDragOut: function(e, id) { 3260 this.logger.log(this.id.toString() + " onDragOut: " + id); 3261 }, 3262 3263 onDragDrop: function(e, id) { 3264 this.logger.log(this.id.toString() + " onDragDrop: " + id); 3265 }, 3266 3267 endDrag: function(e) { 3268 this.logger.log(this.id.toString() + " endDrag"); 3269 } 3270 3271 */ 3272 3273 /** 3274 * @event mouseDownEvent 3275 * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation. 3276 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3277 */ 3278 3279 /** 3280 * @event b4MouseDownEvent 3281 * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag. 3282 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3283 */ 3284 3285 /** 3286 * @event mouseUpEvent 3287 * @description Fired from inside DragDropMgr when the drag operation is finished. 3288 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3289 */ 3290 3291 /** 3292 * @event b4StartDragEvent 3293 * @description Fires before the startDragEvent, returning false will cancel the startDrag Event. 3294 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3295 */ 3296 3297 /** 3298 * @event startDragEvent 3299 * @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. 3300 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3301 */ 3302 3303 /** 3304 * @event b4EndDragEvent 3305 * @description Fires before the endDragEvent. Returning false will cancel. 3306 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3307 */ 3308 3309 /** 3310 * @event endDragEvent 3311 * @description Fires on the mouseup event after a drag has been initiated (startDrag fired). 3312 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3313 */ 3314 3315 /** 3316 * @event dragEvent 3317 * @description Occurs every mousemove event while dragging. 3318 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3319 */ 3320 /** 3321 * @event b4DragEvent 3322 * @description Fires before the dragEvent. 3323 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3324 */ 3325 /** 3326 * @event invalidDropEvent 3327 * @description Fires when the dragged objects is dropped in a location that contains no drop targets. 3328 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3329 */ 3330 /** 3331 * @event b4DragOutEvent 3332 * @description Fires before the dragOutEvent 3333 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3334 */ 3335 /** 3336 * @event dragOutEvent 3337 * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 3338 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3339 */ 3340 /** 3341 * @event dragEnterEvent 3342 * @description Occurs when the dragged object first interacts with another targettable drag and drop object. 3343 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3344 */ 3345 /** 3346 * @event b4DragOverEvent 3347 * @description Fires before the dragOverEvent. 3348 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3349 */ 3350 /** 3351 * @event dragOverEvent 3352 * @description Fires every mousemove event while over a drag and drop object. 3353 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3354 */ 3355 /** 3356 * @event b4DragDropEvent 3357 * @description Fires before the dragDropEvent 3358 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3359 */ 3360 /** 3361 * @event dragDropEvent 3362 * @description Fires when the dragged objects is dropped on another. 3363 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3364 */ 3365 }); 3366 /** 3367 * A DragDrop implementation that inserts an empty, bordered div into 3368 * the document that follows the cursor during drag operations. At the time of 3369 * the click, the frame div is resized to the dimensions of the linked html 3370 * element, and moved to the exact location of the linked element. 3371 * 3372 * References to the "frame" element refer to the single proxy element that 3373 * was created to be dragged in place of all DDProxy elements on the 3374 * page. 3375 * 3376 * @class DDProxy 3377 * @extends YAHOO.util.DD 3378 * @constructor 3379 * @param {String} id the id of the linked html element 3380 * @param {String} sGroup the group of related DragDrop objects 3381 * @param {object} config an object containing configurable attributes 3382 * Valid properties for DDProxy in addition to those in DragDrop: 3383 * resizeFrame, centerFrame, dragElId 3384 */ 3385 YAHOO.util.DDProxy = function(id, sGroup, config) { 3386 if (id) { 3387 this.init(id, sGroup, config); 3388 this.initFrame(); 3389 } 3390 }; 3391 3392 /** 3393 * The default drag frame div id 3394 * @property YAHOO.util.DDProxy.dragElId 3395 * @type String 3396 * @static 3397 */ 3398 YAHOO.util.DDProxy.dragElId = "ygddfdiv"; 3399 3400 YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, { 3401 3402 /** 3403 * By default we resize the drag frame to be the same size as the element 3404 * we want to drag (this is to get the frame effect). We can turn it off 3405 * if we want a different behavior. 3406 * @property resizeFrame 3407 * @type boolean 3408 */ 3409 resizeFrame: true, 3410 3411 /** 3412 * By default the frame is positioned exactly where the drag element is, so 3413 * we use the cursor offset provided by YAHOO.util.DD. Another option that works only if 3414 * you do not have constraints on the obj is to have the drag frame centered 3415 * around the cursor. Set centerFrame to true for this effect. 3416 * @property centerFrame 3417 * @type boolean 3418 */ 3419 centerFrame: false, 3420 3421 /** 3422 * Creates the proxy element if it does not yet exist 3423 * @method createFrame 3424 */ 3425 createFrame: function() { 3426 var self=this, body=document.body; 3427 3428 if (!body || !body.firstChild) { 3429 setTimeout( function() { self.createFrame(); }, 50 ); 3430 return; 3431 } 3432 3433 var div=this.getDragEl(), Dom=YAHOO.util.Dom; 3434 3435 if (!div) { 3436 div = document.createElement("div"); 3437 div.id = this.dragElId; 3438 var s = div.style; 3439 3440 s.position = "absolute"; 3441 s.visibility = "hidden"; 3442 s.cursor = "move"; 3443 s.border = "2px solid #aaa"; 3444 s.zIndex = 999; 3445 s.height = "25px"; 3446 s.width = "25px"; 3447 3448 var _data = document.createElement('div'); 3449 Dom.setStyle(_data, 'height', '100%'); 3450 Dom.setStyle(_data, 'width', '100%'); 3451 /** 3452 * If the proxy element has no background-color, then it is considered to the "transparent" by Internet Explorer. 3453 * Since it is "transparent" then the events pass through it to the iframe below. 3454 * So creating a "fake" div inside the proxy element and giving it a background-color, then setting it to an 3455 * opacity of 0, it appears to not be there, however IE still thinks that it is so the events never pass through. 3456 */ 3457 Dom.setStyle(_data, 'background-color', '#ccc'); 3458 Dom.setStyle(_data, 'opacity', '0'); 3459 div.appendChild(_data); 3460 3461 // appendChild can blow up IE if invoked prior to the window load event 3462 // while rendering a table. It is possible there are other scenarios 3463 // that would cause this to happen as well. 3464 body.insertBefore(div, body.firstChild); 3465 } 3466 }, 3467 3468 /** 3469 * Initialization for the drag frame element. Must be called in the 3470 * constructor of all subclasses 3471 * @method initFrame 3472 */ 3473 initFrame: function() { 3474 this.createFrame(); 3475 }, 3476 3477 applyConfig: function() { 3478 //this.logger.log("DDProxy applyConfig"); 3479 YAHOO.util.DDProxy.superclass.applyConfig.call(this); 3480 3481 this.resizeFrame = (this.config.resizeFrame !== false); 3482 this.centerFrame = (this.config.centerFrame); 3483 this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId); 3484 }, 3485 3486 /** 3487 * Resizes the drag frame to the dimensions of the clicked object, positions 3488 * it over the object, and finally displays it 3489 * @method showFrame 3490 * @param {int} iPageX X click position 3491 * @param {int} iPageY Y click position 3492 * @private 3493 */ 3494 showFrame: function(iPageX, iPageY) { 3495 var el = this.getEl(); 3496 var dragEl = this.getDragEl(); 3497 var s = dragEl.style; 3498 3499 this._resizeProxy(); 3500 3501 if (this.centerFrame) { 3502 this.setDelta( Math.round(parseInt(s.width, 10)/2), 3503 Math.round(parseInt(s.height, 10)/2) ); 3504 } 3505 3506 this.setDragElPos(iPageX, iPageY); 3507 3508 YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); 3509 }, 3510 3511 /** 3512 * The proxy is automatically resized to the dimensions of the linked 3513 * element when a drag is initiated, unless resizeFrame is set to false 3514 * @method _resizeProxy 3515 * @private 3516 */ 3517 _resizeProxy: function() { 3518 if (this.resizeFrame) { 3519 var DOM = YAHOO.util.Dom; 3520 var el = this.getEl(); 3521 var dragEl = this.getDragEl(); 3522 3523 var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth" ), 10); 3524 var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth" ), 10); 3525 var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10); 3526 var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth" ), 10); 3527 3528 if (isNaN(bt)) { bt = 0; } 3529 if (isNaN(br)) { br = 0; } 3530 if (isNaN(bb)) { bb = 0; } 3531 if (isNaN(bl)) { bl = 0; } 3532 3533 this.logger.log("proxy size: " + bt + " " + br + " " + bb + " " + bl); 3534 3535 var newWidth = Math.max(0, el.offsetWidth - br - bl); 3536 var newHeight = Math.max(0, el.offsetHeight - bt - bb); 3537 3538 this.logger.log("Resizing proxy element"); 3539 3540 DOM.setStyle( dragEl, "width", newWidth + "px" ); 3541 DOM.setStyle( dragEl, "height", newHeight + "px" ); 3542 } 3543 }, 3544 3545 // overrides YAHOO.util.DragDrop 3546 b4MouseDown: function(e) { 3547 this.setStartPosition(); 3548 var x = YAHOO.util.Event.getPageX(e); 3549 var y = YAHOO.util.Event.getPageY(e); 3550 this.autoOffset(x, y); 3551 3552 // This causes the autoscroll code to kick off, which means autoscroll can 3553 // happen prior to the check for a valid drag handle. 3554 // this.setDragElPos(x, y); 3555 }, 3556 3557 // overrides YAHOO.util.DragDrop 3558 b4StartDrag: function(x, y) { 3559 // show the drag frame 3560 this.logger.log("start drag show frame, x: " + x + ", y: " + y); 3561 this.showFrame(x, y); 3562 }, 3563 3564 // overrides YAHOO.util.DragDrop 3565 b4EndDrag: function(e) { 3566 this.logger.log(this.id + " b4EndDrag"); 3567 YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); 3568 }, 3569 3570 // overrides YAHOO.util.DragDrop 3571 // By default we try to move the element to the last location of the frame. 3572 // This is so that the default behavior mirrors that of YAHOO.util.DD. 3573 endDrag: function(e) { 3574 var DOM = YAHOO.util.Dom; 3575 this.logger.log(this.id + " endDrag"); 3576 var lel = this.getEl(); 3577 var del = this.getDragEl(); 3578 3579 // Show the drag frame briefly so we can get its position 3580 // del.style.visibility = ""; 3581 DOM.setStyle(del, "visibility", ""); 3582 3583 // Hide the linked element before the move to get around a Safari 3584 // rendering bug. 3585 //lel.style.visibility = "hidden"; 3586 DOM.setStyle(lel, "visibility", "hidden"); 3587 YAHOO.util.DDM.moveToEl(lel, del); 3588 //del.style.visibility = "hidden"; 3589 DOM.setStyle(del, "visibility", "hidden"); 3590 //lel.style.visibility = ""; 3591 DOM.setStyle(lel, "visibility", ""); 3592 }, 3593 3594 toString: function() { 3595 return ("DDProxy " + this.id); 3596 } 3597 /** 3598 * @event mouseDownEvent 3599 * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation. 3600 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3601 */ 3602 3603 /** 3604 * @event b4MouseDownEvent 3605 * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag. 3606 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3607 */ 3608 3609 /** 3610 * @event mouseUpEvent 3611 * @description Fired from inside DragDropMgr when the drag operation is finished. 3612 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3613 */ 3614 3615 /** 3616 * @event b4StartDragEvent 3617 * @description Fires before the startDragEvent, returning false will cancel the startDrag Event. 3618 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3619 */ 3620 3621 /** 3622 * @event startDragEvent 3623 * @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. 3624 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3625 */ 3626 3627 /** 3628 * @event b4EndDragEvent 3629 * @description Fires before the endDragEvent. Returning false will cancel. 3630 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3631 */ 3632 3633 /** 3634 * @event endDragEvent 3635 * @description Fires on the mouseup event after a drag has been initiated (startDrag fired). 3636 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3637 */ 3638 3639 /** 3640 * @event dragEvent 3641 * @description Occurs every mousemove event while dragging. 3642 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3643 */ 3644 /** 3645 * @event b4DragEvent 3646 * @description Fires before the dragEvent. 3647 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3648 */ 3649 /** 3650 * @event invalidDropEvent 3651 * @description Fires when the dragged objects is dropped in a location that contains no drop targets. 3652 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3653 */ 3654 /** 3655 * @event b4DragOutEvent 3656 * @description Fires before the dragOutEvent 3657 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3658 */ 3659 /** 3660 * @event dragOutEvent 3661 * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 3662 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3663 */ 3664 /** 3665 * @event dragEnterEvent 3666 * @description Occurs when the dragged object first interacts with another targettable drag and drop object. 3667 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3668 */ 3669 /** 3670 * @event b4DragOverEvent 3671 * @description Fires before the dragOverEvent. 3672 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3673 */ 3674 /** 3675 * @event dragOverEvent 3676 * @description Fires every mousemove event while over a drag and drop object. 3677 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3678 */ 3679 /** 3680 * @event b4DragDropEvent 3681 * @description Fires before the dragDropEvent 3682 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3683 */ 3684 /** 3685 * @event dragDropEvent 3686 * @description Fires when the dragged objects is dropped on another. 3687 * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event. 3688 */ 3689 3690 }); 3691 /** 3692 * A DragDrop implementation that does not move, but can be a drop 3693 * target. You would get the same result by simply omitting implementation 3694 * for the event callbacks, but this way we reduce the processing cost of the 3695 * event listener and the callbacks. 3696 * @class DDTarget 3697 * @extends YAHOO.util.DragDrop 3698 * @constructor 3699 * @param {String} id the id of the element that is a drop target 3700 * @param {String} sGroup the group of related DragDrop objects 3701 * @param {object} config an object containing configurable attributes 3702 * Valid properties for DDTarget in addition to those in 3703 * DragDrop: 3704 * none 3705 */ 3706 YAHOO.util.DDTarget = function(id, sGroup, config) { 3707 if (id) { 3708 this.initTarget(id, sGroup, config); 3709 } 3710 }; 3711 3712 // YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop(); 3713 YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop, { 3714 toString: function() { 3715 return ("DDTarget " + this.id); 3716 } 3717 }); 3718 YAHOO.register("dragdrop", YAHOO.util.DragDropMgr, {version: "2.9.0", build: "2800"}); 3719 3720 }, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-dom", "yui2-event"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |