[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('dd-drag', function (Y, NAME) { 9 10 11 /** 12 * Provides the ability to drag a Node. 13 * @module dd 14 * @submodule dd-drag 15 */ 16 /** 17 * Provides the ability to drag a Node. 18 * @class Drag 19 * @extends Base 20 * @constructor 21 * @namespace DD 22 */ 23 24 var DDM = Y.DD.DDM, 25 NODE = 'node', 26 DRAGGING = 'dragging', 27 DRAG_NODE = 'dragNode', 28 OFFSET_HEIGHT = 'offsetHeight', 29 OFFSET_WIDTH = 'offsetWidth', 30 /** 31 * Handles the mouseup DOM event, does nothing internally just fires. 32 * @event drag:mouseup 33 * @bubbles DDM 34 * @type {CustomEvent} 35 */ 36 /** 37 * Handles the mousedown DOM event, checks to see if you have a valid handle then starts the drag timers. 38 * @event drag:mouseDown 39 * @preventable _defMouseDownFn 40 * @param {EventFacade} event An Event Facade object with the following specific property added: 41 * <dl><dt>ev</dt><dd>The original mousedown event.</dd></dl> 42 * @bubbles DDM 43 * @type {CustomEvent} 44 */ 45 EV_MOUSE_DOWN = 'drag:mouseDown', 46 /** 47 * Fires after the mousedown event has been cleared. 48 * @event drag:afterMouseDown 49 * @param {EventFacade} event An Event Facade object with the following specific property added: 50 * <dl><dt>ev</dt><dd>The original mousedown event.</dd></dl> 51 * @bubbles DDM 52 * @type {CustomEvent} 53 */ 54 EV_AFTER_MOUSE_DOWN = 'drag:afterMouseDown', 55 /** 56 * Fires after a handle is removed. 57 * @event drag:removeHandle 58 * @param {EventFacade} event An Event Facade object with the following specific property added: 59 * <dl><dt>handle</dt><dd>The handle that was removed.</dd></dl> 60 * @bubbles DDM 61 * @type {CustomEvent} 62 */ 63 EV_REMOVE_HANDLE = 'drag:removeHandle', 64 /** 65 * Fires after a handle is added. 66 * @event drag:addHandle 67 * @param {EventFacade} event An Event Facade object with the following specific property added: 68 * <dl><dt>handle</dt><dd>The handle that was added.</dd></dl> 69 * @bubbles DDM 70 * @type {CustomEvent} 71 */ 72 EV_ADD_HANDLE = 'drag:addHandle', 73 /** 74 * Fires after an invalid selector is removed. 75 * @event drag:removeInvalid 76 * @param {EventFacade} event An Event Facade object with the following specific property added: 77 * <dl><dt>handle</dt><dd>The handle that was removed.</dd></dl> 78 * @bubbles DDM 79 * @type {CustomEvent} 80 */ 81 EV_REMOVE_INVALID = 'drag:removeInvalid', 82 /** 83 * Fires after an invalid selector is added. 84 * @event drag:addInvalid 85 * @param {EventFacade} event An Event Facade object with the following specific property added: 86 * <dl><dt>handle</dt><dd>The handle that was added.</dd></dl> 87 * @bubbles DDM 88 * @type {CustomEvent} 89 */ 90 EV_ADD_INVALID = 'drag:addInvalid', 91 /** 92 * Fires at the start of a drag operation. 93 * @event drag:start 94 * @param {EventFacade} event An Event Facade object with the following specific property added: 95 * <dl> 96 * <dt>pageX</dt><dd>The original node position X.</dd> 97 * <dt>pageY</dt><dd>The original node position Y.</dd> 98 * <dt>startTime</dt><dd>The startTime of the event. getTime on the current Date object.</dd> 99 * </dl> 100 * @bubbles DDM 101 * @type {CustomEvent} 102 */ 103 EV_START = 'drag:start', 104 /** 105 * Fires at the end of a drag operation. 106 * @event drag:end 107 * @param {EventFacade} event An Event Facade object with the following specific property added: 108 * <dl> 109 * <dt>pageX</dt><dd>The current node position X.</dd> 110 * <dt>pageY</dt><dd>The current node position Y.</dd> 111 * <dt>startTime</dt><dd>The startTime of the event, from the start event.</dd> 112 * <dt>endTime</dt><dd>The endTime of the event. getTime on the current Date object.</dd> 113 * </dl> 114 * @bubbles DDM 115 * @type {CustomEvent} 116 */ 117 EV_END = 'drag:end', 118 /** 119 * Fires every mousemove during a drag operation. 120 * @event drag:drag 121 * @param {EventFacade} event An Event Facade object with the following specific property added: 122 * <dl> 123 * <dt>pageX</dt><dd>The current node position X.</dd> 124 * <dt>pageY</dt><dd>The current node position Y.</dd> 125 * <dt>scroll</dt><dd>Should a scroll action occur.</dd> 126 * <dt>info</dt><dd>Object hash containing calculated XY arrays: start, xy, delta, offset</dd> 127 * </dl> 128 * @bubbles DDM 129 * @type {CustomEvent} 130 */ 131 EV_DRAG = 'drag:drag', 132 /** 133 * Fires when this node is aligned. 134 * @event drag:align 135 * @preventable _defAlignFn 136 * @param {EventFacade} event An Event Facade object with the following specific property added: 137 * <dl> 138 * <dt>pageX</dt><dd>The current node position X.</dd> 139 * <dt>pageY</dt><dd>The current node position Y.</dd> 140 * </dl> 141 * @bubbles DDM 142 * @type {CustomEvent} 143 */ 144 EV_ALIGN = 'drag:align', 145 /** 146 * Fires when this node is over a Drop Target. (Fired from dd-drop) 147 * @event drag:over 148 * @param {EventFacade} event An Event Facade object with the following specific property added: 149 * <dl> 150 * <dt>drop</dt><dd>The drop object at the time of the event.</dd> 151 * <dt>drag</dt><dd>The drag object at the time of the event.</dd> 152 * </dl> 153 * @bubbles DDM 154 * @type {CustomEvent} 155 */ 156 /** 157 * Fires when this node enters a Drop Target. (Fired from dd-drop) 158 * @event drag:enter 159 * @param {EventFacade} event An Event Facade object with the following specific property added: 160 * <dl> 161 * <dt>drop</dt><dd>The drop object at the time of the event.</dd> 162 * <dt>drag</dt><dd>The drag object at the time of the event.</dd> 163 * </dl> 164 * @bubbles DDM 165 * @type {CustomEvent} 166 */ 167 /** 168 * Fires when this node exits a Drop Target. (Fired from dd-drop) 169 * @event drag:exit 170 * @param {EventFacade} event An Event Facade object with the following specific property added: 171 * <dl> 172 * <dt>drop</dt><dd>The drop object at the time of the event.</dd> 173 * </dl> 174 * @bubbles DDM 175 * @type {CustomEvent} 176 */ 177 /** 178 * Fires when this node is dropped on a valid Drop Target. (Fired from dd-ddm-drop) 179 * @event drag:drophit 180 * @param {EventFacade} event An Event Facade object with the following specific property added: 181 * <dl> 182 * <dt>drop</dt><dd>The best guess on what was dropped on.</dd> 183 * <dt>drag</dt><dd>The drag object at the time of the event.</dd> 184 * <dt>others</dt><dd>An array of all the other drop targets that was dropped on.</dd> 185 * </dl> 186 * @bubbles DDM 187 * @type {CustomEvent} 188 */ 189 /** 190 * Fires when this node is dropped on an invalid Drop Target. (Fired from dd-ddm-drop) 191 * @event drag:dropmiss 192 * @param {EventFacade} event An Event Facade object with the following specific property added: 193 * <dl> 194 * <dt>pageX</dt><dd>The current node position X.</dd> 195 * <dt>pageY</dt><dd>The current node position Y.</dd> 196 * </dl> 197 * @bubbles DDM 198 * @type {CustomEvent} 199 */ 200 201 Drag = function(o) { 202 this._lazyAddAttrs = false; 203 Drag.superclass.constructor.apply(this, arguments); 204 205 var valid = DDM._regDrag(this); 206 if (!valid) { 207 Y.error('Failed to register node, already in use: ' + o.node); 208 } 209 }; 210 211 Drag.NAME = 'drag'; 212 213 /** 214 * This property defaults to "mousedown", but when drag-gestures is loaded, it is changed to "gesturemovestart" 215 * @static 216 * @property START_EVENT 217 */ 218 Drag.START_EVENT = 'mousedown'; 219 220 Drag.ATTRS = { 221 /** 222 * Y.Node instance to use as the element to initiate a drag operation 223 * @attribute node 224 * @type Node 225 */ 226 node: { 227 setter: function(node) { 228 if (this._canDrag(node)) { 229 return node; 230 } 231 var n = Y.one(node); 232 if (!n) { 233 Y.error('DD.Drag: Invalid Node Given: ' + node); 234 } 235 return n; 236 } 237 }, 238 /** 239 * Y.Node instance to use as the draggable element, defaults to node 240 * @attribute dragNode 241 * @type Node 242 */ 243 dragNode: { 244 setter: function(node) { 245 if (this._canDrag(node)) { 246 return node; 247 } 248 var n = Y.one(node); 249 if (!n) { 250 Y.error('DD.Drag: Invalid dragNode Given: ' + node); 251 } 252 return n; 253 } 254 }, 255 /** 256 * Offset the drag element by the difference in cursor position: default true 257 * @attribute offsetNode 258 * @type Boolean 259 */ 260 offsetNode: { 261 value: true 262 }, 263 /** 264 * Center the dragNode to the mouse position on drag:start: default false 265 * @attribute startCentered 266 * @type Boolean 267 */ 268 startCentered: { 269 value: false 270 }, 271 /** 272 * The number of pixels to move to start a drag operation, default is 3. 273 * @attribute clickPixelThresh 274 * @type Number 275 */ 276 clickPixelThresh: { 277 value: DDM.get('clickPixelThresh') 278 }, 279 /** 280 * The number of milliseconds a mousedown has to pass to start a drag operation, default is 1000. 281 * @attribute clickTimeThresh 282 * @type Number 283 */ 284 clickTimeThresh: { 285 value: DDM.get('clickTimeThresh') 286 }, 287 /** 288 * Set to lock this drag element so that it can't be dragged: default false. 289 * @attribute lock 290 * @type Boolean 291 */ 292 lock: { 293 value: false, 294 setter: function(lock) { 295 if (lock) { 296 this.get(NODE).addClass(DDM.CSS_PREFIX + '-locked'); 297 } else { 298 this.get(NODE).removeClass(DDM.CSS_PREFIX + '-locked'); 299 } 300 return lock; 301 } 302 }, 303 /** 304 * A payload holder to store arbitrary data about this drag object, can be used to store any value. 305 * @attribute data 306 * @type Mixed 307 */ 308 data: { 309 value: false 310 }, 311 /** 312 * If this is false, the drag element will not move with the cursor: default true. Can be used to "resize" the element. 313 * @attribute move 314 * @type Boolean 315 */ 316 move: { 317 value: true 318 }, 319 /** 320 * Use the protective shim on all drag operations: default true. Only works with dd-ddm, not dd-ddm-base. 321 * @attribute useShim 322 * @type Boolean 323 */ 324 useShim: { 325 value: true 326 }, 327 /** 328 * Config option is set by Drag to inform you of which handle fired the drag event (in the case that there are several handles): default false. 329 * @attribute activeHandle 330 * @type Node 331 */ 332 activeHandle: { 333 value: false 334 }, 335 /** 336 * By default a drag operation will only begin if the mousedown occurred with the primary mouse button. 337 * Setting this to false will allow for all mousedown events to trigger a drag. 338 * @attribute primaryButtonOnly 339 * @type Boolean 340 */ 341 primaryButtonOnly: { 342 value: true 343 }, 344 /** 345 * This attribute is not meant to be used by the implementor, it is meant to be used as an Event tracker so you can listen for it to change. 346 * @attribute dragging 347 * @type Boolean 348 */ 349 dragging: { 350 value: false 351 }, 352 parent: { 353 value: false 354 }, 355 /** 356 * This attribute only works if the dd-drop module has been loaded. It will make this node a drop target as well as draggable. 357 * @attribute target 358 * @type Boolean 359 */ 360 target: { 361 value: false, 362 setter: function(config) { 363 this._handleTarget(config); 364 return config; 365 } 366 }, 367 /** 368 * This attribute only works if the dd-drop module is active. It will set the dragMode (point, intersect, strict) of this Drag instance. 369 * @attribute dragMode 370 * @type String 371 */ 372 dragMode: { 373 value: null, 374 setter: function(mode) { 375 return DDM._setDragMode(mode); 376 } 377 }, 378 /** 379 * Array of groups to add this drag into. 380 * @attribute groups 381 * @type Array 382 */ 383 groups: { 384 value: ['default'], 385 getter: function() { 386 if (!this._groups) { 387 this._groups = {}; 388 return []; 389 } 390 391 return Y.Object.keys(this._groups); 392 }, 393 setter: function(g) { 394 this._groups = Y.Array.hash(g); 395 return g; 396 } 397 }, 398 /** 399 * Array of valid handles to add. Adding something here will set all handles, even if previously added with addHandle 400 * @attribute handles 401 * @type Array 402 */ 403 handles: { 404 value: null, 405 setter: function(g) { 406 if (g) { 407 this._handles = {}; 408 Y.Array.each(g, function(v) { 409 var key = v; 410 if (v instanceof Y.Node || v instanceof Y.NodeList) { 411 key = v._yuid; 412 } 413 this._handles[key] = v; 414 }, this); 415 } else { 416 this._handles = null; 417 } 418 return g; 419 } 420 }, 421 /** 422 * Controls the default bubble parent for this Drag instance. Default: Y.DD.DDM. Set to false to disable bubbling. Use bubbleTargets in config 423 * @deprecated 424 * @attribute bubbles 425 * @type Object 426 */ 427 bubbles: { 428 setter: function(t) { 429 Y.log('bubbles is deprecated use bubbleTargets: HOST', 'warn', 'dd'); 430 this.addTarget(t); 431 return t; 432 } 433 }, 434 /** 435 * Should the mousedown event be halted. Default: true 436 * @attribute haltDown 437 * @type Boolean 438 */ 439 haltDown: { 440 value: true 441 } 442 }; 443 444 Y.extend(Drag, Y.Base, { 445 /** 446 * Checks the object for the methods needed to drag the object around. 447 * Normally this would be a node instance, but in the case of Graphics, it 448 * may be an SVG node or something similar. 449 * @method _canDrag 450 * @private 451 * @param {Object} n The object to check 452 * @return {Boolean} True or false if the Object contains the methods needed to Drag 453 */ 454 _canDrag: function(n) { 455 if (n && n.setXY && n.getXY && n.test && n.contains) { 456 return true; 457 } 458 return false; 459 }, 460 /** 461 * The default bubbleTarget for this object. Default: Y.DD.DDM 462 * @private 463 * @property _bubbleTargets 464 */ 465 _bubbleTargets: Y.DD.DDM, 466 /** 467 * Add this Drag instance to a group, this should be used for on-the-fly group additions. 468 * @method addToGroup 469 * @param {String} g The group to add this Drag Instance to. 470 * @chainable 471 */ 472 addToGroup: function(g) { 473 this._groups[g] = true; 474 DDM._activateTargets(); 475 return this; 476 }, 477 /** 478 * Remove this Drag instance from a group, this should be used for on-the-fly group removals. 479 * @method removeFromGroup 480 * @param {String} g The group to remove this Drag Instance from. 481 * @chainable 482 */ 483 removeFromGroup: function(g) { 484 delete this._groups[g]; 485 DDM._activateTargets(); 486 return this; 487 }, 488 /** 489 * This will be a reference to the Drop instance associated with this drag if the target: true config attribute is set.. 490 * @property target 491 * @type {Object} 492 */ 493 target: null, 494 /** 495 * Attribute handler for the target config attribute. 496 * @private 497 * @method _handleTarget 498 * @param {Boolean/Object} config The Config 499 */ 500 _handleTarget: function(config) { 501 if (Y.DD.Drop) { 502 if (config === false) { 503 if (this.target) { 504 DDM._unregTarget(this.target); 505 this.target = null; 506 } 507 } else { 508 if (!Y.Lang.isObject(config)) { 509 config = {}; 510 } 511 config.bubbleTargets = config.bubbleTargets || this.getTargets(); 512 config.node = this.get(NODE); 513 config.groups = config.groups || this.get('groups'); 514 this.target = new Y.DD.Drop(config); 515 } 516 } 517 }, 518 /** 519 * Storage Array for the groups this drag belongs to. 520 * @private 521 * @property _groups 522 * @type {Array} 523 */ 524 _groups: null, 525 /** 526 * This method creates all the events for this Event Target and publishes them so we get Event Bubbling. 527 * @private 528 * @method _createEvents 529 */ 530 _createEvents: function() { 531 532 this.publish(EV_MOUSE_DOWN, { 533 defaultFn: this._defMouseDownFn, 534 queuable: false, 535 emitFacade: true, 536 bubbles: true, 537 prefix: 'drag' 538 }); 539 540 this.publish(EV_ALIGN, { 541 defaultFn: this._defAlignFn, 542 queuable: false, 543 emitFacade: true, 544 bubbles: true, 545 prefix: 'drag' 546 }); 547 548 this.publish(EV_DRAG, { 549 defaultFn: this._defDragFn, 550 queuable: false, 551 emitFacade: true, 552 bubbles: true, 553 prefix: 'drag' 554 }); 555 556 this.publish(EV_END, { 557 defaultFn: this._defEndFn, 558 preventedFn: this._prevEndFn, 559 queuable: false, 560 emitFacade: true, 561 bubbles: true, 562 prefix: 'drag' 563 }); 564 565 var ev = [ 566 EV_AFTER_MOUSE_DOWN, 567 EV_REMOVE_HANDLE, 568 EV_ADD_HANDLE, 569 EV_REMOVE_INVALID, 570 EV_ADD_INVALID, 571 EV_START, 572 'drag:drophit', 573 'drag:dropmiss', 574 'drag:over', 575 'drag:enter', 576 'drag:exit' 577 ]; 578 579 Y.Array.each(ev, function(v) { 580 this.publish(v, { 581 type: v, 582 emitFacade: true, 583 bubbles: true, 584 preventable: false, 585 queuable: false, 586 prefix: 'drag' 587 }); 588 }, this); 589 }, 590 /** 591 * A private reference to the mousedown DOM event 592 * @private 593 * @property _ev_md 594 * @type {EventFacade} 595 */ 596 _ev_md: null, 597 /** 598 * The getTime of the mousedown event. Not used, just here in case someone wants/needs to use it. 599 * @private 600 * @property _startTime 601 * @type Date 602 */ 603 _startTime: null, 604 /** 605 * The getTime of the mouseup event. Not used, just here in case someone wants/needs to use it. 606 * @private 607 * @property _endTime 608 * @type Date 609 */ 610 _endTime: null, 611 /** 612 * A private hash of the valid drag handles 613 * @private 614 * @property _handles 615 * @type {Object} 616 */ 617 _handles: null, 618 /** 619 * A private hash of the invalid selector strings 620 * @private 621 * @property _invalids 622 * @type {Object} 623 */ 624 _invalids: null, 625 /** 626 * A private hash of the default invalid selector strings: {'textarea': true, 'input': true, 'a': true, 'button': true, 'select': true} 627 * @private 628 * @property _invalidsDefault 629 * @type {Object} 630 */ 631 _invalidsDefault: {'textarea': true, 'input': true, 'a': true, 'button': true, 'select': true }, 632 /** 633 * Private flag to see if the drag threshhold was met 634 * @private 635 * @property _dragThreshMet 636 * @type {Boolean} 637 */ 638 _dragThreshMet: null, 639 /** 640 * Flag to determine if the drag operation came from a timeout 641 * @private 642 * @property _fromTimeout 643 * @type {Boolean} 644 */ 645 _fromTimeout: null, 646 /** 647 * Holder for the setTimeout call 648 * @private 649 * @property _clickTimeout 650 * @type {Boolean} 651 */ 652 _clickTimeout: null, 653 /** 654 * The offset of the mouse position to the element's position 655 * @property deltaXY 656 * @type {Array} 657 */ 658 deltaXY: null, 659 /** 660 * The initial mouse position 661 * @property startXY 662 * @type {Array} 663 */ 664 startXY: null, 665 /** 666 * The initial element position 667 * @property nodeXY 668 * @type {Array} 669 */ 670 nodeXY: null, 671 /** 672 * The position of the element as it's moving (for offset calculations) 673 * @property lastXY 674 * @type {Array} 675 */ 676 lastXY: null, 677 /** 678 * The xy that the node will be set to. Changing this will alter the position as it's dragged. 679 * @property actXY 680 * @type {Array} 681 */ 682 actXY: null, 683 /** 684 * The real xy position of the node. 685 * @property realXY 686 * @type {Array} 687 */ 688 realXY: null, 689 /** 690 * The XY coords of the mousemove 691 * @property mouseXY 692 * @type {Array} 693 */ 694 mouseXY: null, 695 /** 696 * A region object associated with this drag, used for checking regions while dragging. 697 * @property region 698 * @type Object 699 */ 700 region: null, 701 /** 702 * Handler for the mouseup DOM event 703 * @private 704 * @method _handleMouseUp 705 * @param {EventFacade} ev The Event 706 */ 707 _handleMouseUp: function() { 708 this.fire('drag:mouseup'); 709 this._fixIEMouseUp(); 710 if (DDM.activeDrag) { 711 DDM._end(); 712 } 713 }, 714 /** 715 * The function we use as the ondragstart handler when we start a drag 716 * in Internet Explorer. This keeps IE from blowing up on images as drag handles. 717 * @private 718 * @method _fixDragStart 719 * @param {Event} e The Event 720 */ 721 _fixDragStart: function(e) { 722 if (this.validClick(e)) { 723 e.preventDefault(); 724 } 725 }, 726 /** 727 * The function we use as the onselectstart handler when we start a drag in Internet Explorer 728 * @private 729 * @method _ieSelectFix 730 */ 731 _ieSelectFix: function() { 732 return false; 733 }, 734 /** 735 * We will hold a copy of the current "onselectstart" method on this property, and reset it after we are done using it. 736 * @private 737 * @property _ieSelectBack 738 */ 739 _ieSelectBack: null, 740 /** 741 * This method copies the onselectstart listner on the document to the _ieSelectFix property 742 * @private 743 * @method _fixIEMouseDown 744 */ 745 _fixIEMouseDown: function() { 746 if (Y.UA.ie) { 747 this._ieSelectBack = Y.config.doc.body.onselectstart; 748 Y.config.doc.body.onselectstart = this._ieSelectFix; 749 } 750 }, 751 /** 752 * This method copies the _ieSelectFix property back to the onselectstart listner on the document. 753 * @private 754 * @method _fixIEMouseUp 755 */ 756 _fixIEMouseUp: function() { 757 if (Y.UA.ie) { 758 Y.config.doc.body.onselectstart = this._ieSelectBack; 759 } 760 }, 761 /** 762 * Handler for the mousedown DOM event 763 * @private 764 * @method _handleMouseDownEvent 765 * @param {EventFacade} ev The Event 766 */ 767 _handleMouseDownEvent: function(ev) { 768 if (this.validClick(ev)) { 769 ev.preventDefault(); 770 } 771 this.fire(EV_MOUSE_DOWN, { ev: ev }); 772 }, 773 /** 774 * Handler for the mousedown DOM event 775 * @private 776 * @method _defMouseDownFn 777 * @param {EventFacade} e The Event 778 */ 779 _defMouseDownFn: function(e) { 780 var ev = e.ev; 781 782 this._dragThreshMet = false; 783 this._ev_md = ev; 784 785 if (this.get('primaryButtonOnly') && ev.button > 1) { 786 return false; 787 } 788 if (this.validClick(ev)) { 789 this._fixIEMouseDown(ev); 790 if (Drag.START_EVENT.indexOf('gesture') !== 0) { 791 //Only do these if it's not a gesture 792 if (this.get('haltDown')) { 793 Y.log('Halting MouseDown', 'info', 'drag'); 794 ev.halt(); 795 } else { 796 Y.log('Preventing Default on MouseDown', 'info', 'drag'); 797 ev.preventDefault(); 798 } 799 } 800 801 this._setStartPosition([ev.pageX, ev.pageY]); 802 803 DDM.activeDrag = this; 804 805 this._clickTimeout = Y.later(this.get('clickTimeThresh'), this, this._timeoutCheck); 806 } 807 this.fire(EV_AFTER_MOUSE_DOWN, { ev: ev }); 808 }, 809 /** 810 * Method first checks to see if we have handles, if so it validates the click 811 * against the handle. Then if it finds a valid handle, it checks it against 812 * the invalid handles list. Returns true if a good handle was used, false otherwise. 813 * @method validClick 814 * @param {EventFacade} ev The Event 815 * @return {Boolean} 816 */ 817 validClick: function(ev) { 818 var r = false, n = false, 819 tar = ev.target, 820 hTest = null, 821 els = null, 822 nlist = null, 823 set = false; 824 if (this._handles) { 825 Y.Object.each(this._handles, function(i, n) { 826 if (i instanceof Y.Node || i instanceof Y.NodeList) { 827 if (!r) { 828 nlist = i; 829 if (nlist instanceof Y.Node) { 830 nlist = new Y.NodeList(i._node); 831 } 832 nlist.each(function(nl) { 833 if (nl.contains(tar)) { 834 r = true; 835 } 836 }); 837 } 838 } else if (Y.Lang.isString(n)) { 839 //Am I this or am I inside this 840 if (tar.test(n + ', ' + n + ' *') && !hTest) { 841 hTest = n; 842 r = true; 843 } 844 } 845 }); 846 } else { 847 n = this.get(NODE); 848 if (n.contains(tar) || n.compareTo(tar)) { 849 r = true; 850 } 851 } 852 if (r) { 853 if (this._invalids) { 854 Y.Object.each(this._invalids, function(i, n) { 855 if (Y.Lang.isString(n)) { 856 //Am I this or am I inside this 857 if (tar.test(n + ', ' + n + ' *')) { 858 r = false; 859 } 860 } 861 }); 862 } 863 } 864 if (r) { 865 if (hTest) { 866 els = ev.currentTarget.all(hTest); 867 set = false; 868 els.each(function(n) { 869 if ((n.contains(tar) || n.compareTo(tar)) && !set) { 870 set = true; 871 this.set('activeHandle', n); 872 } 873 }, this); 874 } else { 875 this.set('activeHandle', this.get(NODE)); 876 } 877 } 878 return r; 879 }, 880 /** 881 * Sets the current position of the Element and calculates the offset 882 * @private 883 * @method _setStartPosition 884 * @param {Array} xy The XY coords to set the position to. 885 */ 886 _setStartPosition: function(xy) { 887 this.startXY = xy; 888 889 this.nodeXY = this.lastXY = this.realXY = this.get(NODE).getXY(); 890 891 if (this.get('offsetNode')) { 892 this.deltaXY = [(this.startXY[0] - this.nodeXY[0]), (this.startXY[1] - this.nodeXY[1])]; 893 } else { 894 this.deltaXY = [0, 0]; 895 } 896 }, 897 /** 898 * The method passed to setTimeout to determine if the clickTimeThreshold was met. 899 * @private 900 * @method _timeoutCheck 901 */ 902 _timeoutCheck: function() { 903 if (!this.get('lock') && !this._dragThreshMet && this._ev_md) { 904 this._fromTimeout = this._dragThreshMet = true; 905 this.start(); 906 this._alignNode([this._ev_md.pageX, this._ev_md.pageY], true); 907 } 908 }, 909 /** 910 * Remove a Selector added by addHandle 911 * @method removeHandle 912 * @param {String} str The selector for the handle to be removed. 913 * @chainable 914 */ 915 removeHandle: function(str) { 916 var key = str; 917 if (str instanceof Y.Node || str instanceof Y.NodeList) { 918 key = str._yuid; 919 } 920 if (this._handles[key]) { 921 delete this._handles[key]; 922 this.fire(EV_REMOVE_HANDLE, { handle: str }); 923 } 924 return this; 925 }, 926 /** 927 * Add a handle to a drag element. Drag only initiates when a mousedown happens on this element. 928 * @method addHandle 929 * @param {String} str The selector to test for a valid handle. Must be a child of the element. 930 * @chainable 931 */ 932 addHandle: function(str) { 933 if (!this._handles) { 934 this._handles = {}; 935 } 936 var key = str; 937 if (str instanceof Y.Node || str instanceof Y.NodeList) { 938 key = str._yuid; 939 } 940 this._handles[key] = str; 941 this.fire(EV_ADD_HANDLE, { handle: str }); 942 return this; 943 }, 944 /** 945 * Remove an invalid handle added by addInvalid 946 * @method removeInvalid 947 * @param {String} str The invalid handle to remove from the internal list. 948 * @chainable 949 */ 950 removeInvalid: function(str) { 951 if (this._invalids[str]) { 952 this._invalids[str] = null; 953 delete this._invalids[str]; 954 this.fire(EV_REMOVE_INVALID, { handle: str }); 955 } 956 return this; 957 }, 958 /** 959 * Add a selector string to test the handle against. If the test passes the drag operation will not continue. 960 * @method addInvalid 961 * @param {String} str The selector to test against to determine if this is an invalid drag handle. 962 * @chainable 963 */ 964 addInvalid: function(str) { 965 if (Y.Lang.isString(str)) { 966 this._invalids[str] = true; 967 this.fire(EV_ADD_INVALID, { handle: str }); 968 } 969 return this; 970 }, 971 /** 972 * Internal init handler 973 * @private 974 * @method initializer 975 */ 976 initializer: function() { 977 978 this.get(NODE).dd = this; 979 980 if (!this.get(NODE).get('id')) { 981 var id = Y.stamp(this.get(NODE)); 982 this.get(NODE).set('id', id); 983 } 984 985 this.actXY = []; 986 987 this._invalids = Y.clone(this._invalidsDefault, true); 988 989 this._createEvents(); 990 991 if (!this.get(DRAG_NODE)) { 992 this.set(DRAG_NODE, this.get(NODE)); 993 } 994 995 //Fix for #2528096 996 //Don't prep the DD instance until all plugins are loaded. 997 this.on('initializedChange', Y.bind(this._prep, this)); 998 999 //Shouldn't have to do this.. 1000 this.set('groups', this.get('groups')); 1001 }, 1002 /** 1003 * Attach event listners and add classname 1004 * @private 1005 * @method _prep 1006 */ 1007 _prep: function() { 1008 this._dragThreshMet = false; 1009 var node = this.get(NODE); 1010 node.addClass(DDM.CSS_PREFIX + '-draggable'); 1011 node.on(Drag.START_EVENT, Y.bind(this._handleMouseDownEvent, this)); 1012 node.on('mouseup', Y.bind(this._handleMouseUp, this)); 1013 node.on('dragstart', Y.bind(this._fixDragStart, this)); 1014 }, 1015 /** 1016 * Detach event listeners and remove classname 1017 * @private 1018 * @method _unprep 1019 */ 1020 _unprep: function() { 1021 var node = this.get(NODE); 1022 node.removeClass(DDM.CSS_PREFIX + '-draggable'); 1023 node.detachAll('mouseup'); 1024 node.detachAll('dragstart'); 1025 node.detachAll(Drag.START_EVENT); 1026 this.mouseXY = []; 1027 this.deltaXY = [0,0]; 1028 this.startXY = []; 1029 this.nodeXY = []; 1030 this.lastXY = []; 1031 this.actXY = []; 1032 this.realXY = []; 1033 }, 1034 /** 1035 * Starts the drag operation 1036 * @method start 1037 * @chainable 1038 */ 1039 start: function() { 1040 if (!this.get('lock') && !this.get(DRAGGING)) { 1041 var node = this.get(NODE), ow, oh, xy; 1042 this._startTime = (new Date()).getTime(); 1043 1044 DDM._start(); 1045 node.addClass(DDM.CSS_PREFIX + '-dragging'); 1046 this.fire(EV_START, { 1047 pageX: this.nodeXY[0], 1048 pageY: this.nodeXY[1], 1049 startTime: this._startTime 1050 }); 1051 node = this.get(DRAG_NODE); 1052 xy = this.nodeXY; 1053 1054 ow = node.get(OFFSET_WIDTH); 1055 oh = node.get(OFFSET_HEIGHT); 1056 1057 if (this.get('startCentered')) { 1058 this._setStartPosition([xy[0] + (ow / 2), xy[1] + (oh / 2)]); 1059 } 1060 1061 1062 this.region = { 1063 '0': xy[0], 1064 '1': xy[1], 1065 area: 0, 1066 top: xy[1], 1067 right: xy[0] + ow, 1068 bottom: xy[1] + oh, 1069 left: xy[0] 1070 }; 1071 this.set(DRAGGING, true); 1072 } 1073 return this; 1074 }, 1075 /** 1076 * Ends the drag operation 1077 * @method end 1078 * @chainable 1079 */ 1080 end: function() { 1081 this._endTime = (new Date()).getTime(); 1082 if (this._clickTimeout) { 1083 this._clickTimeout.cancel(); 1084 } 1085 this._dragThreshMet = this._fromTimeout = false; 1086 1087 if (!this.get('lock') && this.get(DRAGGING)) { 1088 this.fire(EV_END, { 1089 pageX: this.lastXY[0], 1090 pageY: this.lastXY[1], 1091 startTime: this._startTime, 1092 endTime: this._endTime 1093 }); 1094 } 1095 this.get(NODE).removeClass(DDM.CSS_PREFIX + '-dragging'); 1096 this.set(DRAGGING, false); 1097 this.deltaXY = [0, 0]; 1098 1099 return this; 1100 }, 1101 /** 1102 * Handler for fixing the selection in IE 1103 * @private 1104 * @method _defEndFn 1105 */ 1106 _defEndFn: function() { 1107 this._fixIEMouseUp(); 1108 this._ev_md = null; 1109 }, 1110 /** 1111 * Handler for preventing the drag:end event. It will reset the node back to it's start position 1112 * @private 1113 * @method _prevEndFn 1114 */ 1115 _prevEndFn: function() { 1116 this._fixIEMouseUp(); 1117 //Bug #1852577 1118 this.get(DRAG_NODE).setXY(this.nodeXY); 1119 this._ev_md = null; 1120 this.region = null; 1121 }, 1122 /** 1123 * Calculates the offsets and set's the XY that the element will move to. 1124 * @private 1125 * @method _align 1126 * @param {Array} xy The xy coords to align with. 1127 */ 1128 _align: function(xy) { 1129 this.fire(EV_ALIGN, {pageX: xy[0], pageY: xy[1] }); 1130 }, 1131 /** 1132 * Calculates the offsets and set's the XY that the element will move to. 1133 * @private 1134 * @method _defAlignFn 1135 * @param {EventFacade} e The drag:align event. 1136 */ 1137 _defAlignFn: function(e) { 1138 this.actXY = [e.pageX - this.deltaXY[0], e.pageY - this.deltaXY[1]]; 1139 }, 1140 /** 1141 * This method performs the alignment before the element move. 1142 * @private 1143 * @method _alignNode 1144 * @param {Array} eXY The XY to move the element to, usually comes from the mousemove DOM event. 1145 */ 1146 _alignNode: function(eXY, scroll) { 1147 this._align(eXY); 1148 if (!scroll) { 1149 this._moveNode(); 1150 } 1151 }, 1152 /** 1153 * This method performs the actual element move. 1154 * @private 1155 * @method _moveNode 1156 */ 1157 _moveNode: function(scroll) { 1158 //if (!this.get(DRAGGING)) { 1159 // return; 1160 //} 1161 var diffXY = [], diffXY2 = [], startXY = this.nodeXY, xy = this.actXY; 1162 1163 diffXY[0] = (xy[0] - this.lastXY[0]); 1164 diffXY[1] = (xy[1] - this.lastXY[1]); 1165 1166 diffXY2[0] = (xy[0] - this.nodeXY[0]); 1167 diffXY2[1] = (xy[1] - this.nodeXY[1]); 1168 1169 1170 this.region = { 1171 '0': xy[0], 1172 '1': xy[1], 1173 area: 0, 1174 top: xy[1], 1175 right: xy[0] + this.get(DRAG_NODE).get(OFFSET_WIDTH), 1176 bottom: xy[1] + this.get(DRAG_NODE).get(OFFSET_HEIGHT), 1177 left: xy[0] 1178 }; 1179 1180 this.fire(EV_DRAG, { 1181 pageX: xy[0], 1182 pageY: xy[1], 1183 scroll: scroll, 1184 info: { 1185 start: startXY, 1186 xy: xy, 1187 delta: diffXY, 1188 offset: diffXY2 1189 } 1190 }); 1191 1192 this.lastXY = xy; 1193 }, 1194 /** 1195 * Default function for drag:drag. Fired from _moveNode. 1196 * @private 1197 * @method _defDragFn 1198 * @param {EventFacade} ev The drag:drag event 1199 */ 1200 _defDragFn: function(e) { 1201 if (this.get('move')) { 1202 if (e.scroll && e.scroll.node) { 1203 var domNode = e.scroll.node.getDOMNode(); 1204 //If it's the window 1205 if (domNode === Y.config.win) { 1206 domNode.scrollTo(e.scroll.left, e.scroll.top); 1207 } else { 1208 e.scroll.node.set('scrollTop', e.scroll.top); 1209 e.scroll.node.set('scrollLeft', e.scroll.left); 1210 } 1211 } 1212 this.get(DRAG_NODE).setXY([e.pageX, e.pageY]); 1213 this.realXY = [e.pageX, e.pageY]; 1214 } 1215 }, 1216 /** 1217 * Fired from DragDropMgr (DDM) on mousemove. 1218 * @private 1219 * @method _move 1220 * @param {EventFacade} ev The mousemove DOM event 1221 */ 1222 _move: function(ev) { 1223 if (this.get('lock')) { 1224 return false; 1225 } 1226 1227 this.mouseXY = [ev.pageX, ev.pageY]; 1228 if (!this._dragThreshMet) { 1229 var diffX = Math.abs(this.startXY[0] - ev.pageX), 1230 diffY = Math.abs(this.startXY[1] - ev.pageY); 1231 if (diffX > this.get('clickPixelThresh') || diffY > this.get('clickPixelThresh')) { 1232 this._dragThreshMet = true; 1233 this.start(); 1234 //This only happens on gestures to stop the page from scrolling 1235 if (ev && ev.preventDefault) { 1236 ev.preventDefault(); 1237 } 1238 this._alignNode([ev.pageX, ev.pageY]); 1239 } 1240 } else { 1241 if (this._clickTimeout) { 1242 this._clickTimeout.cancel(); 1243 } 1244 this._alignNode([ev.pageX, ev.pageY]); 1245 } 1246 }, 1247 /** 1248 * Method will forcefully stop a drag operation. For example calling this from inside an ESC keypress handler will stop this drag. 1249 * @method stopDrag 1250 * @chainable 1251 */ 1252 stopDrag: function() { 1253 if (this.get(DRAGGING)) { 1254 DDM._end(); 1255 } 1256 return this; 1257 }, 1258 /** 1259 * Lifecycle destructor, unreg the drag from the DDM and remove listeners 1260 * @private 1261 * @method destructor 1262 */ 1263 destructor: function() { 1264 this._unprep(); 1265 if (this.target) { 1266 this.target.destroy(); 1267 } 1268 DDM._unregDrag(this); 1269 } 1270 }); 1271 Y.namespace('DD'); 1272 Y.DD.Drag = Drag; 1273 1274 1275 1276 1277 }, '3.17.2', {"requires": ["dd-ddm-base"]});
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 |