[ 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 this.addTarget(t); 430 return t; 431 } 432 }, 433 /** 434 * Should the mousedown event be halted. Default: true 435 * @attribute haltDown 436 * @type Boolean 437 */ 438 haltDown: { 439 value: true 440 } 441 }; 442 443 Y.extend(Drag, Y.Base, { 444 /** 445 * Checks the object for the methods needed to drag the object around. 446 * Normally this would be a node instance, but in the case of Graphics, it 447 * may be an SVG node or something similar. 448 * @method _canDrag 449 * @private 450 * @param {Object} n The object to check 451 * @return {Boolean} True or false if the Object contains the methods needed to Drag 452 */ 453 _canDrag: function(n) { 454 if (n && n.setXY && n.getXY && n.test && n.contains) { 455 return true; 456 } 457 return false; 458 }, 459 /** 460 * The default bubbleTarget for this object. Default: Y.DD.DDM 461 * @private 462 * @property _bubbleTargets 463 */ 464 _bubbleTargets: Y.DD.DDM, 465 /** 466 * Add this Drag instance to a group, this should be used for on-the-fly group additions. 467 * @method addToGroup 468 * @param {String} g The group to add this Drag Instance to. 469 * @chainable 470 */ 471 addToGroup: function(g) { 472 this._groups[g] = true; 473 DDM._activateTargets(); 474 return this; 475 }, 476 /** 477 * Remove this Drag instance from a group, this should be used for on-the-fly group removals. 478 * @method removeFromGroup 479 * @param {String} g The group to remove this Drag Instance from. 480 * @chainable 481 */ 482 removeFromGroup: function(g) { 483 delete this._groups[g]; 484 DDM._activateTargets(); 485 return this; 486 }, 487 /** 488 * This will be a reference to the Drop instance associated with this drag if the target: true config attribute is set.. 489 * @property target 490 * @type {Object} 491 */ 492 target: null, 493 /** 494 * Attribute handler for the target config attribute. 495 * @private 496 * @method _handleTarget 497 * @param {Boolean/Object} config The Config 498 */ 499 _handleTarget: function(config) { 500 if (Y.DD.Drop) { 501 if (config === false) { 502 if (this.target) { 503 DDM._unregTarget(this.target); 504 this.target = null; 505 } 506 } else { 507 if (!Y.Lang.isObject(config)) { 508 config = {}; 509 } 510 config.bubbleTargets = config.bubbleTargets || this.getTargets(); 511 config.node = this.get(NODE); 512 config.groups = config.groups || this.get('groups'); 513 this.target = new Y.DD.Drop(config); 514 } 515 } 516 }, 517 /** 518 * Storage Array for the groups this drag belongs to. 519 * @private 520 * @property _groups 521 * @type {Array} 522 */ 523 _groups: null, 524 /** 525 * This method creates all the events for this Event Target and publishes them so we get Event Bubbling. 526 * @private 527 * @method _createEvents 528 */ 529 _createEvents: function() { 530 531 this.publish(EV_MOUSE_DOWN, { 532 defaultFn: this._defMouseDownFn, 533 queuable: false, 534 emitFacade: true, 535 bubbles: true, 536 prefix: 'drag' 537 }); 538 539 this.publish(EV_ALIGN, { 540 defaultFn: this._defAlignFn, 541 queuable: false, 542 emitFacade: true, 543 bubbles: true, 544 prefix: 'drag' 545 }); 546 547 this.publish(EV_DRAG, { 548 defaultFn: this._defDragFn, 549 queuable: false, 550 emitFacade: true, 551 bubbles: true, 552 prefix: 'drag' 553 }); 554 555 this.publish(EV_END, { 556 defaultFn: this._defEndFn, 557 preventedFn: this._prevEndFn, 558 queuable: false, 559 emitFacade: true, 560 bubbles: true, 561 prefix: 'drag' 562 }); 563 564 var ev = [ 565 EV_AFTER_MOUSE_DOWN, 566 EV_REMOVE_HANDLE, 567 EV_ADD_HANDLE, 568 EV_REMOVE_INVALID, 569 EV_ADD_INVALID, 570 EV_START, 571 'drag:drophit', 572 'drag:dropmiss', 573 'drag:over', 574 'drag:enter', 575 'drag:exit' 576 ]; 577 578 Y.Array.each(ev, function(v) { 579 this.publish(v, { 580 type: v, 581 emitFacade: true, 582 bubbles: true, 583 preventable: false, 584 queuable: false, 585 prefix: 'drag' 586 }); 587 }, this); 588 }, 589 /** 590 * A private reference to the mousedown DOM event 591 * @private 592 * @property _ev_md 593 * @type {EventFacade} 594 */ 595 _ev_md: null, 596 /** 597 * The getTime of the mousedown event. Not used, just here in case someone wants/needs to use it. 598 * @private 599 * @property _startTime 600 * @type Date 601 */ 602 _startTime: null, 603 /** 604 * The getTime of the mouseup event. Not used, just here in case someone wants/needs to use it. 605 * @private 606 * @property _endTime 607 * @type Date 608 */ 609 _endTime: null, 610 /** 611 * A private hash of the valid drag handles 612 * @private 613 * @property _handles 614 * @type {Object} 615 */ 616 _handles: null, 617 /** 618 * A private hash of the invalid selector strings 619 * @private 620 * @property _invalids 621 * @type {Object} 622 */ 623 _invalids: null, 624 /** 625 * A private hash of the default invalid selector strings: {'textarea': true, 'input': true, 'a': true, 'button': true, 'select': true} 626 * @private 627 * @property _invalidsDefault 628 * @type {Object} 629 */ 630 _invalidsDefault: {'textarea': true, 'input': true, 'a': true, 'button': true, 'select': true }, 631 /** 632 * Private flag to see if the drag threshhold was met 633 * @private 634 * @property _dragThreshMet 635 * @type {Boolean} 636 */ 637 _dragThreshMet: null, 638 /** 639 * Flag to determine if the drag operation came from a timeout 640 * @private 641 * @property _fromTimeout 642 * @type {Boolean} 643 */ 644 _fromTimeout: null, 645 /** 646 * Holder for the setTimeout call 647 * @private 648 * @property _clickTimeout 649 * @type {Boolean} 650 */ 651 _clickTimeout: null, 652 /** 653 * The offset of the mouse position to the element's position 654 * @property deltaXY 655 * @type {Array} 656 */ 657 deltaXY: null, 658 /** 659 * The initial mouse position 660 * @property startXY 661 * @type {Array} 662 */ 663 startXY: null, 664 /** 665 * The initial element position 666 * @property nodeXY 667 * @type {Array} 668 */ 669 nodeXY: null, 670 /** 671 * The position of the element as it's moving (for offset calculations) 672 * @property lastXY 673 * @type {Array} 674 */ 675 lastXY: null, 676 /** 677 * The xy that the node will be set to. Changing this will alter the position as it's dragged. 678 * @property actXY 679 * @type {Array} 680 */ 681 actXY: null, 682 /** 683 * The real xy position of the node. 684 * @property realXY 685 * @type {Array} 686 */ 687 realXY: null, 688 /** 689 * The XY coords of the mousemove 690 * @property mouseXY 691 * @type {Array} 692 */ 693 mouseXY: null, 694 /** 695 * A region object associated with this drag, used for checking regions while dragging. 696 * @property region 697 * @type Object 698 */ 699 region: null, 700 /** 701 * Handler for the mouseup DOM event 702 * @private 703 * @method _handleMouseUp 704 * @param {EventFacade} ev The Event 705 */ 706 _handleMouseUp: function() { 707 this.fire('drag:mouseup'); 708 this._fixIEMouseUp(); 709 if (DDM.activeDrag) { 710 DDM._end(); 711 } 712 }, 713 /** 714 * The function we use as the ondragstart handler when we start a drag 715 * in Internet Explorer. This keeps IE from blowing up on images as drag handles. 716 * @private 717 * @method _fixDragStart 718 * @param {Event} e The Event 719 */ 720 _fixDragStart: function(e) { 721 if (this.validClick(e)) { 722 e.preventDefault(); 723 } 724 }, 725 /** 726 * The function we use as the onselectstart handler when we start a drag in Internet Explorer 727 * @private 728 * @method _ieSelectFix 729 */ 730 _ieSelectFix: function() { 731 return false; 732 }, 733 /** 734 * We will hold a copy of the current "onselectstart" method on this property, and reset it after we are done using it. 735 * @private 736 * @property _ieSelectBack 737 */ 738 _ieSelectBack: null, 739 /** 740 * This method copies the onselectstart listner on the document to the _ieSelectFix property 741 * @private 742 * @method _fixIEMouseDown 743 */ 744 _fixIEMouseDown: function() { 745 if (Y.UA.ie) { 746 this._ieSelectBack = Y.config.doc.body.onselectstart; 747 Y.config.doc.body.onselectstart = this._ieSelectFix; 748 } 749 }, 750 /** 751 * This method copies the _ieSelectFix property back to the onselectstart listner on the document. 752 * @private 753 * @method _fixIEMouseUp 754 */ 755 _fixIEMouseUp: function() { 756 if (Y.UA.ie) { 757 Y.config.doc.body.onselectstart = this._ieSelectBack; 758 } 759 }, 760 /** 761 * Handler for the mousedown DOM event 762 * @private 763 * @method _handleMouseDownEvent 764 * @param {EventFacade} ev The Event 765 */ 766 _handleMouseDownEvent: function(ev) { 767 if (this.validClick(ev)) { 768 ev.preventDefault(); 769 } 770 this.fire(EV_MOUSE_DOWN, { ev: ev }); 771 }, 772 /** 773 * Handler for the mousedown DOM event 774 * @private 775 * @method _defMouseDownFn 776 * @param {EventFacade} e The Event 777 */ 778 _defMouseDownFn: function(e) { 779 var ev = e.ev; 780 781 this._dragThreshMet = false; 782 this._ev_md = ev; 783 784 if (this.get('primaryButtonOnly') && ev.button > 1) { 785 return false; 786 } 787 if (this.validClick(ev)) { 788 this._fixIEMouseDown(ev); 789 if (Drag.START_EVENT.indexOf('gesture') !== 0) { 790 //Only do these if it's not a gesture 791 if (this.get('haltDown')) { 792 ev.halt(); 793 } else { 794 ev.preventDefault(); 795 } 796 } 797 798 this._setStartPosition([ev.pageX, ev.pageY]); 799 800 DDM.activeDrag = this; 801 802 this._clickTimeout = Y.later(this.get('clickTimeThresh'), this, this._timeoutCheck); 803 } 804 this.fire(EV_AFTER_MOUSE_DOWN, { ev: ev }); 805 }, 806 /** 807 * Method first checks to see if we have handles, if so it validates the click 808 * against the handle. Then if it finds a valid handle, it checks it against 809 * the invalid handles list. Returns true if a good handle was used, false otherwise. 810 * @method validClick 811 * @param {EventFacade} ev The Event 812 * @return {Boolean} 813 */ 814 validClick: function(ev) { 815 var r = false, n = false, 816 tar = ev.target, 817 hTest = null, 818 els = null, 819 nlist = null, 820 set = false; 821 if (this._handles) { 822 Y.Object.each(this._handles, function(i, n) { 823 if (i instanceof Y.Node || i instanceof Y.NodeList) { 824 if (!r) { 825 nlist = i; 826 if (nlist instanceof Y.Node) { 827 nlist = new Y.NodeList(i._node); 828 } 829 nlist.each(function(nl) { 830 if (nl.contains(tar)) { 831 r = true; 832 } 833 }); 834 } 835 } else if (Y.Lang.isString(n)) { 836 //Am I this or am I inside this 837 if (tar.test(n + ', ' + n + ' *') && !hTest) { 838 hTest = n; 839 r = true; 840 } 841 } 842 }); 843 } else { 844 n = this.get(NODE); 845 if (n.contains(tar) || n.compareTo(tar)) { 846 r = true; 847 } 848 } 849 if (r) { 850 if (this._invalids) { 851 Y.Object.each(this._invalids, function(i, n) { 852 if (Y.Lang.isString(n)) { 853 //Am I this or am I inside this 854 if (tar.test(n + ', ' + n + ' *')) { 855 r = false; 856 } 857 } 858 }); 859 } 860 } 861 if (r) { 862 if (hTest) { 863 els = ev.currentTarget.all(hTest); 864 set = false; 865 els.each(function(n) { 866 if ((n.contains(tar) || n.compareTo(tar)) && !set) { 867 set = true; 868 this.set('activeHandle', n); 869 } 870 }, this); 871 } else { 872 this.set('activeHandle', this.get(NODE)); 873 } 874 } 875 return r; 876 }, 877 /** 878 * Sets the current position of the Element and calculates the offset 879 * @private 880 * @method _setStartPosition 881 * @param {Array} xy The XY coords to set the position to. 882 */ 883 _setStartPosition: function(xy) { 884 this.startXY = xy; 885 886 this.nodeXY = this.lastXY = this.realXY = this.get(NODE).getXY(); 887 888 if (this.get('offsetNode')) { 889 this.deltaXY = [(this.startXY[0] - this.nodeXY[0]), (this.startXY[1] - this.nodeXY[1])]; 890 } else { 891 this.deltaXY = [0, 0]; 892 } 893 }, 894 /** 895 * The method passed to setTimeout to determine if the clickTimeThreshold was met. 896 * @private 897 * @method _timeoutCheck 898 */ 899 _timeoutCheck: function() { 900 if (!this.get('lock') && !this._dragThreshMet && this._ev_md) { 901 this._fromTimeout = this._dragThreshMet = true; 902 this.start(); 903 this._alignNode([this._ev_md.pageX, this._ev_md.pageY], true); 904 } 905 }, 906 /** 907 * Remove a Selector added by addHandle 908 * @method removeHandle 909 * @param {String} str The selector for the handle to be removed. 910 * @chainable 911 */ 912 removeHandle: function(str) { 913 var key = str; 914 if (str instanceof Y.Node || str instanceof Y.NodeList) { 915 key = str._yuid; 916 } 917 if (this._handles[key]) { 918 delete this._handles[key]; 919 this.fire(EV_REMOVE_HANDLE, { handle: str }); 920 } 921 return this; 922 }, 923 /** 924 * Add a handle to a drag element. Drag only initiates when a mousedown happens on this element. 925 * @method addHandle 926 * @param {String} str The selector to test for a valid handle. Must be a child of the element. 927 * @chainable 928 */ 929 addHandle: function(str) { 930 if (!this._handles) { 931 this._handles = {}; 932 } 933 var key = str; 934 if (str instanceof Y.Node || str instanceof Y.NodeList) { 935 key = str._yuid; 936 } 937 this._handles[key] = str; 938 this.fire(EV_ADD_HANDLE, { handle: str }); 939 return this; 940 }, 941 /** 942 * Remove an invalid handle added by addInvalid 943 * @method removeInvalid 944 * @param {String} str The invalid handle to remove from the internal list. 945 * @chainable 946 */ 947 removeInvalid: function(str) { 948 if (this._invalids[str]) { 949 this._invalids[str] = null; 950 delete this._invalids[str]; 951 this.fire(EV_REMOVE_INVALID, { handle: str }); 952 } 953 return this; 954 }, 955 /** 956 * Add a selector string to test the handle against. If the test passes the drag operation will not continue. 957 * @method addInvalid 958 * @param {String} str The selector to test against to determine if this is an invalid drag handle. 959 * @chainable 960 */ 961 addInvalid: function(str) { 962 if (Y.Lang.isString(str)) { 963 this._invalids[str] = true; 964 this.fire(EV_ADD_INVALID, { handle: str }); 965 } 966 return this; 967 }, 968 /** 969 * Internal init handler 970 * @private 971 * @method initializer 972 */ 973 initializer: function() { 974 975 this.get(NODE).dd = this; 976 977 if (!this.get(NODE).get('id')) { 978 var id = Y.stamp(this.get(NODE)); 979 this.get(NODE).set('id', id); 980 } 981 982 this.actXY = []; 983 984 this._invalids = Y.clone(this._invalidsDefault, true); 985 986 this._createEvents(); 987 988 if (!this.get(DRAG_NODE)) { 989 this.set(DRAG_NODE, this.get(NODE)); 990 } 991 992 //Fix for #2528096 993 //Don't prep the DD instance until all plugins are loaded. 994 this.on('initializedChange', Y.bind(this._prep, this)); 995 996 //Shouldn't have to do this.. 997 this.set('groups', this.get('groups')); 998 }, 999 /** 1000 * Attach event listners and add classname 1001 * @private 1002 * @method _prep 1003 */ 1004 _prep: function() { 1005 this._dragThreshMet = false; 1006 var node = this.get(NODE); 1007 node.addClass(DDM.CSS_PREFIX + '-draggable'); 1008 node.on(Drag.START_EVENT, Y.bind(this._handleMouseDownEvent, this)); 1009 node.on('mouseup', Y.bind(this._handleMouseUp, this)); 1010 node.on('dragstart', Y.bind(this._fixDragStart, this)); 1011 }, 1012 /** 1013 * Detach event listeners and remove classname 1014 * @private 1015 * @method _unprep 1016 */ 1017 _unprep: function() { 1018 var node = this.get(NODE); 1019 node.removeClass(DDM.CSS_PREFIX + '-draggable'); 1020 node.detachAll('mouseup'); 1021 node.detachAll('dragstart'); 1022 node.detachAll(Drag.START_EVENT); 1023 this.mouseXY = []; 1024 this.deltaXY = [0,0]; 1025 this.startXY = []; 1026 this.nodeXY = []; 1027 this.lastXY = []; 1028 this.actXY = []; 1029 this.realXY = []; 1030 }, 1031 /** 1032 * Starts the drag operation 1033 * @method start 1034 * @chainable 1035 */ 1036 start: function() { 1037 if (!this.get('lock') && !this.get(DRAGGING)) { 1038 var node = this.get(NODE), ow, oh, xy; 1039 this._startTime = (new Date()).getTime(); 1040 1041 DDM._start(); 1042 node.addClass(DDM.CSS_PREFIX + '-dragging'); 1043 this.fire(EV_START, { 1044 pageX: this.nodeXY[0], 1045 pageY: this.nodeXY[1], 1046 startTime: this._startTime 1047 }); 1048 node = this.get(DRAG_NODE); 1049 xy = this.nodeXY; 1050 1051 ow = node.get(OFFSET_WIDTH); 1052 oh = node.get(OFFSET_HEIGHT); 1053 1054 if (this.get('startCentered')) { 1055 this._setStartPosition([xy[0] + (ow / 2), xy[1] + (oh / 2)]); 1056 } 1057 1058 1059 this.region = { 1060 '0': xy[0], 1061 '1': xy[1], 1062 area: 0, 1063 top: xy[1], 1064 right: xy[0] + ow, 1065 bottom: xy[1] + oh, 1066 left: xy[0] 1067 }; 1068 this.set(DRAGGING, true); 1069 } 1070 return this; 1071 }, 1072 /** 1073 * Ends the drag operation 1074 * @method end 1075 * @chainable 1076 */ 1077 end: function() { 1078 this._endTime = (new Date()).getTime(); 1079 if (this._clickTimeout) { 1080 this._clickTimeout.cancel(); 1081 } 1082 this._dragThreshMet = this._fromTimeout = false; 1083 1084 if (!this.get('lock') && this.get(DRAGGING)) { 1085 this.fire(EV_END, { 1086 pageX: this.lastXY[0], 1087 pageY: this.lastXY[1], 1088 startTime: this._startTime, 1089 endTime: this._endTime 1090 }); 1091 } 1092 this.get(NODE).removeClass(DDM.CSS_PREFIX + '-dragging'); 1093 this.set(DRAGGING, false); 1094 this.deltaXY = [0, 0]; 1095 1096 return this; 1097 }, 1098 /** 1099 * Handler for fixing the selection in IE 1100 * @private 1101 * @method _defEndFn 1102 */ 1103 _defEndFn: function() { 1104 this._fixIEMouseUp(); 1105 this._ev_md = null; 1106 }, 1107 /** 1108 * Handler for preventing the drag:end event. It will reset the node back to it's start position 1109 * @private 1110 * @method _prevEndFn 1111 */ 1112 _prevEndFn: function() { 1113 this._fixIEMouseUp(); 1114 //Bug #1852577 1115 this.get(DRAG_NODE).setXY(this.nodeXY); 1116 this._ev_md = null; 1117 this.region = null; 1118 }, 1119 /** 1120 * Calculates the offsets and set's the XY that the element will move to. 1121 * @private 1122 * @method _align 1123 * @param {Array} xy The xy coords to align with. 1124 */ 1125 _align: function(xy) { 1126 this.fire(EV_ALIGN, {pageX: xy[0], pageY: xy[1] }); 1127 }, 1128 /** 1129 * Calculates the offsets and set's the XY that the element will move to. 1130 * @private 1131 * @method _defAlignFn 1132 * @param {EventFacade} e The drag:align event. 1133 */ 1134 _defAlignFn: function(e) { 1135 this.actXY = [e.pageX - this.deltaXY[0], e.pageY - this.deltaXY[1]]; 1136 }, 1137 /** 1138 * This method performs the alignment before the element move. 1139 * @private 1140 * @method _alignNode 1141 * @param {Array} eXY The XY to move the element to, usually comes from the mousemove DOM event. 1142 */ 1143 _alignNode: function(eXY, scroll) { 1144 this._align(eXY); 1145 if (!scroll) { 1146 this._moveNode(); 1147 } 1148 }, 1149 /** 1150 * This method performs the actual element move. 1151 * @private 1152 * @method _moveNode 1153 */ 1154 _moveNode: function(scroll) { 1155 //if (!this.get(DRAGGING)) { 1156 // return; 1157 //} 1158 var diffXY = [], diffXY2 = [], startXY = this.nodeXY, xy = this.actXY; 1159 1160 diffXY[0] = (xy[0] - this.lastXY[0]); 1161 diffXY[1] = (xy[1] - this.lastXY[1]); 1162 1163 diffXY2[0] = (xy[0] - this.nodeXY[0]); 1164 diffXY2[1] = (xy[1] - this.nodeXY[1]); 1165 1166 1167 this.region = { 1168 '0': xy[0], 1169 '1': xy[1], 1170 area: 0, 1171 top: xy[1], 1172 right: xy[0] + this.get(DRAG_NODE).get(OFFSET_WIDTH), 1173 bottom: xy[1] + this.get(DRAG_NODE).get(OFFSET_HEIGHT), 1174 left: xy[0] 1175 }; 1176 1177 this.fire(EV_DRAG, { 1178 pageX: xy[0], 1179 pageY: xy[1], 1180 scroll: scroll, 1181 info: { 1182 start: startXY, 1183 xy: xy, 1184 delta: diffXY, 1185 offset: diffXY2 1186 } 1187 }); 1188 1189 this.lastXY = xy; 1190 }, 1191 /** 1192 * Default function for drag:drag. Fired from _moveNode. 1193 * @private 1194 * @method _defDragFn 1195 * @param {EventFacade} ev The drag:drag event 1196 */ 1197 _defDragFn: function(e) { 1198 if (this.get('move')) { 1199 if (e.scroll && e.scroll.node) { 1200 var domNode = e.scroll.node.getDOMNode(); 1201 //If it's the window 1202 if (domNode === Y.config.win) { 1203 domNode.scrollTo(e.scroll.left, e.scroll.top); 1204 } else { 1205 e.scroll.node.set('scrollTop', e.scroll.top); 1206 e.scroll.node.set('scrollLeft', e.scroll.left); 1207 } 1208 } 1209 this.get(DRAG_NODE).setXY([e.pageX, e.pageY]); 1210 this.realXY = [e.pageX, e.pageY]; 1211 } 1212 }, 1213 /** 1214 * Fired from DragDropMgr (DDM) on mousemove. 1215 * @private 1216 * @method _move 1217 * @param {EventFacade} ev The mousemove DOM event 1218 */ 1219 _move: function(ev) { 1220 if (this.get('lock')) { 1221 return false; 1222 } 1223 1224 this.mouseXY = [ev.pageX, ev.pageY]; 1225 if (!this._dragThreshMet) { 1226 var diffX = Math.abs(this.startXY[0] - ev.pageX), 1227 diffY = Math.abs(this.startXY[1] - ev.pageY); 1228 if (diffX > this.get('clickPixelThresh') || diffY > this.get('clickPixelThresh')) { 1229 this._dragThreshMet = true; 1230 this.start(); 1231 //This only happens on gestures to stop the page from scrolling 1232 if (ev && ev.preventDefault) { 1233 ev.preventDefault(); 1234 } 1235 this._alignNode([ev.pageX, ev.pageY]); 1236 } 1237 } else { 1238 if (this._clickTimeout) { 1239 this._clickTimeout.cancel(); 1240 } 1241 this._alignNode([ev.pageX, ev.pageY]); 1242 } 1243 }, 1244 /** 1245 * Method will forcefully stop a drag operation. For example calling this from inside an ESC keypress handler will stop this drag. 1246 * @method stopDrag 1247 * @chainable 1248 */ 1249 stopDrag: function() { 1250 if (this.get(DRAGGING)) { 1251 DDM._end(); 1252 } 1253 return this; 1254 }, 1255 /** 1256 * Lifecycle destructor, unreg the drag from the DDM and remove listeners 1257 * @private 1258 * @method destructor 1259 */ 1260 destructor: function() { 1261 this._unprep(); 1262 if (this.target) { 1263 this.target.destroy(); 1264 } 1265 DDM._unregDrag(this); 1266 } 1267 }); 1268 Y.namespace('DD'); 1269 Y.DD.Drag = Drag; 1270 1271 1272 1273 1274 }, '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 |