3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * This is a derivative of the similarly named class in the YUI Library.
17 * The original license:
18 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
19 * Code licensed under the BSD License:
20 * http://developer.yahoo.net/yui/license.txt
25 * @class Ext.dd.DragDropManager
26 * DragDropManager 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.
32 Ext.define('Ext.dd.DragDropManager', {
35 requires: ['Ext.util.Region'],
37 uses: ['Ext.tip.QuickTipManager'],
39 // shorter ClassName, to save bytes and use internally
40 alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
43 * Two dimensional Array of registered DragDrop objects. The first
44 * dimension is the DragDrop item group, the second the DragDrop
53 * Array of element ids defined as drag handles. Used to determine
54 * if the element that generated the mousedown event is actually the
55 * handle and not the html element itself.
63 * the DragDrop object that is currently being dragged
64 * @property {Ext.dd.DragDrop} dragCurrent
70 * the DragDrop object(s) that are being hovered over
71 * @property {Ext.dd.DragDrop[]} dragOvers
77 * the X distance between the cursor and the object being dragged
85 * the Y distance between the cursor and the object being dragged
93 * Flag to determine if we should prevent the default behavior of the
94 * events we define. By default this is true, but this can be set to
95 * false if you need the default behavior (not recommended)
96 * @property preventDefault
102 * Flag to determine if we should stop the propagation of the events
103 * we generate. This is true by default but you may want to set it to
104 * false if the html element contains other features that require the
106 * @property stopPropagation
109 stopPropagation: true,
112 * Internal flag that is set to true when drag and drop has been
114 * @property initialized
120 * All drag and drop can be disabled.
127 * Called the first time an element is registered.
132 this.initialized = true;
136 * In point mode, drag and drop interaction is defined by the
137 * location of the cursor during the drag/drop
144 * In intersect mode, drag and drop interaction is defined by the
145 * overlap of two or more drag and drop objects.
146 * @property INTERSECT
152 * The current drag and drop mode. Default: POINT
159 * Runs method on all drag and drop objects
163 _execOnAll: function(sMethod, args) {
164 for (var i in this.ids) {
165 for (var j in this.ids[i]) {
166 var oDD = this.ids[i][j];
167 if (! this.isTypeOfDD(oDD)) {
170 oDD[sMethod].apply(oDD, args);
176 * Drag and drop initialization. Sets up the global event handlers
180 _onLoad: function() {
184 var Event = Ext.EventManager;
185 Event.on(document, "mouseup", this.handleMouseUp, this, true);
186 Event.on(document, "mousemove", this.handleMouseMove, this, true);
187 Event.on(window, "unload", this._onUnload, this, true);
188 Event.on(window, "resize", this._onResize, this, true);
189 // Event.on(window, "mouseout", this._test);
194 * Reset constraints on all drag and drop objs
198 _onResize: function(e) {
199 this._execOnAll("resetConstraints", []);
203 * Lock all drag and drop functionality
206 lock: function() { this.locked = true; },
209 * Unlock all drag and drop functionality
212 unlock: function() { this.locked = false; },
215 * Is drag and drop locked?
217 * @return {Boolean} True if drag and drop is locked, false otherwise.
219 isLocked: function() { return this.locked; },
222 * Location cache that is set for all drag drop objects when a drag is
223 * initiated, cleared when the drag is finished.
224 * @property locationCache
230 * Set useCache to false if you want to force object the lookup of each
231 * drag and drop linked element constantly during a drag.
238 * The number of pixels that the mouse needs to move after the
239 * mousedown before the drag is initiated. Default=3;
240 * @property clickPixelThresh
246 * The number of milliseconds after the mousedown event to initiate the
247 * drag if we don't get a mouseup event. Default=350
248 * @property clickTimeThresh
251 clickTimeThresh: 350,
254 * Flag that indicates that either the drag pixel threshold or the
255 * mousdown time threshold has been met
256 * @property dragThreshMet
260 dragThreshMet: false,
263 * Timeout used for the click time threshold
264 * @property clickTimeout
271 * The X position of the mousedown event stored for later use when a
272 * drag threshold is met.
280 * The Y position of the mousedown event stored for later use when a
281 * drag threshold is met.
289 * Each DragDrop instance must be registered with the DragDropManager.
290 * This is executed in DragDrop.init()
291 * @method regDragDrop
292 * @param {Ext.dd.DragDrop} oDD the DragDrop object to register
293 * @param {String} sGroup the name of the group this element belongs to
295 regDragDrop: function(oDD, sGroup) {
296 if (!this.initialized) { this.init(); }
298 if (!this.ids[sGroup]) {
299 this.ids[sGroup] = {};
301 this.ids[sGroup][oDD.id] = oDD;
305 * Removes the supplied dd instance from the supplied group. Executed
306 * by DragDrop.removeFromGroup, so don't call this function directly.
307 * @method removeDDFromGroup
310 removeDDFromGroup: function(oDD, sGroup) {
311 if (!this.ids[sGroup]) {
312 this.ids[sGroup] = {};
315 var obj = this.ids[sGroup];
316 if (obj && obj[oDD.id]) {
322 * Unregisters a drag and drop item. This is executed in
323 * DragDrop.unreg, use that method instead of calling this directly.
327 _remove: function(oDD) {
328 for (var g in oDD.groups) {
329 if (g && this.ids[g] && this.ids[g][oDD.id]) {
330 delete this.ids[g][oDD.id];
333 delete this.handleIds[oDD.id];
337 * Each DragDrop handle element must be registered. This is done
338 * automatically when executing DragDrop.setHandleElId()
340 * @param {String} sDDId the DragDrop id this element is a handle for
341 * @param {String} sHandleId the id of the element that is the drag
344 regHandle: function(sDDId, sHandleId) {
345 if (!this.handleIds[sDDId]) {
346 this.handleIds[sDDId] = {};
348 this.handleIds[sDDId][sHandleId] = sHandleId;
352 * Utility function to determine if a given element has been
353 * registered as a drag drop item.
355 * @param {String} id the element id to check
356 * @return {Boolean} true if this element is a DragDrop item,
359 isDragDrop: function(id) {
360 return ( this.getDDById(id) ) ? true : false;
364 * Returns the drag and drop instances that are in all groups the
365 * passed in instance belongs to.
367 * @param {Ext.dd.DragDrop} p_oDD the obj to get related data for
368 * @param {Boolean} bTargetsOnly if true, only return targetable objs
369 * @return {Ext.dd.DragDrop[]} the related instances
371 getRelated: function(p_oDD, bTargetsOnly) {
373 for (var i in p_oDD.groups) {
374 for (var j in this.ids[i]) {
375 var dd = this.ids[i][j];
376 if (! this.isTypeOfDD(dd)) {
379 if (!bTargetsOnly || dd.isTarget) {
380 oDDs[oDDs.length] = dd;
389 * Returns true if the specified dd target is a legal target for
390 * the specifice drag obj
391 * @method isLegalTarget
392 * @param {Ext.dd.DragDrop} oDD the drag obj
393 * @param {Ext.dd.DragDrop} oTargetDD the target
394 * @return {Boolean} true if the target is a legal target for the
397 isLegalTarget: function (oDD, oTargetDD) {
398 var targets = this.getRelated(oDD, true);
399 for (var i=0, len=targets.length;i<len;++i) {
400 if (targets[i].id == oTargetDD.id) {
409 * My goal is to be able to transparently determine if an object is
410 * typeof DragDrop, and the exact subclass of DragDrop. typeof
411 * returns "object", oDD.constructor.toString() always returns
412 * "DragDrop" and not the name of the subclass. So for now it just
413 * evaluates a well-known variable in DragDrop.
415 * @param {Object} the object to evaluate
416 * @return {Boolean} true if typeof oDD = DragDrop
418 isTypeOfDD: function (oDD) {
419 return (oDD && oDD.__ygDragDrop);
423 * Utility function to determine if a given element has been
424 * registered as a drag drop handle for the given Drag Drop object.
426 * @param {String} id the element id to check
427 * @return {Boolean} true if this element is a DragDrop handle, false
430 isHandle: function(sDDId, sHandleId) {
431 return ( this.handleIds[sDDId] &&
432 this.handleIds[sDDId][sHandleId] );
436 * Returns the DragDrop instance for a given id
438 * @param {String} id the id of the DragDrop object
439 * @return {Ext.dd.DragDrop} the drag drop object, null if it is not found
441 getDDById: function(id) {
442 for (var i in this.ids) {
443 if (this.ids[i][id]) {
444 return this.ids[i][id];
451 * Fired after a registered DragDrop object gets the mousedown event.
452 * Sets up the events required to track the object being dragged
453 * @method handleMouseDown
454 * @param {Event} e the event
455 * @param {Ext.dd.DragDrop} oDD the DragDrop object being dragged
458 handleMouseDown: function(e, oDD) {
459 if(Ext.tip.QuickTipManager){
460 Ext.tip.QuickTipManager.ddDisable();
462 if(this.dragCurrent){
463 // the original browser mouseup wasn't handled (e.g. outside FF browser window)
464 // so clean up first to avoid breaking the next drag
465 this.handleMouseUp(e);
468 this.currentTarget = e.getTarget();
469 this.dragCurrent = oDD;
471 var el = oDD.getEl();
473 // track start position
474 this.startX = e.getPageX();
475 this.startY = e.getPageY();
477 this.deltaX = this.startX - el.offsetLeft;
478 this.deltaY = this.startY - el.offsetTop;
480 this.dragThreshMet = false;
482 this.clickTimeout = setTimeout(
484 var DDM = Ext.dd.DragDropManager;
485 DDM.startDrag(DDM.startX, DDM.startY);
487 this.clickTimeThresh );
491 * Fired when either the drag pixel threshol or the mousedown hold
492 * time threshold has been met.
494 * @param {Number} x the X position of the original mousedown
495 * @param {Number} y the Y position of the original mousedown
497 startDrag: function(x, y) {
498 clearTimeout(this.clickTimeout);
499 if (this.dragCurrent) {
500 this.dragCurrent.b4StartDrag(x, y);
501 this.dragCurrent.startDrag(x, y);
503 this.dragThreshMet = true;
507 * Internal function to handle the mouseup event. Will be invoked
508 * from the context of the document.
509 * @method handleMouseUp
510 * @param {Event} e the event
513 handleMouseUp: function(e) {
515 if(Ext.tip && Ext.tip.QuickTipManager){
516 Ext.tip.QuickTipManager.ddEnable();
518 if (! this.dragCurrent) {
522 clearTimeout(this.clickTimeout);
524 if (this.dragThreshMet) {
525 this.fireEvents(e, true);
535 * Utility to stop event propagation and event default, if these
536 * features are turned on.
538 * @param {Event} e the event as returned by this.getEvent()
540 stopEvent: function(e){
541 if(this.stopPropagation) {
545 if (this.preventDefault) {
551 * Internal function to clean up event handlers after the drag
552 * operation is complete
554 * @param {Event} e the event
557 stopDrag: function(e) {
558 // Fire the drag end event for the item that was dragged
559 if (this.dragCurrent) {
560 if (this.dragThreshMet) {
561 this.dragCurrent.b4EndDrag(e);
562 this.dragCurrent.endDrag(e);
565 this.dragCurrent.onMouseUp(e);
568 this.dragCurrent = null;
573 * Internal function to handle the mousemove event. Will be invoked
574 * from the context of the html element.
576 * @TODO figure out what we can do about mouse events lost when the
577 * user drags objects beyond the window boundary. Currently we can
578 * detect this in internet explorer by verifying that the mouse is
579 * down during the mousemove event. Firefox doesn't give us the
580 * button state on the mousemove event.
581 * @method handleMouseMove
582 * @param {Event} e the event
585 handleMouseMove: function(e) {
586 if (! this.dragCurrent) {
589 // var button = e.which || e.button;
591 // check for IE mouseup outside of page boundary
592 if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
594 return this.handleMouseUp(e);
597 if (!this.dragThreshMet) {
598 var diffX = Math.abs(this.startX - e.getPageX());
599 var diffY = Math.abs(this.startY - e.getPageY());
600 if (diffX > this.clickPixelThresh ||
601 diffY > this.clickPixelThresh) {
602 this.startDrag(this.startX, this.startY);
606 if (this.dragThreshMet) {
607 this.dragCurrent.b4Drag(e);
608 this.dragCurrent.onDrag(e);
609 if(!this.dragCurrent.moveOnly){
610 this.fireEvents(e, false);
620 * Iterates over all of the DragDrop elements to find ones we are
621 * hovering over or dropping on
623 * @param {Event} e the event
624 * @param {Boolean} isDrop is this a drop op or a mouseover op?
627 fireEvents: function(e, isDrop) {
628 var dc = this.dragCurrent;
630 // If the user did the mouse up outside of the window, we could
631 // get here even though we have ended the drag.
632 if (!dc || dc.isLocked()) {
636 var pt = e.getPoint();
638 // cache the previous dragOver array
646 // Check to see if the object(s) we were hovering over is no longer
647 // being hovered over so we can fire the onDragOut event
648 for (var i in this.dragOvers) {
650 var ddo = this.dragOvers[i];
652 if (! this.isTypeOfDD(ddo)) {
656 if (! this.isOverTarget(pt, ddo, this.mode)) {
661 delete this.dragOvers[i];
664 for (var sGroup in dc.groups) {
666 if ("string" != typeof sGroup) {
670 for (i in this.ids[sGroup]) {
671 var oDD = this.ids[sGroup][i];
672 if (! this.isTypeOfDD(oDD)) {
676 if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
677 if (this.isOverTarget(pt, oDD, this.mode)) {
678 // look for drop interactions
680 dropEvts.push( oDD );
681 // look for drag enter and drag over interactions
684 // initial drag over: dragEnter fires
685 if (!oldOvers[oDD.id]) {
686 enterEvts.push( oDD );
687 // subsequent drag overs: dragOver fires
689 overEvts.push( oDD );
692 this.dragOvers[oDD.id] = oDD;
700 if (outEvts.length) {
701 dc.b4DragOut(e, outEvts);
702 dc.onDragOut(e, outEvts);
705 if (enterEvts.length) {
706 dc.onDragEnter(e, enterEvts);
709 if (overEvts.length) {
710 dc.b4DragOver(e, overEvts);
711 dc.onDragOver(e, overEvts);
714 if (dropEvts.length) {
715 dc.b4DragDrop(e, dropEvts);
716 dc.onDragDrop(e, dropEvts);
720 // fire dragout events
722 for (i=0, len=outEvts.length; i<len; ++i) {
723 dc.b4DragOut(e, outEvts[i].id);
724 dc.onDragOut(e, outEvts[i].id);
728 for (i=0,len=enterEvts.length; i<len; ++i) {
729 // dc.b4DragEnter(e, oDD.id);
730 dc.onDragEnter(e, enterEvts[i].id);
734 for (i=0,len=overEvts.length; i<len; ++i) {
735 dc.b4DragOver(e, overEvts[i].id);
736 dc.onDragOver(e, overEvts[i].id);
740 for (i=0, len=dropEvts.length; i<len; ++i) {
741 dc.b4DragDrop(e, dropEvts[i].id);
742 dc.onDragDrop(e, dropEvts[i].id);
747 // notify about a drop that did not find a target
748 if (isDrop && !dropEvts.length) {
755 * Helper function for getting the best match from the list of drag
756 * and drop objects returned by the drag and drop events when we are
757 * in INTERSECT mode. It returns either the first object that the
758 * cursor is over, or the object that has the greatest overlap with
759 * the dragged element.
760 * @method getBestMatch
761 * @param {Ext.dd.DragDrop[]} dds The array of drag and drop objects
763 * @return {Ext.dd.DragDrop} The best single match
765 getBestMatch: function(dds) {
767 // Return null if the input is not what we expect
768 //if (!dds || !dds.length || dds.length == 0) {
770 // If there is only one item, it wins
771 //} else if (dds.length == 1) {
773 var len = dds.length;
778 // Loop through the targeted items
779 for (var i=0; i<len; ++i) {
781 // If the cursor is over the object, it wins. If the
782 // cursor is over multiple matches, the first one we come
784 if (dd.cursorIsOver) {
787 // Otherwise the object with the most overlap wins
790 winner.overlap.getArea() < dd.overlap.getArea()) {
801 * Refreshes the cache of the top-left and bottom-right points of the
802 * drag and drop objects in the specified group(s). This is in the
803 * format that is stored in the drag and drop instance, so typical
806 * Ext.dd.DragDropManager.refreshCache(ddinstance.groups);
810 * Ext.dd.DragDropManager.refreshCache({group1:true, group2:true});
812 * @TODO this really should be an indexed array. Alternatively this
813 * method could accept both.
814 * @method refreshCache
815 * @param {Object} groups an associative array of groups to refresh
817 refreshCache: function(groups) {
818 for (var sGroup in groups) {
819 if ("string" != typeof sGroup) {
822 for (var i in this.ids[sGroup]) {
823 var oDD = this.ids[sGroup][i];
825 if (this.isTypeOfDD(oDD)) {
826 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
827 var loc = this.getLocation(oDD);
829 this.locationCache[oDD.id] = loc;
831 delete this.locationCache[oDD.id];
832 // this will unregister the drag and drop object if
833 // the element is not in a usable state
842 * This checks to make sure an element exists and is in the DOM. The
843 * main purpose is to handle cases where innerHTML is used to remove
844 * drag and drop objects from the DOM. IE provides an 'unspecified
845 * error' when trying to access the offsetParent of such an element
847 * @param {HTMLElement} el the element to check
848 * @return {Boolean} true if the element looks usable
850 verifyEl: function(el) {
855 parent = el.offsetParent;
858 parent = el.offsetParent;
869 * Returns a Region object containing the drag and drop element's position
870 * and size, including the padding configured for it
871 * @method getLocation
872 * @param {Ext.dd.DragDrop} oDD the drag and drop object to get the location for.
873 * @return {Ext.util.Region} a Region object representing the total area
874 * the element occupies, including any padding
875 * the instance is configured for.
877 getLocation: function(oDD) {
878 if (! this.isTypeOfDD(oDD)) {
882 //delegate getLocation method to the
883 //drag and drop target.
885 return oDD.getRegion();
888 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
891 pos= Ext.Element.getXY(el);
899 x2 = x1 + el.offsetWidth;
901 y2 = y1 + el.offsetHeight;
903 t = y1 - oDD.padding[0];
904 r = x2 + oDD.padding[1];
905 b = y2 + oDD.padding[2];
906 l = x1 - oDD.padding[3];
908 return Ext.create('Ext.util.Region', t, r, b, l);
912 * Checks the cursor location to see if it over the target
913 * @method isOverTarget
914 * @param {Ext.util.Point} pt The point to evaluate
915 * @param {Ext.dd.DragDrop} oTarget the DragDrop object we are inspecting
916 * @return {Boolean} true if the mouse is over the target
919 isOverTarget: function(pt, oTarget, intersect) {
920 // use cache if available
921 var loc = this.locationCache[oTarget.id];
922 if (!loc || !this.useCache) {
923 loc = this.getLocation(oTarget);
924 this.locationCache[oTarget.id] = loc;
932 oTarget.cursorIsOver = loc.contains( pt );
934 // DragDrop is using this as a sanity check for the initial mousedown
935 // in this case we are done. In POINT mode, if the drag obj has no
936 // contraints, we are also done. Otherwise we need to evaluate the
937 // location of the target as related to the actual location of the
939 var dc = this.dragCurrent;
940 if (!dc || !dc.getTargetCoord ||
941 (!intersect && !dc.constrainX && !dc.constrainY)) {
942 return oTarget.cursorIsOver;
945 oTarget.overlap = null;
947 // Get the current location of the drag element, this is the
948 // location of the mouse event less the delta that represents
949 // where the original mousedown happened on the element. We
950 // need to consider constraints and ticks as well.
951 var pos = dc.getTargetCoord(pt.x, pt.y);
953 var el = dc.getDragEl();
954 var curRegion = Ext.create('Ext.util.Region', pos.y,
955 pos.x + el.offsetWidth,
956 pos.y + el.offsetHeight,
959 var overlap = curRegion.intersect(loc);
962 oTarget.overlap = overlap;
963 return (intersect) ? true : oTarget.cursorIsOver;
970 * unload event handler
974 _onUnload: function(e, me) {
975 Ext.dd.DragDropManager.unregAll();
979 * Cleans up the drag and drop events and objects.
983 unregAll: function() {
985 if (this.dragCurrent) {
987 this.dragCurrent = null;
990 this._execOnAll("unreg", []);
992 for (var i in this.elementCache) {
993 delete this.elementCache[i];
996 this.elementCache = {};
1001 * A cache of DOM elements
1002 * @property elementCache
1008 * Get the wrapper for the DOM element specified
1009 * @method getElWrapper
1010 * @param {String} id the id of the element to get
1011 * @return {Ext.dd.DragDropManager.ElementWrapper} the wrapped element
1013 * @deprecated This wrapper isn't that useful
1015 getElWrapper: function(id) {
1016 var oWrapper = this.elementCache[id];
1017 if (!oWrapper || !oWrapper.el) {
1018 oWrapper = this.elementCache[id] =
1019 new this.ElementWrapper(Ext.getDom(id));
1025 * Returns the actual DOM element
1026 * @method getElement
1027 * @param {String} id the id of the elment to get
1028 * @return {Object} The element
1029 * @deprecated use Ext.lib.Ext.getDom instead
1031 getElement: function(id) {
1032 return Ext.getDom(id);
1036 * Returns the style property for the DOM element (i.e.,
1037 * document.getElById(id).style)
1039 * @param {String} id the id of the elment to get
1040 * @return {Object} The style property of the element
1042 getCss: function(id) {
1043 var el = Ext.getDom(id);
1044 return (el) ? el.style : null;
1048 * @class Ext.dd.DragDropManager.ElementWrapper
1049 * Inner class for cached elements
1053 ElementWrapper: function(el) {
1058 this.el = el || null;
1063 this.id = this.el && el.id;
1065 * A reference to the style property
1068 this.css = this.el && el.style;
1071 // The DragDropManager class continues
1072 /** @class Ext.dd.DragDropManager */
1075 * Returns the X position of an html element
1076 * @param {HTMLElement} el the element for which to get the position
1077 * @return {Number} the X coordinate
1079 getPosX: function(el) {
1080 return Ext.Element.getX(el);
1084 * Returns the Y position of an html element
1085 * @param {HTMLElement} el the element for which to get the position
1086 * @return {Number} the Y coordinate
1088 getPosY: function(el) {
1089 return Ext.Element.getY(el);
1093 * Swap two nodes. In IE, we use the native method, for others we
1094 * emulate the IE behavior
1095 * @param {HTMLElement} n1 the first node to swap
1096 * @param {HTMLElement} n2 the other node to swap
1098 swapNode: function(n1, n2) {
1102 var p = n2.parentNode;
1103 var s = n2.nextSibling;
1106 p.insertBefore(n1, n2);
1107 } else if (n2 == n1.nextSibling) {
1108 p.insertBefore(n2, n1);
1110 n1.parentNode.replaceChild(n2, n1);
1111 p.insertBefore(n1, s);
1117 * Returns the current scroll position
1120 getScroll: function () {
1121 var doc = window.document,
1122 docEl = doc.documentElement,
1128 top = window.scrollYOffset;
1129 left = window.scrollXOffset;
1131 if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
1132 top = docEl.scrollTop;
1133 left = docEl.scrollLeft;
1135 top = body.scrollTop;
1136 left = body.scrollLeft;
1146 * Returns the specified element style property
1147 * @param {HTMLElement} el the element
1148 * @param {String} styleProp the style property
1149 * @return {String} The value of the style property
1151 getStyle: function(el, styleProp) {
1152 return Ext.fly(el).getStyle(styleProp);
1156 * Gets the scrollTop
1157 * @return {Number} the document's scrollTop
1159 getScrollTop: function () {
1160 return this.getScroll().top;
1164 * Gets the scrollLeft
1165 * @return {Number} the document's scrollTop
1167 getScrollLeft: function () {
1168 return this.getScroll().left;
1172 * Sets the x/y position of an element to the location of the
1174 * @param {HTMLElement} moveEl The element to move
1175 * @param {HTMLElement} targetEl The position reference element
1177 moveToEl: function (moveEl, targetEl) {
1178 var aCoord = Ext.Element.getXY(targetEl);
1179 Ext.Element.setXY(moveEl, aCoord);
1183 * Numeric array sort function
1186 * @returns {Number} positive, negative or 0
1188 numericSort: function(a, b) {
1194 * @property {Number} _timeoutCount
1200 * Trying to make the load order less important. Without this we get
1201 * an error if this file is loaded before the Event Utility.
1204 _addListeners: function() {
1208 if (this._timeoutCount > 2000) {
1210 setTimeout(this._addListeners, 10);
1211 if (document && document.body) {
1212 this._timeoutCount += 1;
1219 * Recursively searches the immediate parent and all child nodes for
1220 * the handle element in order to determine wheter or not it was
1222 * @param {HTMLElement} node the html element to inspect
1224 handleWasClicked: function(node, id) {
1225 if (this.isHandle(id, node.id)) {
1228 // check to see if this is a text node child of the one we want
1229 var p = node.parentNode;
1232 if (this.isHandle(id, p.id)) {
1243 this._addListeners();