Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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