4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
15 * These classes are derivatives of the similarly named classes in the YUI Library.
16 * The original license:
17 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
18 * Code licensed under the BSD License:
19 * http://developer.yahoo.net/yui/license.txt
24 var Event=Roo.EventManager;
28 * @class Roo.dd.DragDrop
29 * @extends Roo.util.Observable
30 * Defines the interface and base operation of items that that can be
31 * dragged or can be drop targets. It was designed to be extended, overriding
32 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
33 * Up to three html elements can be associated with a DragDrop instance:
35 * <li>linked element: the element that is passed into the constructor.
36 * This is the element which defines the boundaries for interaction with
37 * other DragDrop objects.</li>
38 * <li>handle element(s): The drag operation only occurs if the element that
39 * was clicked matches a handle element. By default this is the linked
40 * element, but there are times that you will want only a portion of the
41 * linked element to initiate the drag operation, and the setHandleElId()
42 * method provides a way to define this.</li>
43 * <li>drag element: this represents the element that would be moved along
44 * with the cursor during a drag operation. By default, this is the linked
45 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
46 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
49 * This class should not be instantiated until the onload event to ensure that
50 * the associated elements are available.
51 * The following would define a DragDrop obj that would interact with any
52 * other DragDrop obj in the "group1" group:
54 * dd = new Roo.dd.DragDrop("div1", "group1");
56 * Since none of the event handlers have been implemented, nothing would
57 * actually happen if you were to run the code above. Normally you would
58 * override this class or one of the default implementations, but you can
59 * also override the methods you want on an instance of the class...
61 * dd.onDragDrop = function(e, id) {
62 * alert("dd was dropped on " + id);
66 * @param {String} id of the element that is linked to this instance
67 * @param {String} sGroup the group of related DragDrop objects
68 * @param {object} config an object containing configurable attributes
69 * Valid properties for DragDrop:
70 * padding, isTarget, maintainOffset, primaryButtonOnly
72 Roo.dd.DragDrop = function(id, sGroup, config) {
74 this.init(id, sGroup, config);
79 Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
82 * The id of the element associated with this object. This is what we
83 * refer to as the "linked element" because the size and position of
84 * this element is used to determine when the drag and drop objects have
92 * Configuration attributes passed into the constructor
99 * The id of the element that will be dragged. By default this is same
100 * as the linked element , but could be changed to another element. Ex:
109 * the id of the element that initiates the drag operation. By default
110 * this is the linked element, but could be changed to be a child of this
111 * element. This lets us do things like only starting the drag when the
112 * header element within the linked html element is clicked.
113 * @property handleElId
120 * An associative array of HTML tags that will be ignored if clicked.
121 * @property invalidHandleTypes
122 * @type {string: string}
124 invalidHandleTypes: null,
127 * An associative array of ids for elements that will be ignored if clicked
128 * @property invalidHandleIds
129 * @type {string: string}
131 invalidHandleIds: null,
134 * An indexted array of css class names for elements that will be ignored
136 * @property invalidHandleClasses
139 invalidHandleClasses: null,
142 * The linked element's absolute X position at the time the drag was
144 * @property startPageX
151 * The linked element's absolute X position at the time the drag was
153 * @property startPageY
160 * The group defines a logical collection of DragDrop objects that are
161 * related. Instances only get events when interacting with other
162 * DragDrop object in the same group. This lets us define multiple
163 * groups using a single DragDrop subclass if we want.
165 * @type {string: string}
170 * Individual drag/drop instances can be locked. This will prevent
171 * onmousedown start drag.
182 lock: function() { this.locked = true; },
185 * Unlock this instace
188 unlock: function() { this.locked = false; },
191 * By default, all insances can be a drop target. This can be disabled by
192 * setting isTarget to false.
199 * The padding configured for this drag and drop object for calculating
200 * the drop zone intersection with this object.
207 * Cached reference to the linked element
214 * Internal typeof flag
215 * @property __ygDragDrop
221 * Set to true when horizontal contraints are applied
222 * @property constrainX
229 * Set to true when vertical contraints are applied
230 * @property constrainY
237 * The left constraint
245 * The right constraint
262 * The down constraint
270 * Maintain offsets when we resetconstraints. Set to true when you want
271 * the position of the element relative to its parent to stay the same
272 * when the page changes
274 * @property maintainOffset
277 maintainOffset: false,
280 * Array of pixel locations the element will snap to if we specified a
281 * horizontal graduation/interval. This array is generated automatically
282 * when you define a tick interval.
289 * Array of pixel locations the element will snap to if we specified a
290 * vertical graduation/interval. This array is generated automatically
291 * when you define a tick interval.
298 * By default the drag and drop instance will only respond to the primary
299 * button click (left button for a right-handed mouse). Set to true to
300 * allow drag and drop to start with any mouse click that is propogated
302 * @property primaryButtonOnly
305 primaryButtonOnly: true,
308 * The availabe property is false until the linked dom element is accessible.
309 * @property available
315 * By default, drags can only be initiated if the mousedown occurs in the
316 * region the linked element is. This is done in part to work around a
317 * bug in some browsers that mis-report the mousedown if the previous
318 * mouseup happened outside of the window. This property is set to true
319 * if outer handles are defined.
321 * @property hasOuterHandles
325 hasOuterHandles: false,
328 * Code that executes immediately before the startDrag event
329 * @method b4StartDrag
332 b4StartDrag: function(x, y) { },
335 * Abstract method called after a drag/drop object is clicked
336 * and the drag or mousedown time thresholds have beeen met.
338 * @param {int} X click location
339 * @param {int} Y click location
341 startDrag: function(x, y) { /* override this */ },
344 * Code that executes immediately before the onDrag event
348 b4Drag: function(e) { },
351 * Abstract method called during the onMouseMove event while dragging an
354 * @param {Event} e the mousemove event
356 onDrag: function(e) { /* override this */ },
359 * Abstract method called when this element fist begins hovering over
360 * another DragDrop obj
361 * @method onDragEnter
362 * @param {Event} e the mousemove event
363 * @param {String|DragDrop[]} id In POINT mode, the element
364 * id this is hovering over. In INTERSECT mode, an array of one or more
365 * dragdrop items being hovered over.
367 onDragEnter: function(e, id) { /* override this */ },
370 * Code that executes immediately before the onDragOver event
374 b4DragOver: function(e) { },
377 * Abstract method called when this element is hovering over another
380 * @param {Event} e the mousemove event
381 * @param {String|DragDrop[]} id In POINT mode, the element
382 * id this is hovering over. In INTERSECT mode, an array of dd items
383 * being hovered over.
385 onDragOver: function(e, id) { /* override this */ },
388 * Code that executes immediately before the onDragOut event
392 b4DragOut: function(e) { },
395 * Abstract method called when we are no longer hovering over an element
397 * @param {Event} e the mousemove event
398 * @param {String|DragDrop[]} id In POINT mode, the element
399 * id this was hovering over. In INTERSECT mode, an array of dd items
400 * that the mouse is no longer over.
402 onDragOut: function(e, id) { /* override this */ },
405 * Code that executes immediately before the onDragDrop event
409 b4DragDrop: function(e) { },
412 * Abstract method called when this item is dropped on another DragDrop
415 * @param {Event} e the mouseup event
416 * @param {String|DragDrop[]} id In POINT mode, the element
417 * id this was dropped on. In INTERSECT mode, an array of dd items this
420 onDragDrop: function(e, id) { /* override this */ },
423 * Abstract method called when this item is dropped on an area with no
425 * @method onInvalidDrop
426 * @param {Event} e the mouseup event
428 onInvalidDrop: function(e) { /* override this */ },
431 * Code that executes immediately before the endDrag event
435 b4EndDrag: function(e) { },
438 * Fired when we are done dragging the object
440 * @param {Event} e the mouseup event
442 endDrag: function(e) { /* override this */ },
445 * Code executed immediately before the onMouseDown event
446 * @method b4MouseDown
447 * @param {Event} e the mousedown event
450 b4MouseDown: function(e) { },
453 * Event handler that fires when a drag/drop obj gets a mousedown
454 * @method onMouseDown
455 * @param {Event} e the mousedown event
457 onMouseDown: function(e) { /* override this */ },
460 * Event handler that fires when a drag/drop obj gets a mouseup
462 * @param {Event} e the mouseup event
464 onMouseUp: function(e) { /* override this */ },
467 * Override the onAvailable method to do what is needed after the initial
468 * position was determined.
469 * @method onAvailable
471 onAvailable: function () {
475 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
478 defaultPadding : {left:0, right:0, top:0, bottom:0},
481 * Initializes the drag drop object's constraints to restrict movement to a certain element.
485 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
486 { dragElId: "existingProxyDiv" });
487 dd.startDrag = function(){
488 this.constrainTo("parent-id");
491 * Or you can initalize it using the {@link Roo.Element} object:
493 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
494 startDrag : function(){
495 this.constrainTo("parent-id");
499 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
500 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
501 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
502 * an object containing the sides to pad. For example: {right:10, bottom:10}
503 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
505 constrainTo : function(constrainTo, pad, inContent){
506 if(typeof pad == "number"){
507 pad = {left: pad, right:pad, top:pad, bottom:pad};
509 pad = pad || this.defaultPadding;
510 var b = Roo.get(this.getEl()).getBox();
511 var ce = Roo.get(constrainTo);
512 var s = ce.getScroll();
514 if(cd == document.body){
515 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
518 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
522 var topSpace = b.y - c.y;
523 var leftSpace = b.x - c.x;
525 this.resetConstraints();
526 this.setXConstraint(leftSpace - (pad.left||0), // left
527 c.width - leftSpace - b.width - (pad.right||0) //right
529 this.setYConstraint(topSpace - (pad.top||0), //top
530 c.height - topSpace - b.height - (pad.bottom||0) //bottom
535 * Returns a reference to the linked element
537 * @return {HTMLElement} the html element
541 this._domRef = Roo.getDom(this.id);
548 * Returns a reference to the actual element to drag. By default this is
549 * the same as the html element, but it can be assigned to another
550 * element. An example of this can be found in Roo.dd.DDProxy
552 * @return {HTMLElement} the html element
554 getDragEl: function() {
555 return Roo.getDom(this.dragElId);
559 * Sets up the DragDrop object. Must be called in the constructor of any
560 * Roo.dd.DragDrop subclass
562 * @param id the id of the linked element
563 * @param {String} sGroup the group of related items
564 * @param {object} config configuration attributes
566 init: function(id, sGroup, config) {
567 this.initTarget(id, sGroup, config);
568 Event.on(this.id, "mousedown", this.handleMouseDown, this);
569 // Event.on(this.id, "selectstart", Event.preventDefault);
573 * Initializes Targeting functionality only... the object does not
574 * get a mousedown handler.
576 * @param id the id of the linked element
577 * @param {String} sGroup the group of related items
578 * @param {object} config configuration attributes
580 initTarget: function(id, sGroup, config) {
582 // configuration attributes
583 this.config = config || {};
585 // create a local reference to the drag and drop manager
586 this.DDM = Roo.dd.DDM;
587 // initialize the groups array
590 // assume that we have an element reference instead of an id if the
591 // parameter is not a string
592 if (typeof id !== "string") {
599 // add to an interaction group
600 this.addToGroup((sGroup) ? sGroup : "default");
602 // We don't want to register this as the handle with the manager
603 // so we just set the id rather than calling the setter.
604 this.handleElId = id;
606 // the linked element is the element that gets dragged by default
607 this.setDragElId(id);
609 // by default, clicked anchors will not start drag operations.
610 this.invalidHandleTypes = { A: "A" };
611 this.invalidHandleIds = {};
612 this.invalidHandleClasses = [];
616 this.handleOnAvailable();
620 * Applies the configuration parameters that were passed into the constructor.
621 * This is supposed to happen at each level through the inheritance chain. So
622 * a DDProxy implentation will execute apply config on DDProxy, DD, and
623 * DragDrop in order to get all of the parameters that are available in
625 * @method applyConfig
627 applyConfig: function() {
629 // configurable properties:
630 // padding, isTarget, maintainOffset, primaryButtonOnly
631 this.padding = this.config.padding || [0, 0, 0, 0];
632 this.isTarget = (this.config.isTarget !== false);
633 this.maintainOffset = (this.config.maintainOffset);
634 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
639 * Executed when the linked element is available
640 * @method handleOnAvailable
643 handleOnAvailable: function() {
644 this.available = true;
645 this.resetConstraints();
650 * Configures the padding for the target zone in px. Effectively expands
651 * (or reduces) the virtual object size for targeting calculations.
652 * Supports css-style shorthand; if only one parameter is passed, all sides
653 * will have that padding, and if only two are passed, the top and bottom
654 * will have the first param, the left and right the second.
656 * @param {int} iTop Top pad
657 * @param {int} iRight Right pad
658 * @param {int} iBot Bot pad
659 * @param {int} iLeft Left pad
661 setPadding: function(iTop, iRight, iBot, iLeft) {
662 // this.padding = [iLeft, iRight, iTop, iBot];
663 if (!iRight && 0 !== iRight) {
664 this.padding = [iTop, iTop, iTop, iTop];
665 } else if (!iBot && 0 !== iBot) {
666 this.padding = [iTop, iRight, iTop, iRight];
668 this.padding = [iTop, iRight, iBot, iLeft];
673 * Stores the initial placement of the linked element.
674 * @method setInitialPosition
675 * @param {int} diffX the X offset, default 0
676 * @param {int} diffY the Y offset, default 0
678 setInitPosition: function(diffX, diffY) {
679 var el = this.getEl();
681 if (!this.DDM.verifyEl(el)) {
688 var p = Dom.getXY( el );
690 this.initPageX = p[0] - dx;
691 this.initPageY = p[1] - dy;
693 this.lastPageX = p[0];
694 this.lastPageY = p[1];
697 this.setStartPosition(p);
701 * Sets the start position of the element. This is set when the obj
702 * is initialized, the reset when a drag is started.
703 * @method setStartPosition
704 * @param pos current position (from previous lookup)
707 setStartPosition: function(pos) {
708 var p = pos || Dom.getXY( this.getEl() );
709 this.deltaSetXY = null;
711 this.startPageX = p[0];
712 this.startPageY = p[1];
716 * Add this instance to a group of related drag/drop objects. All
717 * instances belong to at least one group, and can belong to as many
720 * @param sGroup {string} the name of the group
722 addToGroup: function(sGroup) {
723 this.groups[sGroup] = true;
724 this.DDM.regDragDrop(this, sGroup);
728 * Remove's this instance from the supplied interaction group
729 * @method removeFromGroup
730 * @param {string} sGroup The group to drop
732 removeFromGroup: function(sGroup) {
733 if (this.groups[sGroup]) {
734 delete this.groups[sGroup];
737 this.DDM.removeDDFromGroup(this, sGroup);
741 * Allows you to specify that an element other than the linked element
742 * will be moved with the cursor during a drag
743 * @method setDragElId
744 * @param id {string} the id of the element that will be used to initiate the drag
746 setDragElId: function(id) {
751 * Allows you to specify a child of the linked element that should be
752 * used to initiate the drag operation. An example of this would be if
753 * you have a content div with text and links. Clicking anywhere in the
754 * content area would normally start the drag operation. Use this method
755 * to specify that an element inside of the content div is the element
756 * that starts the drag operation.
757 * @method setHandleElId
758 * @param id {string} the id of the element that will be used to
761 setHandleElId: function(id) {
762 if (typeof id !== "string") {
765 this.handleElId = id;
766 this.DDM.regHandle(this.id, id);
770 * Allows you to set an element outside of the linked element as a drag
772 * @method setOuterHandleElId
773 * @param id the id of the element that will be used to initiate the drag
775 setOuterHandleElId: function(id) {
776 if (typeof id !== "string") {
779 Event.on(id, "mousedown",
780 this.handleMouseDown, this);
781 this.setHandleElId(id);
783 this.hasOuterHandles = true;
787 * Remove all drag and drop hooks for this element
791 Event.un(this.id, "mousedown",
792 this.handleMouseDown);
794 this.DDM._remove(this);
797 destroy : function(){
802 * Returns true if this instance is locked, or the drag drop mgr is locked
803 * (meaning that all drag/drop is disabled on the page.)
805 * @return {boolean} true if this obj or all drag/drop is locked, else
808 isLocked: function() {
809 return (this.DDM.isLocked() || this.locked);
813 * Fired when this object is clicked
814 * @method handleMouseDown
816 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
819 handleMouseDown: function(e, oDD){
820 if (this.primaryButtonOnly && e.button != 0) {
824 if (this.isLocked()) {
828 this.DDM.refreshCache(this.groups);
830 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
831 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
833 if (this.clickValidator(e)) {
835 // set the initial element position
836 this.setStartPosition();
842 this.DDM.handleMouseDown(e, this);
844 this.DDM.stopEvent(e);
852 clickValidator: function(e) {
853 var target = e.getTarget();
854 return ( this.isValidHandleChild(target) &&
855 (this.id == this.handleElId ||
856 this.DDM.handleWasClicked(target, this.id)) );
860 * Allows you to specify a tag name that should not start a drag operation
861 * when clicked. This is designed to facilitate embedding links within a
862 * drag handle that do something other than start the drag.
863 * @method addInvalidHandleType
864 * @param {string} tagName the type of element to exclude
866 addInvalidHandleType: function(tagName) {
867 var type = tagName.toUpperCase();
868 this.invalidHandleTypes[type] = type;
872 * Lets you to specify an element id for a child of a drag handle
873 * that should not initiate a drag
874 * @method addInvalidHandleId
875 * @param {string} id the element id of the element you wish to ignore
877 addInvalidHandleId: function(id) {
878 if (typeof id !== "string") {
881 this.invalidHandleIds[id] = id;
885 * Lets you specify a css class of elements that will not initiate a drag
886 * @method addInvalidHandleClass
887 * @param {string} cssClass the class of the elements you wish to ignore
889 addInvalidHandleClass: function(cssClass) {
890 this.invalidHandleClasses.push(cssClass);
894 * Unsets an excluded tag name set by addInvalidHandleType
895 * @method removeInvalidHandleType
896 * @param {string} tagName the type of element to unexclude
898 removeInvalidHandleType: function(tagName) {
899 var type = tagName.toUpperCase();
900 // this.invalidHandleTypes[type] = null;
901 delete this.invalidHandleTypes[type];
905 * Unsets an invalid handle id
906 * @method removeInvalidHandleId
907 * @param {string} id the id of the element to re-enable
909 removeInvalidHandleId: function(id) {
910 if (typeof id !== "string") {
913 delete this.invalidHandleIds[id];
917 * Unsets an invalid css class
918 * @method removeInvalidHandleClass
919 * @param {string} cssClass the class of the element(s) you wish to
922 removeInvalidHandleClass: function(cssClass) {
923 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
924 if (this.invalidHandleClasses[i] == cssClass) {
925 delete this.invalidHandleClasses[i];
931 * Checks the tag exclusion list to see if this click should be ignored
932 * @method isValidHandleChild
933 * @param {HTMLElement} node the HTMLElement to evaluate
934 * @return {boolean} true if this is a valid tag type, false if not
936 isValidHandleChild: function(node) {
939 // var n = (node.nodeName == "#text") ? node.parentNode : node;
942 nodeName = node.nodeName.toUpperCase();
944 nodeName = node.nodeName;
946 valid = valid && !this.invalidHandleTypes[nodeName];
947 valid = valid && !this.invalidHandleIds[node.id];
949 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
950 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
959 * Create the array of horizontal tick marks if an interval was specified
960 * in setXConstraint().
964 setXTicks: function(iStartX, iTickSize) {
966 this.xTickSize = iTickSize;
970 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
972 this.xTicks[this.xTicks.length] = i;
977 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
979 this.xTicks[this.xTicks.length] = i;
984 this.xTicks.sort(this.DDM.numericSort) ;
988 * Create the array of vertical tick marks if an interval was specified in
993 setYTicks: function(iStartY, iTickSize) {
995 this.yTickSize = iTickSize;
999 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
1001 this.yTicks[this.yTicks.length] = i;
1006 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
1008 this.yTicks[this.yTicks.length] = i;
1013 this.yTicks.sort(this.DDM.numericSort) ;
1017 * By default, the element can be dragged any place on the screen. Use
1018 * this method to limit the horizontal travel of the element. Pass in
1019 * 0,0 for the parameters if you want to lock the drag to the y axis.
1020 * @method setXConstraint
1021 * @param {int} iLeft the number of pixels the element can move to the left
1022 * @param {int} iRight the number of pixels the element can move to the
1024 * @param {int} iTickSize optional parameter for specifying that the
1026 * should move iTickSize pixels at a time.
1028 setXConstraint: function(iLeft, iRight, iTickSize) {
1029 this.leftConstraint = iLeft;
1030 this.rightConstraint = iRight;
1032 this.minX = this.initPageX - iLeft;
1033 this.maxX = this.initPageX + iRight;
1034 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
1036 this.constrainX = true;
1040 * Clears any constraints applied to this instance. Also clears ticks
1041 * since they can't exist independent of a constraint at this time.
1042 * @method clearConstraints
1044 clearConstraints: function() {
1045 this.constrainX = false;
1046 this.constrainY = false;
1051 * Clears any tick interval defined for this instance
1052 * @method clearTicks
1054 clearTicks: function() {
1062 * By default, the element can be dragged any place on the screen. Set
1063 * this to limit the vertical travel of the element. Pass in 0,0 for the
1064 * parameters if you want to lock the drag to the x axis.
1065 * @method setYConstraint
1066 * @param {int} iUp the number of pixels the element can move up
1067 * @param {int} iDown the number of pixels the element can move down
1068 * @param {int} iTickSize optional parameter for specifying that the
1069 * element should move iTickSize pixels at a time.
1071 setYConstraint: function(iUp, iDown, iTickSize) {
1072 this.topConstraint = iUp;
1073 this.bottomConstraint = iDown;
1075 this.minY = this.initPageY - iUp;
1076 this.maxY = this.initPageY + iDown;
1077 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
1079 this.constrainY = true;
1084 * resetConstraints must be called if you manually reposition a dd element.
1085 * @method resetConstraints
1086 * @param {boolean} maintainOffset
1088 resetConstraints: function() {
1091 // Maintain offsets if necessary
1092 if (this.initPageX || this.initPageX === 0) {
1093 // figure out how much this thing has moved
1094 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
1095 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
1097 this.setInitPosition(dx, dy);
1099 // This is the first time we have detected the element's position
1101 this.setInitPosition();
1104 if (this.constrainX) {
1105 this.setXConstraint( this.leftConstraint,
1106 this.rightConstraint,
1110 if (this.constrainY) {
1111 this.setYConstraint( this.topConstraint,
1112 this.bottomConstraint,
1118 * Normally the drag element is moved pixel by pixel, but we can specify
1119 * that it move a number of pixels at a time. This method resolves the
1120 * location when we have it set up like this.
1122 * @param {int} val where we want to place the object
1123 * @param {int[]} tickArray sorted array of valid points
1124 * @return {int} the closest tick
1127 getTick: function(val, tickArray) {
1130 // If tick interval is not defined, it is effectively 1 pixel,
1131 // so we return the value passed to us.
1133 } else if (tickArray[0] >= val) {
1134 // The value is lower than the first tick, so we return the first
1136 return tickArray[0];
1138 for (var i=0, len=tickArray.length; i<len; ++i) {
1140 if (tickArray[next] && tickArray[next] >= val) {
1141 var diff1 = val - tickArray[i];
1142 var diff2 = tickArray[next] - val;
1143 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
1147 // The value is larger than the last tick, so we return the last
1149 return tickArray[tickArray.length - 1];
1156 * @return {string} string representation of the dd obj
1158 toString: function() {
1159 return ("DragDrop " + this.id);
1167 * Ext JS Library 1.1.1
1168 * Copyright(c) 2006-2007, Ext JS, LLC.
1170 * Originally Released Under LGPL - original licence link has changed is not relivant.
1173 * <script type="text/javascript">
1178 * The drag and drop utility provides a framework for building drag and drop
1179 * applications. In addition to enabling drag and drop for specific elements,
1180 * the drag and drop elements are tracked by the manager class, and the
1181 * interactions between the various elements are tracked during the drag and
1182 * the implementing code is notified about these important moments.
1185 // Only load the library once. Rewriting the manager class would orphan
1186 // existing drag and drop instances.
1187 if (!Roo.dd.DragDropMgr) {
1190 * @class Roo.dd.DragDropMgr
1191 * DragDropMgr is a singleton that tracks the element interaction for
1192 * all DragDrop items in the window. Generally, you will not call
1193 * this class directly, but it does have helper methods that could
1194 * be useful in your DragDrop implementations.
1197 Roo.dd.DragDropMgr = function() {
1199 var Event = Roo.EventManager;
1204 * Two dimensional Array of registered DragDrop objects. The first
1205 * dimension is the DragDrop item group, the second the DragDrop
1208 * @type {string: string}
1215 * Array of element ids defined as drag handles. Used to determine
1216 * if the element that generated the mousedown event is actually the
1217 * handle and not the html element itself.
1218 * @property handleIds
1219 * @type {string: string}
1226 * the DragDrop object that is currently being dragged
1227 * @property dragCurrent
1235 * the DragDrop object(s) that are being hovered over
1236 * @property dragOvers
1244 * the X distance between the cursor and the object being dragged
1253 * the Y distance between the cursor and the object being dragged
1262 * Flag to determine if we should prevent the default behavior of the
1263 * events we define. By default this is true, but this can be set to
1264 * false if you need the default behavior (not recommended)
1265 * @property preventDefault
1269 preventDefault: true,
1272 * Flag to determine if we should stop the propagation of the events
1273 * we generate. This is true by default but you may want to set it to
1274 * false if the html element contains other features that require the
1276 * @property stopPropagation
1280 stopPropagation: true,
1283 * Internal flag that is set to true when drag and drop has been
1285 * @property initialized
1292 * All drag and drop can be disabled.
1300 * Called the first time an element is registered.
1306 this.initialized = true;
1310 * In point mode, drag and drop interaction is defined by the
1311 * location of the cursor during the drag/drop
1319 * In intersect mode, drag and drop interactio nis defined by the
1320 * overlap of two or more drag and drop objects.
1321 * @property INTERSECT
1328 * The current drag and drop mode. Default: POINT
1336 * Runs method on all drag and drop objects
1337 * @method _execOnAll
1341 _execOnAll: function(sMethod, args) {
1342 for (var i in this.ids) {
1343 for (var j in this.ids[i]) {
1344 var oDD = this.ids[i][j];
1345 if (! this.isTypeOfDD(oDD)) {
1348 oDD[sMethod].apply(oDD, args);
1354 * Drag and drop initialization. Sets up the global event handlers
1359 _onLoad: function() {
1364 Event.on(document, "mouseup", this.handleMouseUp, this, true);
1365 Event.on(document, "mousemove", this.handleMouseMove, this, true);
1366 Event.on(window, "unload", this._onUnload, this, true);
1367 Event.on(window, "resize", this._onResize, this, true);
1368 // Event.on(window, "mouseout", this._test);
1373 * Reset constraints on all drag and drop objs
1378 _onResize: function(e) {
1379 this._execOnAll("resetConstraints", []);
1383 * Lock all drag and drop functionality
1387 lock: function() { this.locked = true; },
1390 * Unlock all drag and drop functionality
1394 unlock: function() { this.locked = false; },
1397 * Is drag and drop locked?
1399 * @return {boolean} True if drag and drop is locked, false otherwise.
1402 isLocked: function() { return this.locked; },
1405 * Location cache that is set for all drag drop objects when a drag is
1406 * initiated, cleared when the drag is finished.
1407 * @property locationCache
1414 * Set useCache to false if you want to force object the lookup of each
1415 * drag and drop linked element constantly during a drag.
1416 * @property useCache
1423 * The number of pixels that the mouse needs to move after the
1424 * mousedown before the drag is initiated. Default=3;
1425 * @property clickPixelThresh
1429 clickPixelThresh: 3,
1432 * The number of milliseconds after the mousedown event to initiate the
1433 * drag if we don't get a mouseup event. Default=1000
1434 * @property clickTimeThresh
1438 clickTimeThresh: 350,
1441 * Flag that indicates that either the drag pixel threshold or the
1442 * mousdown time threshold has been met
1443 * @property dragThreshMet
1448 dragThreshMet: false,
1451 * Timeout used for the click time threshold
1452 * @property clickTimeout
1460 * The X position of the mousedown event stored for later use when a
1461 * drag threshold is met.
1470 * The Y position of the mousedown event stored for later use when a
1471 * drag threshold is met.
1480 * Each DragDrop instance must be registered with the DragDropMgr.
1481 * This is executed in DragDrop.init()
1482 * @method regDragDrop
1483 * @param {DragDrop} oDD the DragDrop object to register
1484 * @param {String} sGroup the name of the group this element belongs to
1487 regDragDrop: function(oDD, sGroup) {
1488 if (!this.initialized) { this.init(); }
1490 if (!this.ids[sGroup]) {
1491 this.ids[sGroup] = {};
1493 this.ids[sGroup][oDD.id] = oDD;
1497 * Removes the supplied dd instance from the supplied group. Executed
1498 * by DragDrop.removeFromGroup, so don't call this function directly.
1499 * @method removeDDFromGroup
1503 removeDDFromGroup: function(oDD, sGroup) {
1504 if (!this.ids[sGroup]) {
1505 this.ids[sGroup] = {};
1508 var obj = this.ids[sGroup];
1509 if (obj && obj[oDD.id]) {
1515 * Unregisters a drag and drop item. This is executed in
1516 * DragDrop.unreg, use that method instead of calling this directly.
1521 _remove: function(oDD) {
1522 for (var g in oDD.groups) {
1523 if (g && this.ids[g][oDD.id]) {
1524 delete this.ids[g][oDD.id];
1527 delete this.handleIds[oDD.id];
1531 * Each DragDrop handle element must be registered. This is done
1532 * automatically when executing DragDrop.setHandleElId()
1534 * @param {String} sDDId the DragDrop id this element is a handle for
1535 * @param {String} sHandleId the id of the element that is the drag
1539 regHandle: function(sDDId, sHandleId) {
1540 if (!this.handleIds[sDDId]) {
1541 this.handleIds[sDDId] = {};
1543 this.handleIds[sDDId][sHandleId] = sHandleId;
1547 * Utility function to determine if a given element has been
1548 * registered as a drag drop item.
1549 * @method isDragDrop
1550 * @param {String} id the element id to check
1551 * @return {boolean} true if this element is a DragDrop item,
1555 isDragDrop: function(id) {
1556 return ( this.getDDById(id) ) ? true : false;
1560 * Returns the drag and drop instances that are in all groups the
1561 * passed in instance belongs to.
1562 * @method getRelated
1563 * @param {DragDrop} p_oDD the obj to get related data for
1564 * @param {boolean} bTargetsOnly if true, only return targetable objs
1565 * @return {DragDrop[]} the related instances
1568 getRelated: function(p_oDD, bTargetsOnly) {
1570 for (var i in p_oDD.groups) {
1571 for (j in this.ids[i]) {
1572 var dd = this.ids[i][j];
1573 if (! this.isTypeOfDD(dd)) {
1576 if (!bTargetsOnly || dd.isTarget) {
1577 oDDs[oDDs.length] = dd;
1586 * Returns true if the specified dd target is a legal target for
1587 * the specifice drag obj
1588 * @method isLegalTarget
1589 * @param {DragDrop} the drag obj
1590 * @param {DragDrop} the target
1591 * @return {boolean} true if the target is a legal target for the
1595 isLegalTarget: function (oDD, oTargetDD) {
1596 var targets = this.getRelated(oDD, true);
1597 for (var i=0, len=targets.length;i<len;++i) {
1598 if (targets[i].id == oTargetDD.id) {
1607 * My goal is to be able to transparently determine if an object is
1608 * typeof DragDrop, and the exact subclass of DragDrop. typeof
1609 * returns "object", oDD.constructor.toString() always returns
1610 * "DragDrop" and not the name of the subclass. So for now it just
1611 * evaluates a well-known variable in DragDrop.
1612 * @method isTypeOfDD
1613 * @param {Object} the object to evaluate
1614 * @return {boolean} true if typeof oDD = DragDrop
1617 isTypeOfDD: function (oDD) {
1618 return (oDD && oDD.__ygDragDrop);
1622 * Utility function to determine if a given element has been
1623 * registered as a drag drop handle for the given Drag Drop object.
1625 * @param {String} id the element id to check
1626 * @return {boolean} true if this element is a DragDrop handle, false
1630 isHandle: function(sDDId, sHandleId) {
1631 return ( this.handleIds[sDDId] &&
1632 this.handleIds[sDDId][sHandleId] );
1636 * Returns the DragDrop instance for a given id
1638 * @param {String} id the id of the DragDrop object
1639 * @return {DragDrop} the drag drop object, null if it is not found
1642 getDDById: function(id) {
1643 for (var i in this.ids) {
1644 if (this.ids[i][id]) {
1645 return this.ids[i][id];
1652 * Fired after a registered DragDrop object gets the mousedown event.
1653 * Sets up the events required to track the object being dragged
1654 * @method handleMouseDown
1655 * @param {Event} e the event
1656 * @param oDD the DragDrop object being dragged
1660 handleMouseDown: function(e, oDD) {
1662 Roo.QuickTips.disable();
1664 this.currentTarget = e.getTarget();
1666 this.dragCurrent = oDD;
1668 var el = oDD.getEl();
1670 // track start position
1671 this.startX = e.getPageX();
1672 this.startY = e.getPageY();
1674 this.deltaX = this.startX - el.offsetLeft;
1675 this.deltaY = this.startY - el.offsetTop;
1677 this.dragThreshMet = false;
1679 this.clickTimeout = setTimeout(
1681 var DDM = Roo.dd.DDM;
1682 DDM.startDrag(DDM.startX, DDM.startY);
1684 this.clickTimeThresh );
1688 * Fired when either the drag pixel threshol or the mousedown hold
1689 * time threshold has been met.
1691 * @param x {int} the X position of the original mousedown
1692 * @param y {int} the Y position of the original mousedown
1695 startDrag: function(x, y) {
1696 clearTimeout(this.clickTimeout);
1697 if (this.dragCurrent) {
1698 this.dragCurrent.b4StartDrag(x, y);
1699 this.dragCurrent.startDrag(x, y);
1701 this.dragThreshMet = true;
1705 * Internal function to handle the mouseup event. Will be invoked
1706 * from the context of the document.
1707 * @method handleMouseUp
1708 * @param {Event} e the event
1712 handleMouseUp: function(e) {
1715 Roo.QuickTips.enable();
1717 if (! this.dragCurrent) {
1721 clearTimeout(this.clickTimeout);
1723 if (this.dragThreshMet) {
1724 this.fireEvents(e, true);
1734 * Utility to stop event propagation and event default, if these
1735 * features are turned on.
1737 * @param {Event} e the event as returned by this.getEvent()
1740 stopEvent: function(e){
1741 if(this.stopPropagation) {
1742 e.stopPropagation();
1745 if (this.preventDefault) {
1751 * Internal function to clean up event handlers after the drag
1752 * operation is complete
1754 * @param {Event} e the event
1758 stopDrag: function(e) {
1759 // Fire the drag end event for the item that was dragged
1760 if (this.dragCurrent) {
1761 if (this.dragThreshMet) {
1762 this.dragCurrent.b4EndDrag(e);
1763 this.dragCurrent.endDrag(e);
1766 this.dragCurrent.onMouseUp(e);
1769 this.dragCurrent = null;
1770 this.dragOvers = {};
1774 * Internal function to handle the mousemove event. Will be invoked
1775 * from the context of the html element.
1777 * @TODO figure out what we can do about mouse events lost when the
1778 * user drags objects beyond the window boundary. Currently we can
1779 * detect this in internet explorer by verifying that the mouse is
1780 * down during the mousemove event. Firefox doesn't give us the
1781 * button state on the mousemove event.
1782 * @method handleMouseMove
1783 * @param {Event} e the event
1787 handleMouseMove: function(e) {
1788 if (! this.dragCurrent) {
1792 // var button = e.which || e.button;
1794 // check for IE mouseup outside of page boundary
1795 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
1797 return this.handleMouseUp(e);
1800 if (!this.dragThreshMet) {
1801 var diffX = Math.abs(this.startX - e.getPageX());
1802 var diffY = Math.abs(this.startY - e.getPageY());
1803 if (diffX > this.clickPixelThresh ||
1804 diffY > this.clickPixelThresh) {
1805 this.startDrag(this.startX, this.startY);
1809 if (this.dragThreshMet) {
1810 this.dragCurrent.b4Drag(e);
1811 this.dragCurrent.onDrag(e);
1812 if(!this.dragCurrent.moveOnly){
1813 this.fireEvents(e, false);
1823 * Iterates over all of the DragDrop elements to find ones we are
1824 * hovering over or dropping on
1825 * @method fireEvents
1826 * @param {Event} e the event
1827 * @param {boolean} isDrop is this a drop op or a mouseover op?
1831 fireEvents: function(e, isDrop) {
1832 var dc = this.dragCurrent;
1834 // If the user did the mouse up outside of the window, we could
1835 // get here even though we have ended the drag.
1836 if (!dc || dc.isLocked()) {
1840 var pt = e.getPoint();
1842 // cache the previous dragOver array
1850 // Check to see if the object(s) we were hovering over is no longer
1851 // being hovered over so we can fire the onDragOut event
1852 for (var i in this.dragOvers) {
1854 var ddo = this.dragOvers[i];
1856 if (! this.isTypeOfDD(ddo)) {
1860 if (! this.isOverTarget(pt, ddo, this.mode)) {
1861 outEvts.push( ddo );
1865 delete this.dragOvers[i];
1868 for (var sGroup in dc.groups) {
1870 if ("string" != typeof sGroup) {
1874 for (i in this.ids[sGroup]) {
1875 var oDD = this.ids[sGroup][i];
1876 if (! this.isTypeOfDD(oDD)) {
1880 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
1881 if (this.isOverTarget(pt, oDD, this.mode)) {
1882 // look for drop interactions
1884 dropEvts.push( oDD );
1885 // look for drag enter and drag over interactions
1888 // initial drag over: dragEnter fires
1889 if (!oldOvers[oDD.id]) {
1890 enterEvts.push( oDD );
1891 // subsequent drag overs: dragOver fires
1893 overEvts.push( oDD );
1896 this.dragOvers[oDD.id] = oDD;
1904 if (outEvts.length) {
1905 dc.b4DragOut(e, outEvts);
1906 dc.onDragOut(e, outEvts);
1909 if (enterEvts.length) {
1910 dc.onDragEnter(e, enterEvts);
1913 if (overEvts.length) {
1914 dc.b4DragOver(e, overEvts);
1915 dc.onDragOver(e, overEvts);
1918 if (dropEvts.length) {
1919 dc.b4DragDrop(e, dropEvts);
1920 dc.onDragDrop(e, dropEvts);
1924 // fire dragout events
1926 for (i=0, len=outEvts.length; i<len; ++i) {
1927 dc.b4DragOut(e, outEvts[i].id);
1928 dc.onDragOut(e, outEvts[i].id);
1931 // fire enter events
1932 for (i=0,len=enterEvts.length; i<len; ++i) {
1933 // dc.b4DragEnter(e, oDD.id);
1934 dc.onDragEnter(e, enterEvts[i].id);
1938 for (i=0,len=overEvts.length; i<len; ++i) {
1939 dc.b4DragOver(e, overEvts[i].id);
1940 dc.onDragOver(e, overEvts[i].id);
1944 for (i=0, len=dropEvts.length; i<len; ++i) {
1945 dc.b4DragDrop(e, dropEvts[i].id);
1946 dc.onDragDrop(e, dropEvts[i].id);
1951 // notify about a drop that did not find a target
1952 if (isDrop && !dropEvts.length) {
1953 dc.onInvalidDrop(e);
1959 * Helper function for getting the best match from the list of drag
1960 * and drop objects returned by the drag and drop events when we are
1961 * in INTERSECT mode. It returns either the first object that the
1962 * cursor is over, or the object that has the greatest overlap with
1963 * the dragged element.
1964 * @method getBestMatch
1965 * @param {DragDrop[]} dds The array of drag and drop objects
1967 * @return {DragDrop} The best single match
1970 getBestMatch: function(dds) {
1972 // Return null if the input is not what we expect
1973 //if (!dds || !dds.length || dds.length == 0) {
1975 // If there is only one item, it wins
1976 //} else if (dds.length == 1) {
1978 var len = dds.length;
1983 // Loop through the targeted items
1984 for (var i=0; i<len; ++i) {
1986 // If the cursor is over the object, it wins. If the
1987 // cursor is over multiple matches, the first one we come
1989 if (dd.cursorIsOver) {
1992 // Otherwise the object with the most overlap wins
1995 winner.overlap.getArea() < dd.overlap.getArea()) {
2006 * Refreshes the cache of the top-left and bottom-right points of the
2007 * drag and drop objects in the specified group(s). This is in the
2008 * format that is stored in the drag and drop instance, so typical
2011 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
2015 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
2017 * @TODO this really should be an indexed array. Alternatively this
2018 * method could accept both.
2019 * @method refreshCache
2020 * @param {Object} groups an associative array of groups to refresh
2023 refreshCache: function(groups) {
2024 for (var sGroup in groups) {
2025 if ("string" != typeof sGroup) {
2028 for (var i in this.ids[sGroup]) {
2029 var oDD = this.ids[sGroup][i];
2031 if (this.isTypeOfDD(oDD)) {
2032 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
2033 var loc = this.getLocation(oDD);
2035 this.locationCache[oDD.id] = loc;
2037 delete this.locationCache[oDD.id];
2038 // this will unregister the drag and drop object if
2039 // the element is not in a usable state
2048 * This checks to make sure an element exists and is in the DOM. The
2049 * main purpose is to handle cases where innerHTML is used to remove
2050 * drag and drop objects from the DOM. IE provides an 'unspecified
2051 * error' when trying to access the offsetParent of such an element
2053 * @param {HTMLElement} el the element to check
2054 * @return {boolean} true if the element looks usable
2057 verifyEl: function(el) {
2062 parent = el.offsetParent;
2065 parent = el.offsetParent;
2076 * Returns a Region object containing the drag and drop element's position
2077 * and size, including the padding configured for it
2078 * @method getLocation
2079 * @param {DragDrop} oDD the drag and drop object to get the
2081 * @return {Roo.lib.Region} a Region object representing the total area
2082 * the element occupies, including any padding
2083 * the instance is configured for.
2086 getLocation: function(oDD) {
2087 if (! this.isTypeOfDD(oDD)) {
2091 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
2094 pos= Roo.lib.Dom.getXY(el);
2102 x2 = x1 + el.offsetWidth;
2104 y2 = y1 + el.offsetHeight;
2106 t = y1 - oDD.padding[0];
2107 r = x2 + oDD.padding[1];
2108 b = y2 + oDD.padding[2];
2109 l = x1 - oDD.padding[3];
2111 return new Roo.lib.Region( t, r, b, l );
2115 * Checks the cursor location to see if it over the target
2116 * @method isOverTarget
2117 * @param {Roo.lib.Point} pt The point to evaluate
2118 * @param {DragDrop} oTarget the DragDrop object we are inspecting
2119 * @return {boolean} true if the mouse is over the target
2123 isOverTarget: function(pt, oTarget, intersect) {
2124 // use cache if available
2125 var loc = this.locationCache[oTarget.id];
2126 if (!loc || !this.useCache) {
2127 loc = this.getLocation(oTarget);
2128 this.locationCache[oTarget.id] = loc;
2136 oTarget.cursorIsOver = loc.contains( pt );
2138 // DragDrop is using this as a sanity check for the initial mousedown
2139 // in this case we are done. In POINT mode, if the drag obj has no
2140 // contraints, we are also done. Otherwise we need to evaluate the
2141 // location of the target as related to the actual location of the
2143 var dc = this.dragCurrent;
2144 if (!dc || !dc.getTargetCoord ||
2145 (!intersect && !dc.constrainX && !dc.constrainY)) {
2146 return oTarget.cursorIsOver;
2149 oTarget.overlap = null;
2151 // Get the current location of the drag element, this is the
2152 // location of the mouse event less the delta that represents
2153 // where the original mousedown happened on the element. We
2154 // need to consider constraints and ticks as well.
2155 var pos = dc.getTargetCoord(pt.x, pt.y);
2157 var el = dc.getDragEl();
2158 var curRegion = new Roo.lib.Region( pos.y,
2159 pos.x + el.offsetWidth,
2160 pos.y + el.offsetHeight,
2163 var overlap = curRegion.intersect(loc);
2166 oTarget.overlap = overlap;
2167 return (intersect) ? true : oTarget.cursorIsOver;
2174 * unload event handler
2179 _onUnload: function(e, me) {
2180 Roo.dd.DragDropMgr.unregAll();
2184 * Cleans up the drag and drop events and objects.
2189 unregAll: function() {
2191 if (this.dragCurrent) {
2193 this.dragCurrent = null;
2196 this._execOnAll("unreg", []);
2198 for (i in this.elementCache) {
2199 delete this.elementCache[i];
2202 this.elementCache = {};
2207 * A cache of DOM elements
2208 * @property elementCache
2215 * Get the wrapper for the DOM element specified
2216 * @method getElWrapper
2217 * @param {String} id the id of the element to get
2218 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
2220 * @deprecated This wrapper isn't that useful
2223 getElWrapper: function(id) {
2224 var oWrapper = this.elementCache[id];
2225 if (!oWrapper || !oWrapper.el) {
2226 oWrapper = this.elementCache[id] =
2227 new this.ElementWrapper(Roo.getDom(id));
2233 * Returns the actual DOM element
2234 * @method getElement
2235 * @param {String} id the id of the elment to get
2236 * @return {Object} The element
2237 * @deprecated use Roo.getDom instead
2240 getElement: function(id) {
2241 return Roo.getDom(id);
2245 * Returns the style property for the DOM element (i.e.,
2246 * document.getElById(id).style)
2248 * @param {String} id the id of the elment to get
2249 * @return {Object} The style property of the element
2250 * @deprecated use Roo.getDom instead
2253 getCss: function(id) {
2254 var el = Roo.getDom(id);
2255 return (el) ? el.style : null;
2259 * Inner class for cached elements
2260 * @class DragDropMgr.ElementWrapper
2265 ElementWrapper: function(el) {
2270 this.el = el || null;
2275 this.id = this.el && el.id;
2277 * A reference to the style property
2280 this.css = this.el && el.style;
2284 * Returns the X position of an html element
2286 * @param el the element for which to get the position
2287 * @return {int} the X coordinate
2289 * @deprecated use Roo.lib.Dom.getX instead
2292 getPosX: function(el) {
2293 return Roo.lib.Dom.getX(el);
2297 * Returns the Y position of an html element
2299 * @param el the element for which to get the position
2300 * @return {int} the Y coordinate
2301 * @deprecated use Roo.lib.Dom.getY instead
2304 getPosY: function(el) {
2305 return Roo.lib.Dom.getY(el);
2309 * Swap two nodes. In IE, we use the native method, for others we
2310 * emulate the IE behavior
2312 * @param n1 the first node to swap
2313 * @param n2 the other node to swap
2316 swapNode: function(n1, n2) {
2320 var p = n2.parentNode;
2321 var s = n2.nextSibling;
2324 p.insertBefore(n1, n2);
2325 } else if (n2 == n1.nextSibling) {
2326 p.insertBefore(n2, n1);
2328 n1.parentNode.replaceChild(n2, n1);
2329 p.insertBefore(n1, s);
2335 * Returns the current scroll position
2340 getScroll: function () {
2341 var t, l, dde=document.documentElement, db=document.body;
2342 if (dde && (dde.scrollTop || dde.scrollLeft)) {
2351 return { top: t, left: l };
2355 * Returns the specified element style property
2357 * @param {HTMLElement} el the element
2358 * @param {string} styleProp the style property
2359 * @return {string} The value of the style property
2360 * @deprecated use Roo.lib.Dom.getStyle
2363 getStyle: function(el, styleProp) {
2364 return Roo.fly(el).getStyle(styleProp);
2368 * Gets the scrollTop
2369 * @method getScrollTop
2370 * @return {int} the document's scrollTop
2373 getScrollTop: function () { return this.getScroll().top; },
2376 * Gets the scrollLeft
2377 * @method getScrollLeft
2378 * @return {int} the document's scrollTop
2381 getScrollLeft: function () { return this.getScroll().left; },
2384 * Sets the x/y position of an element to the location of the
2387 * @param {HTMLElement} moveEl The element to move
2388 * @param {HTMLElement} targetEl The position reference element
2391 moveToEl: function (moveEl, targetEl) {
2392 var aCoord = Roo.lib.Dom.getXY(targetEl);
2393 Roo.lib.Dom.setXY(moveEl, aCoord);
2397 * Numeric array sort function
2398 * @method numericSort
2401 numericSort: function(a, b) { return (a - b); },
2405 * @property _timeoutCount
2412 * Trying to make the load order less important. Without this we get
2413 * an error if this file is loaded before the Event Utility.
2414 * @method _addListeners
2418 _addListeners: function() {
2419 var DDM = Roo.dd.DDM;
2420 if ( Roo.lib.Event && document ) {
2423 if (DDM._timeoutCount > 2000) {
2425 setTimeout(DDM._addListeners, 10);
2426 if (document && document.body) {
2427 DDM._timeoutCount += 1;
2434 * Recursively searches the immediate parent and all child nodes for
2435 * the handle element in order to determine wheter or not it was
2437 * @method handleWasClicked
2438 * @param node the html element to inspect
2441 handleWasClicked: function(node, id) {
2442 if (this.isHandle(id, node.id)) {
2445 // check to see if this is a text node child of the one we want
2446 var p = node.parentNode;
2449 if (this.isHandle(id, p.id)) {
2464 // shorter alias, save a few bytes
2465 Roo.dd.DDM = Roo.dd.DragDropMgr;
2466 Roo.dd.DDM._addListeners();
2470 * Ext JS Library 1.1.1
2471 * Copyright(c) 2006-2007, Ext JS, LLC.
2473 * Originally Released Under LGPL - original licence link has changed is not relivant.
2476 * <script type="text/javascript">
2481 * A DragDrop implementation where the linked element follows the
2482 * mouse cursor during a drag.
2483 * @extends Roo.dd.DragDrop
2485 * @param {String} id the id of the linked element
2486 * @param {String} sGroup the group of related DragDrop items
2487 * @param {object} config an object containing configurable attributes
2488 * Valid properties for DD:
2491 Roo.dd.DD = function(id, sGroup, config) {
2493 this.init(id, sGroup, config);
2497 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
2500 * When set to true, the utility automatically tries to scroll the browser
2501 * window wehn a drag and drop element is dragged near the viewport boundary.
2509 * Sets the pointer offset to the distance between the linked element's top
2510 * left corner and the location the element was clicked
2511 * @method autoOffset
2512 * @param {int} iPageX the X coordinate of the click
2513 * @param {int} iPageY the Y coordinate of the click
2515 autoOffset: function(iPageX, iPageY) {
2516 var x = iPageX - this.startPageX;
2517 var y = iPageY - this.startPageY;
2518 this.setDelta(x, y);
2522 * Sets the pointer offset. You can call this directly to force the
2523 * offset to be in a particular location (e.g., pass in 0,0 to set it
2524 * to the center of the object)
2526 * @param {int} iDeltaX the distance from the left
2527 * @param {int} iDeltaY the distance from the top
2529 setDelta: function(iDeltaX, iDeltaY) {
2530 this.deltaX = iDeltaX;
2531 this.deltaY = iDeltaY;
2535 * Sets the drag element to the location of the mousedown or click event,
2536 * maintaining the cursor location relative to the location on the element
2537 * that was clicked. Override this if you want to place the element in a
2538 * location other than where the cursor is.
2539 * @method setDragElPos
2540 * @param {int} iPageX the X coordinate of the mousedown or drag event
2541 * @param {int} iPageY the Y coordinate of the mousedown or drag event
2543 setDragElPos: function(iPageX, iPageY) {
2544 // the first time we do this, we are going to check to make sure
2545 // the element has css positioning
2547 var el = this.getDragEl();
2548 this.alignElWithMouse(el, iPageX, iPageY);
2552 * Sets the element to the location of the mousedown or click event,
2553 * maintaining the cursor location relative to the location on the element
2554 * that was clicked. Override this if you want to place the element in a
2555 * location other than where the cursor is.
2556 * @method alignElWithMouse
2557 * @param {HTMLElement} el the element to move
2558 * @param {int} iPageX the X coordinate of the mousedown or drag event
2559 * @param {int} iPageY the Y coordinate of the mousedown or drag event
2561 alignElWithMouse: function(el, iPageX, iPageY) {
2562 var oCoord = this.getTargetCoord(iPageX, iPageY);
2563 var fly = el.dom ? el : Roo.fly(el);
2564 if (!this.deltaSetXY) {
2565 var aCoord = [oCoord.x, oCoord.y];
2567 var newLeft = fly.getLeft(true);
2568 var newTop = fly.getTop(true);
2569 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
2571 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
2574 this.cachePosition(oCoord.x, oCoord.y);
2575 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
2580 * Saves the most recent position so that we can reset the constraints and
2581 * tick marks on-demand. We need to know this so that we can calculate the
2582 * number of pixels the element is offset from its original position.
2583 * @method cachePosition
2584 * @param iPageX the current x position (optional, this just makes it so we
2585 * don't have to look it up again)
2586 * @param iPageY the current y position (optional, this just makes it so we
2587 * don't have to look it up again)
2589 cachePosition: function(iPageX, iPageY) {
2591 this.lastPageX = iPageX;
2592 this.lastPageY = iPageY;
2594 var aCoord = Roo.lib.Dom.getXY(this.getEl());
2595 this.lastPageX = aCoord[0];
2596 this.lastPageY = aCoord[1];
2601 * Auto-scroll the window if the dragged object has been moved beyond the
2602 * visible window boundary.
2603 * @method autoScroll
2604 * @param {int} x the drag element's x position
2605 * @param {int} y the drag element's y position
2606 * @param {int} h the height of the drag element
2607 * @param {int} w the width of the drag element
2610 autoScroll: function(x, y, h, w) {
2613 // The client height
2614 var clientH = Roo.lib.Dom.getViewWidth();
2617 var clientW = Roo.lib.Dom.getViewHeight();
2619 // The amt scrolled down
2620 var st = this.DDM.getScrollTop();
2622 // The amt scrolled right
2623 var sl = this.DDM.getScrollLeft();
2625 // Location of the bottom of the element
2628 // Location of the right of the element
2631 // The distance from the cursor to the bottom of the visible area,
2632 // adjusted so that we don't scroll if the cursor is beyond the
2633 // element drag constraints
2634 var toBot = (clientH + st - y - this.deltaY);
2636 // The distance from the cursor to the right of the visible area
2637 var toRight = (clientW + sl - x - this.deltaX);
2640 // How close to the edge the cursor must be before we scroll
2641 // var thresh = (document.all) ? 100 : 40;
2644 // How many pixels to scroll per autoscroll op. This helps to reduce
2645 // clunky scrolling. IE is more sensitive about this ... it needs this
2646 // value to be higher.
2647 var scrAmt = (document.all) ? 80 : 30;
2649 // Scroll down if we are near the bottom of the visible page and the
2650 // obj extends below the crease
2651 if ( bot > clientH && toBot < thresh ) {
2652 window.scrollTo(sl, st + scrAmt);
2655 // Scroll up if the window is scrolled down and the top of the object
2656 // goes above the top border
2657 if ( y < st && st > 0 && y - st < thresh ) {
2658 window.scrollTo(sl, st - scrAmt);
2661 // Scroll right if the obj is beyond the right border and the cursor is
2663 if ( right > clientW && toRight < thresh ) {
2664 window.scrollTo(sl + scrAmt, st);
2667 // Scroll left if the window has been scrolled to the right and the obj
2668 // extends past the left border
2669 if ( x < sl && sl > 0 && x - sl < thresh ) {
2670 window.scrollTo(sl - scrAmt, st);
2676 * Finds the location the element should be placed if we want to move
2677 * it to where the mouse location less the click offset would place us.
2678 * @method getTargetCoord
2679 * @param {int} iPageX the X coordinate of the click
2680 * @param {int} iPageY the Y coordinate of the click
2681 * @return an object that contains the coordinates (Object.x and Object.y)
2684 getTargetCoord: function(iPageX, iPageY) {
2687 var x = iPageX - this.deltaX;
2688 var y = iPageY - this.deltaY;
2690 if (this.constrainX) {
2691 if (x < this.minX) { x = this.minX; }
2692 if (x > this.maxX) { x = this.maxX; }
2695 if (this.constrainY) {
2696 if (y < this.minY) { y = this.minY; }
2697 if (y > this.maxY) { y = this.maxY; }
2700 x = this.getTick(x, this.xTicks);
2701 y = this.getTick(y, this.yTicks);
2708 * Sets up config options specific to this class. Overrides
2709 * Roo.dd.DragDrop, but all versions of this method through the
2710 * inheritance chain are called
2712 applyConfig: function() {
2713 Roo.dd.DD.superclass.applyConfig.call(this);
2714 this.scroll = (this.config.scroll !== false);
2718 * Event that fires prior to the onMouseDown event. Overrides
2721 b4MouseDown: function(e) {
2722 // this.resetConstraints();
2723 this.autoOffset(e.getPageX(),
2728 * Event that fires prior to the onDrag event. Overrides
2731 b4Drag: function(e) {
2732 this.setDragElPos(e.getPageX(),
2736 toString: function() {
2737 return ("DD " + this.id);
2740 //////////////////////////////////////////////////////////////////////////
2741 // Debugging ygDragDrop events that can be overridden
2742 //////////////////////////////////////////////////////////////////////////
2744 startDrag: function(x, y) {
2747 onDrag: function(e) {
2750 onDragEnter: function(e, id) {
2753 onDragOver: function(e, id) {
2756 onDragOut: function(e, id) {
2759 onDragDrop: function(e, id) {
2762 endDrag: function(e) {
2769 * Ext JS Library 1.1.1
2770 * Copyright(c) 2006-2007, Ext JS, LLC.
2772 * Originally Released Under LGPL - original licence link has changed is not relivant.
2775 * <script type="text/javascript">
2779 * @class Roo.dd.DDProxy
2780 * A DragDrop implementation that inserts an empty, bordered div into
2781 * the document that follows the cursor during drag operations. At the time of
2782 * the click, the frame div is resized to the dimensions of the linked html
2783 * element, and moved to the exact location of the linked element.
2785 * References to the "frame" element refer to the single proxy element that
2786 * was created to be dragged in place of all DDProxy elements on the
2789 * @extends Roo.dd.DD
2791 * @param {String} id the id of the linked html element
2792 * @param {String} sGroup the group of related DragDrop objects
2793 * @param {object} config an object containing configurable attributes
2794 * Valid properties for DDProxy in addition to those in DragDrop:
2795 * resizeFrame, centerFrame, dragElId
2797 Roo.dd.DDProxy = function(id, sGroup, config) {
2799 this.init(id, sGroup, config);
2805 * The default drag frame div id
2806 * @property Roo.dd.DDProxy.dragElId
2810 Roo.dd.DDProxy.dragElId = "ygddfdiv";
2812 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
2815 * By default we resize the drag frame to be the same size as the element
2816 * we want to drag (this is to get the frame effect). We can turn it off
2817 * if we want a different behavior.
2818 * @property resizeFrame
2824 * By default the frame is positioned exactly where the drag element is, so
2825 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
2826 * you do not have constraints on the obj is to have the drag frame centered
2827 * around the cursor. Set centerFrame to true for this effect.
2828 * @property centerFrame
2834 * Creates the proxy element if it does not yet exist
2835 * @method createFrame
2837 createFrame: function() {
2839 var body = document.body;
2841 if (!body || !body.firstChild) {
2842 setTimeout( function() { self.createFrame(); }, 50 );
2846 var div = this.getDragEl();
2849 div = document.createElement("div");
2850 div.id = this.dragElId;
2853 s.position = "absolute";
2854 s.visibility = "hidden";
2856 s.border = "2px solid #aaa";
2859 // appendChild can blow up IE if invoked prior to the window load event
2860 // while rendering a table. It is possible there are other scenarios
2861 // that would cause this to happen as well.
2862 body.insertBefore(div, body.firstChild);
2867 * Initialization for the drag frame element. Must be called in the
2868 * constructor of all subclasses
2871 initFrame: function() {
2875 applyConfig: function() {
2876 Roo.dd.DDProxy.superclass.applyConfig.call(this);
2878 this.resizeFrame = (this.config.resizeFrame !== false);
2879 this.centerFrame = (this.config.centerFrame);
2880 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
2884 * Resizes the drag frame to the dimensions of the clicked object, positions
2885 * it over the object, and finally displays it
2887 * @param {int} iPageX X click position
2888 * @param {int} iPageY Y click position
2891 showFrame: function(iPageX, iPageY) {
2892 var el = this.getEl();
2893 var dragEl = this.getDragEl();
2894 var s = dragEl.style;
2896 this._resizeProxy();
2898 if (this.centerFrame) {
2899 this.setDelta( Math.round(parseInt(s.width, 10)/2),
2900 Math.round(parseInt(s.height, 10)/2) );
2903 this.setDragElPos(iPageX, iPageY);
2905 Roo.fly(dragEl).show();
2909 * The proxy is automatically resized to the dimensions of the linked
2910 * element when a drag is initiated, unless resizeFrame is set to false
2911 * @method _resizeProxy
2914 _resizeProxy: function() {
2915 if (this.resizeFrame) {
2916 var el = this.getEl();
2917 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
2921 // overrides Roo.dd.DragDrop
2922 b4MouseDown: function(e) {
2923 var x = e.getPageX();
2924 var y = e.getPageY();
2925 this.autoOffset(x, y);
2926 this.setDragElPos(x, y);
2929 // overrides Roo.dd.DragDrop
2930 b4StartDrag: function(x, y) {
2931 // show the drag frame
2932 this.showFrame(x, y);
2935 // overrides Roo.dd.DragDrop
2936 b4EndDrag: function(e) {
2937 Roo.fly(this.getDragEl()).hide();
2940 // overrides Roo.dd.DragDrop
2941 // By default we try to move the element to the last location of the frame.
2942 // This is so that the default behavior mirrors that of Roo.dd.DD.
2943 endDrag: function(e) {
2945 var lel = this.getEl();
2946 var del = this.getDragEl();
2948 // Show the drag frame briefly so we can get its position
2949 del.style.visibility = "";
2952 // Hide the linked element before the move to get around a Safari
2954 lel.style.visibility = "hidden";
2955 Roo.dd.DDM.moveToEl(lel, del);
2956 del.style.visibility = "hidden";
2957 lel.style.visibility = "";
2962 beforeMove : function(){
2966 afterDrag : function(){
2970 toString: function() {
2971 return ("DDProxy " + this.id);
2977 * Ext JS Library 1.1.1
2978 * Copyright(c) 2006-2007, Ext JS, LLC.
2980 * Originally Released Under LGPL - original licence link has changed is not relivant.
2983 * <script type="text/javascript">
2987 * @class Roo.dd.DDTarget
2988 * A DragDrop implementation that does not move, but can be a drop
2989 * target. You would get the same result by simply omitting implementation
2990 * for the event callbacks, but this way we reduce the processing cost of the
2991 * event listener and the callbacks.
2992 * @extends Roo.dd.DragDrop
2994 * @param {String} id the id of the element that is a drop target
2995 * @param {String} sGroup the group of related DragDrop objects
2996 * @param {object} config an object containing configurable attributes
2997 * Valid properties for DDTarget in addition to those in
3001 Roo.dd.DDTarget = function(id, sGroup, config) {
3003 this.initTarget(id, sGroup, config);
3005 if (config.listeners || config.events) {
3006 Roo.dd.DragDrop.superclass.constructor.call(this, {
3007 listeners : config.listeners || {},
3008 events : config.events || {}
3013 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
3014 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
3015 toString: function() {
3016 return ("DDTarget " + this.id);
3021 * Ext JS Library 1.1.1
3022 * Copyright(c) 2006-2007, Ext JS, LLC.
3024 * Originally Released Under LGPL - original licence link has changed is not relivant.
3027 * <script type="text/javascript">
3032 * @class Roo.dd.ScrollManager
3033 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
3034 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
3037 Roo.dd.ScrollManager = function(){
3038 var ddm = Roo.dd.DragDropMgr;
3043 var onStop = function(e){
3048 var triggerRefresh = function(){
3049 if(ddm.dragCurrent){
3050 ddm.refreshCache(ddm.dragCurrent.groups);
3054 var doScroll = function(){
3055 if(ddm.dragCurrent){
3056 var dds = Roo.dd.ScrollManager;
3058 if(proc.el.scroll(proc.dir, dds.increment)){
3062 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
3067 var clearProc = function(){
3069 clearInterval(proc.id);
3076 var startProc = function(el, dir){
3080 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
3083 var onFire = function(e, isDrop){
3084 if(isDrop || !ddm.dragCurrent){ return; }
3085 var dds = Roo.dd.ScrollManager;
3086 if(!dragEl || dragEl != ddm.dragCurrent){
3087 dragEl = ddm.dragCurrent;
3088 // refresh regions on drag start
3092 var xy = Roo.lib.Event.getXY(e);
3093 var pt = new Roo.lib.Point(xy[0], xy[1]);
3095 var el = els[id], r = el._region;
3096 if(r && r.contains(pt) && el.isScrollable()){
3097 if(r.bottom - pt.y <= dds.thresh){
3099 startProc(el, "down");
3102 }else if(r.right - pt.x <= dds.thresh){
3104 startProc(el, "left");
3107 }else if(pt.y - r.top <= dds.thresh){
3109 startProc(el, "up");
3112 }else if(pt.x - r.left <= dds.thresh){
3114 startProc(el, "right");
3123 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
3124 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
3128 * Registers new overflow element(s) to auto scroll
3129 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
3131 register : function(el){
3132 if(el instanceof Array){
3133 for(var i = 0, len = el.length; i < len; i++) {
3134 this.register(el[i]);
3143 * Unregisters overflow element(s) so they are no longer scrolled
3144 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
3146 unregister : function(el){
3147 if(el instanceof Array){
3148 for(var i = 0, len = el.length; i < len; i++) {
3149 this.unregister(el[i]);
3158 * The number of pixels from the edge of a container the pointer needs to be to
3159 * trigger scrolling (defaults to 25)
3165 * The number of pixels to scroll in each scroll increment (defaults to 50)
3171 * The frequency of scrolls in milliseconds (defaults to 500)
3177 * True to animate the scroll (defaults to true)
3183 * The animation duration in seconds -
3184 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
3190 * Manually trigger a cache refresh.
3192 refreshCache : function(){
3194 if(typeof els[id] == 'object'){ // for people extending the object prototype
3195 els[id]._region = els[id].getRegion();
3202 * Ext JS Library 1.1.1
3203 * Copyright(c) 2006-2007, Ext JS, LLC.
3205 * Originally Released Under LGPL - original licence link has changed is not relivant.
3208 * <script type="text/javascript">
3213 * @class Roo.dd.Registry
3214 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
3215 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
3218 Roo.dd.Registry = function(){
3223 var getId = function(el, autogen){
3224 if(typeof el == "string"){
3228 if(!id && autogen !== false){
3229 id = "roodd-" + (++autoIdSeed);
3237 * Register a drag drop element
3238 * @param {String|HTMLElement} element The id or DOM node to register
3239 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
3240 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
3241 * knows how to interpret, plus there are some specific properties known to the Registry that should be
3242 * populated in the data object (if applicable):
3244 Value Description<br />
3245 --------- ------------------------------------------<br />
3246 handles Array of DOM nodes that trigger dragging<br />
3247 for the element being registered<br />
3248 isHandle True if the element passed in triggers<br />
3249 dragging itself, else false
3252 register : function(el, data){
3254 if(typeof el == "string"){
3255 el = document.getElementById(el);
3258 elements[getId(el)] = data;
3259 if(data.isHandle !== false){
3260 handles[data.ddel.id] = data;
3263 var hs = data.handles;
3264 for(var i = 0, len = hs.length; i < len; i++){
3265 handles[getId(hs[i])] = data;
3271 * Unregister a drag drop element
3272 * @param {String|HTMLElement} element The id or DOM node to unregister
3274 unregister : function(el){
3275 var id = getId(el, false);
3276 var data = elements[id];
3278 delete elements[id];
3280 var hs = data.handles;
3281 for(var i = 0, len = hs.length; i < len; i++){
3282 delete handles[getId(hs[i], false)];
3289 * Returns the handle registered for a DOM Node by id
3290 * @param {String|HTMLElement} id The DOM node or id to look up
3291 * @return {Object} handle The custom handle data
3293 getHandle : function(id){
3294 if(typeof id != "string"){ // must be element?
3301 * Returns the handle that is registered for the DOM node that is the target of the event
3302 * @param {Event} e The event
3303 * @return {Object} handle The custom handle data
3305 getHandleFromEvent : function(e){
3306 var t = Roo.lib.Event.getTarget(e);
3307 return t ? handles[t.id] : null;
3311 * Returns a custom data object that is registered for a DOM node by id
3312 * @param {String|HTMLElement} id The DOM node or id to look up
3313 * @return {Object} data The custom data
3315 getTarget : function(id){
3316 if(typeof id != "string"){ // must be element?
3319 return elements[id];
3323 * Returns a custom data object that is registered for the DOM node that is the target of the event
3324 * @param {Event} e The event
3325 * @return {Object} data The custom data
3327 getTargetFromEvent : function(e){
3328 var t = Roo.lib.Event.getTarget(e);
3329 return t ? elements[t.id] || handles[t.id] : null;
3334 * Ext JS Library 1.1.1
3335 * Copyright(c) 2006-2007, Ext JS, LLC.
3337 * Originally Released Under LGPL - original licence link has changed is not relivant.
3340 * <script type="text/javascript">
3345 * @class Roo.dd.StatusProxy
3346 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
3347 * default drag proxy used by all Roo.dd components.
3349 * @param {Object} config
3351 Roo.dd.StatusProxy = function(config){
3352 Roo.apply(this, config);
3353 this.id = this.id || Roo.id();
3354 this.el = new Roo.Layer({
3356 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
3357 {tag: "div", cls: "x-dd-drop-icon"},
3358 {tag: "div", cls: "x-dd-drag-ghost"}
3361 shadow: !config || config.shadow !== false
3363 this.ghost = Roo.get(this.el.dom.childNodes[1]);
3364 this.dropStatus = this.dropNotAllowed;
3367 Roo.dd.StatusProxy.prototype = {
3369 * @cfg {String} dropAllowed
3370 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
3372 dropAllowed : "x-dd-drop-ok",
3374 * @cfg {String} dropNotAllowed
3375 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
3377 dropNotAllowed : "x-dd-drop-nodrop",
3380 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
3381 * over the current target element.
3382 * @param {String} cssClass The css class for the new drop status indicator image
3384 setStatus : function(cssClass){
3385 cssClass = cssClass || this.dropNotAllowed;
3386 if(this.dropStatus != cssClass){
3387 this.el.replaceClass(this.dropStatus, cssClass);
3388 this.dropStatus = cssClass;
3393 * Resets the status indicator to the default dropNotAllowed value
3394 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
3396 reset : function(clearGhost){
3397 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
3398 this.dropStatus = this.dropNotAllowed;
3400 this.ghost.update("");
3405 * Updates the contents of the ghost element
3406 * @param {String} html The html that will replace the current innerHTML of the ghost element
3408 update : function(html){
3409 if(typeof html == "string"){
3410 this.ghost.update(html);
3412 this.ghost.update("");
3413 html.style.margin = "0";
3414 this.ghost.dom.appendChild(html);
3416 // ensure float = none set?? cant remember why though.
3417 var el = this.ghost.dom.firstChild;
3419 Roo.fly(el).setStyle('float', 'none');
3424 * Returns the underlying proxy {@link Roo.Layer}
3425 * @return {Roo.Layer} el
3432 * Returns the ghost element
3433 * @return {Roo.Element} el
3435 getGhost : function(){
3441 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
3443 hide : function(clear){
3451 * Stops the repair animation if it's currently running
3454 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
3460 * Displays this proxy
3467 * Force the Layer to sync its shadow and shim positions to the element
3474 * Causes the proxy to return to its position of origin via an animation. Should be called after an
3475 * invalid drop operation by the item being dragged.
3476 * @param {Array} xy The XY position of the element ([x, y])
3477 * @param {Function} callback The function to call after the repair is complete
3478 * @param {Object} scope The scope in which to execute the callback
3480 repair : function(xy, callback, scope){
3481 this.callback = callback;
3483 if(xy && this.animRepair !== false){
3484 this.el.addClass("x-dd-drag-repair");
3485 this.el.hideUnders(true);
3486 this.anim = this.el.shift({
3487 duration: this.repairDuration || .5,
3491 callback: this.afterRepair,
3500 afterRepair : function(){
3502 if(typeof this.callback == "function"){
3503 this.callback.call(this.scope || this);
3505 this.callback = null;
3510 * Ext JS Library 1.1.1
3511 * Copyright(c) 2006-2007, Ext JS, LLC.
3513 * Originally Released Under LGPL - original licence link has changed is not relivant.
3516 * <script type="text/javascript">
3520 * @class Roo.dd.DragSource
3521 * @extends Roo.dd.DDProxy
3522 * A simple class that provides the basic implementation needed to make any element draggable.
3524 * @param {String/HTMLElement/Element} el The container element
3525 * @param {Object} config
3527 Roo.dd.DragSource = function(el, config){
3528 this.el = Roo.get(el);
3531 Roo.apply(this, config);
3534 this.proxy = new Roo.dd.StatusProxy();
3537 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
3538 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
3540 this.dragging = false;
3543 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
3545 * @cfg {String} dropAllowed
3546 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
3548 dropAllowed : "x-dd-drop-ok",
3550 * @cfg {String} dropNotAllowed
3551 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
3553 dropNotAllowed : "x-dd-drop-nodrop",
3556 * Returns the data object associated with this drag source
3557 * @return {Object} data An object containing arbitrary data
3559 getDragData : function(e){
3560 return this.dragData;
3564 onDragEnter : function(e, id){
3565 var target = Roo.dd.DragDropMgr.getDDById(id);
3566 this.cachedTarget = target;
3567 if(this.beforeDragEnter(target, e, id) !== false){
3568 if(target.isNotifyTarget){
3569 var status = target.notifyEnter(this, e, this.dragData);
3570 this.proxy.setStatus(status);
3572 this.proxy.setStatus(this.dropAllowed);
3575 if(this.afterDragEnter){
3577 * An empty function by default, but provided so that you can perform a custom action
3578 * when the dragged item enters the drop target by providing an implementation.
3579 * @param {Roo.dd.DragDrop} target The drop target
3580 * @param {Event} e The event object
3581 * @param {String} id The id of the dragged element
3582 * @method afterDragEnter
3584 this.afterDragEnter(target, e, id);
3590 * An empty function by default, but provided so that you can perform a custom action
3591 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
3592 * @param {Roo.dd.DragDrop} target The drop target
3593 * @param {Event} e The event object
3594 * @param {String} id The id of the dragged element
3595 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
3597 beforeDragEnter : function(target, e, id){
3602 alignElWithMouse: function() {
3603 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
3608 onDragOver : function(e, id){
3609 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
3610 if(this.beforeDragOver(target, e, id) !== false){
3611 if(target.isNotifyTarget){
3612 var status = target.notifyOver(this, e, this.dragData);
3613 this.proxy.setStatus(status);
3616 if(this.afterDragOver){
3618 * An empty function by default, but provided so that you can perform a custom action
3619 * while the dragged item is over the drop target by providing an implementation.
3620 * @param {Roo.dd.DragDrop} target The drop target
3621 * @param {Event} e The event object
3622 * @param {String} id The id of the dragged element
3623 * @method afterDragOver
3625 this.afterDragOver(target, e, id);
3631 * An empty function by default, but provided so that you can perform a custom action
3632 * while the dragged item is over the drop target and optionally cancel the onDragOver.
3633 * @param {Roo.dd.DragDrop} target The drop target
3634 * @param {Event} e The event object
3635 * @param {String} id The id of the dragged element
3636 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
3638 beforeDragOver : function(target, e, id){
3643 onDragOut : function(e, id){
3644 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
3645 if(this.beforeDragOut(target, e, id) !== false){
3646 if(target.isNotifyTarget){
3647 target.notifyOut(this, e, this.dragData);
3650 if(this.afterDragOut){
3652 * An empty function by default, but provided so that you can perform a custom action
3653 * after the dragged item is dragged out of the target without dropping.
3654 * @param {Roo.dd.DragDrop} target The drop target
3655 * @param {Event} e The event object
3656 * @param {String} id The id of the dragged element
3657 * @method afterDragOut
3659 this.afterDragOut(target, e, id);
3662 this.cachedTarget = null;
3666 * An empty function by default, but provided so that you can perform a custom action before the dragged
3667 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
3668 * @param {Roo.dd.DragDrop} target The drop target
3669 * @param {Event} e The event object
3670 * @param {String} id The id of the dragged element
3671 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
3673 beforeDragOut : function(target, e, id){
3678 onDragDrop : function(e, id){
3679 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
3680 if(this.beforeDragDrop(target, e, id) !== false){
3681 if(target.isNotifyTarget){
3682 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
3683 this.onValidDrop(target, e, id);
3685 this.onInvalidDrop(target, e, id);
3688 this.onValidDrop(target, e, id);
3691 if(this.afterDragDrop){
3693 * An empty function by default, but provided so that you can perform a custom action
3694 * after a valid drag drop has occurred by providing an implementation.
3695 * @param {Roo.dd.DragDrop} target The drop target
3696 * @param {Event} e The event object
3697 * @param {String} id The id of the dropped element
3698 * @method afterDragDrop
3700 this.afterDragDrop(target, e, id);
3703 delete this.cachedTarget;
3707 * An empty function by default, but provided so that you can perform a custom action before the dragged
3708 * item is dropped onto the target and optionally cancel the onDragDrop.
3709 * @param {Roo.dd.DragDrop} target The drop target
3710 * @param {Event} e The event object
3711 * @param {String} id The id of the dragged element
3712 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
3714 beforeDragDrop : function(target, e, id){
3719 onValidDrop : function(target, e, id){
3721 if(this.afterValidDrop){
3723 * An empty function by default, but provided so that you can perform a custom action
3724 * after a valid drop has occurred by providing an implementation.
3725 * @param {Object} target The target DD
3726 * @param {Event} e The event object
3727 * @param {String} id The id of the dropped element
3728 * @method afterInvalidDrop
3730 this.afterValidDrop(target, e, id);
3735 getRepairXY : function(e, data){
3736 return this.el.getXY();
3740 onInvalidDrop : function(target, e, id){
3741 this.beforeInvalidDrop(target, e, id);
3742 if(this.cachedTarget){
3743 if(this.cachedTarget.isNotifyTarget){
3744 this.cachedTarget.notifyOut(this, e, this.dragData);
3746 this.cacheTarget = null;
3748 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
3750 if(this.afterInvalidDrop){
3752 * An empty function by default, but provided so that you can perform a custom action
3753 * after an invalid drop has occurred by providing an implementation.
3754 * @param {Event} e The event object
3755 * @param {String} id The id of the dropped element
3756 * @method afterInvalidDrop
3758 this.afterInvalidDrop(e, id);
3763 afterRepair : function(){
3765 this.el.highlight(this.hlColor || "c3daf9");
3767 this.dragging = false;
3771 * An empty function by default, but provided so that you can perform a custom action after an invalid
3772 * drop has occurred.
3773 * @param {Roo.dd.DragDrop} target The drop target
3774 * @param {Event} e The event object
3775 * @param {String} id The id of the dragged element
3776 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
3778 beforeInvalidDrop : function(target, e, id){
3783 handleMouseDown : function(e){
3787 var data = this.getDragData(e);
3788 if(data && this.onBeforeDrag(data, e) !== false){
3789 this.dragData = data;
3791 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
3796 * An empty function by default, but provided so that you can perform a custom action before the initial
3797 * drag event begins and optionally cancel it.
3798 * @param {Object} data An object containing arbitrary data to be shared with drop targets
3799 * @param {Event} e The event object
3800 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
3802 onBeforeDrag : function(data, e){
3807 * An empty function by default, but provided so that you can perform a custom action once the initial
3808 * drag event has begun. The drag cannot be canceled from this function.
3809 * @param {Number} x The x position of the click on the dragged object
3810 * @param {Number} y The y position of the click on the dragged object
3812 onStartDrag : Roo.emptyFn,
3814 // private - YUI override
3815 startDrag : function(x, y){
3817 this.dragging = true;
3818 this.proxy.update("");
3819 this.onInitDrag(x, y);
3824 onInitDrag : function(x, y){
3825 var clone = this.el.dom.cloneNode(true);
3826 clone.id = Roo.id(); // prevent duplicate ids
3827 this.proxy.update(clone);
3828 this.onStartDrag(x, y);
3833 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
3834 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
3836 getProxy : function(){
3841 * Hides the drag source's {@link Roo.dd.StatusProxy}
3843 hideProxy : function(){
3845 this.proxy.reset(true);
3846 this.dragging = false;
3850 triggerCacheRefresh : function(){
3851 Roo.dd.DDM.refreshCache(this.groups);
3854 // private - override to prevent hiding
3855 b4EndDrag: function(e) {
3858 // private - override to prevent moving
3859 endDrag : function(e){
3860 this.onEndDrag(this.dragData, e);
3864 onEndDrag : function(data, e){
3867 // private - pin to cursor
3868 autoOffset : function(x, y) {
3869 this.setDelta(-12, -20);
3873 * Ext JS Library 1.1.1
3874 * Copyright(c) 2006-2007, Ext JS, LLC.
3876 * Originally Released Under LGPL - original licence link has changed is not relivant.
3879 * <script type="text/javascript">
3884 * @class Roo.dd.DropTarget
3885 * @extends Roo.dd.DDTarget
3886 * A simple class that provides the basic implementation needed to make any element a drop target that can have
3887 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
3889 * @param {String/HTMLElement/Element} el The container element
3890 * @param {Object} config
3892 Roo.dd.DropTarget = function(el, config){
3893 this.el = Roo.get(el);
3895 var listeners = false; ;
3896 if (config && config.listeners) {
3897 listeners= config.listeners;
3898 delete config.listeners;
3900 Roo.apply(this, config);
3902 if(this.containerScroll){
3903 Roo.dd.ScrollManager.register(this.el);
3907 * @scope Roo.dd.DropTarget
3912 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
3913 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
3914 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
3916 * IMPORTANT : it should set this.overClass and this.dropAllowed
3918 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
3919 * @param {Event} e The event
3920 * @param {Object} data An object containing arbitrary data supplied by the drag source
3926 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
3927 * This method will be called on every mouse movement while the drag source is over the drop target.
3928 * This default implementation simply returns the dropAllowed config value.
3930 * IMPORTANT : it should set this.dropAllowed
3932 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
3933 * @param {Event} e The event
3934 * @param {Object} data An object containing arbitrary data supplied by the drag source
3940 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
3941 * out of the target without dropping. This default implementation simply removes the CSS class specified by
3942 * overClass (if any) from the drop element.
3943 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
3944 * @param {Event} e The event
3945 * @param {Object} data An object containing arbitrary data supplied by the drag source
3951 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
3952 * been dropped on it. This method has no default implementation and returns false, so you must provide an
3953 * implementation that does something to process the drop event and returns true so that the drag source's
3954 * repair action does not run.
3956 * IMPORTANT : it should set this.success
3958 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
3959 * @param {Event} e The event
3960 * @param {Object} data An object containing arbitrary data supplied by the drag source
3966 Roo.dd.DropTarget.superclass.constructor.call( this,
3968 this.ddGroup || this.group,
3971 listeners : listeners || {}
3979 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
3981 * @cfg {String} overClass
3982 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
3985 * @cfg {String} ddGroup
3986 * The drag drop group to handle drop events for
3990 * @cfg {String} dropAllowed
3991 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
3993 dropAllowed : "x-dd-drop-ok",
3995 * @cfg {String} dropNotAllowed
3996 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
3998 dropNotAllowed : "x-dd-drop-nodrop",
4000 * @cfg {boolean} success
4001 * set this after drop listener..
4005 * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
4006 * if the drop point is valid for over/enter..
4013 isNotifyTarget : true,
4018 notifyEnter : function(dd, e, data)
4021 this.fireEvent('enter', dd, e, data);
4023 this.el.addClass(this.overClass);
4025 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
4026 this.valid ? this.dropAllowed : this.dropNotAllowed
4033 notifyOver : function(dd, e, data)
4036 this.fireEvent('over', dd, e, data);
4037 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
4038 this.valid ? this.dropAllowed : this.dropNotAllowed
4045 notifyOut : function(dd, e, data)
4047 this.fireEvent('out', dd, e, data);
4049 this.el.removeClass(this.overClass);
4056 notifyDrop : function(dd, e, data)
4058 this.success = false;
4059 this.fireEvent('drop', dd, e, data);
4060 return this.success;
4064 * Ext JS Library 1.1.1
4065 * Copyright(c) 2006-2007, Ext JS, LLC.
4067 * Originally Released Under LGPL - original licence link has changed is not relivant.
4070 * <script type="text/javascript">
4075 * @class Roo.dd.DragZone
4076 * @extends Roo.dd.DragSource
4077 * This class provides a container DD instance that proxies for multiple child node sources.<br />
4078 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
4080 * @param {String/HTMLElement/Element} el The container element
4081 * @param {Object} config
4083 Roo.dd.DragZone = function(el, config){
4084 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
4085 if(this.containerScroll){
4086 Roo.dd.ScrollManager.register(this.el);
4090 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
4092 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
4093 * for auto scrolling during drag operations.
4096 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
4097 * method after a failed drop (defaults to "c3daf9" - light blue)
4101 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
4102 * for a valid target to drag based on the mouse down. Override this method
4103 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
4104 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
4105 * @param {EventObject} e The mouse down event
4106 * @return {Object} The dragData
4108 getDragData : function(e){
4109 return Roo.dd.Registry.getHandleFromEvent(e);
4113 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
4114 * this.dragData.ddel
4115 * @param {Number} x The x position of the click on the dragged object
4116 * @param {Number} y The y position of the click on the dragged object
4117 * @return {Boolean} true to continue the drag, false to cancel
4119 onInitDrag : function(x, y){
4120 this.proxy.update(this.dragData.ddel.cloneNode(true));
4121 this.onStartDrag(x, y);
4126 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
4128 afterRepair : function(){
4130 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
4132 this.dragging = false;
4136 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
4137 * the XY of this.dragData.ddel
4138 * @param {EventObject} e The mouse up event
4139 * @return {Array} The xy location (e.g. [100, 200])
4141 getRepairXY : function(e){
4142 return Roo.Element.fly(this.dragData.ddel).getXY();
4146 * Ext JS Library 1.1.1
4147 * Copyright(c) 2006-2007, Ext JS, LLC.
4149 * Originally Released Under LGPL - original licence link has changed is not relivant.
4152 * <script type="text/javascript">
4155 * @class Roo.dd.DropZone
4156 * @extends Roo.dd.DropTarget
4157 * This class provides a container DD instance that proxies for multiple child node targets.<br />
4158 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
4160 * @param {String/HTMLElement/Element} el The container element
4161 * @param {Object} config
4163 Roo.dd.DropZone = function(el, config){
4164 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
4167 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
4169 * Returns a custom data object associated with the DOM node that is the target of the event. By default
4170 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
4171 * provide your own custom lookup.
4172 * @param {Event} e The event
4173 * @return {Object} data The custom data
4175 getTargetFromEvent : function(e){
4176 return Roo.dd.Registry.getTargetFromEvent(e);
4180 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
4181 * that it has registered. This method has no default implementation and should be overridden to provide
4182 * node-specific processing if necessary.
4183 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
4184 * {@link #getTargetFromEvent} for this node)
4185 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4186 * @param {Event} e The event
4187 * @param {Object} data An object containing arbitrary data supplied by the drag source
4189 onNodeEnter : function(n, dd, e, data){
4194 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
4195 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
4196 * overridden to provide the proper feedback.
4197 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
4198 * {@link #getTargetFromEvent} for this node)
4199 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4200 * @param {Event} e The event
4201 * @param {Object} data An object containing arbitrary data supplied by the drag source
4202 * @return {String} status The CSS class that communicates the drop status back to the source so that the
4203 * underlying {@link Roo.dd.StatusProxy} can be updated
4205 onNodeOver : function(n, dd, e, data){
4206 return this.dropAllowed;
4210 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
4211 * the drop node without dropping. This method has no default implementation and should be overridden to provide
4212 * node-specific processing if necessary.
4213 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
4214 * {@link #getTargetFromEvent} for this node)
4215 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4216 * @param {Event} e The event
4217 * @param {Object} data An object containing arbitrary data supplied by the drag source
4219 onNodeOut : function(n, dd, e, data){
4224 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
4225 * the drop node. The default implementation returns false, so it should be overridden to provide the
4226 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
4227 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
4228 * {@link #getTargetFromEvent} for this node)
4229 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4230 * @param {Event} e The event
4231 * @param {Object} data An object containing arbitrary data supplied by the drag source
4232 * @return {Boolean} True if the drop was valid, else false
4234 onNodeDrop : function(n, dd, e, data){
4239 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
4240 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
4241 * it should be overridden to provide the proper feedback if necessary.
4242 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4243 * @param {Event} e The event
4244 * @param {Object} data An object containing arbitrary data supplied by the drag source
4245 * @return {String} status The CSS class that communicates the drop status back to the source so that the
4246 * underlying {@link Roo.dd.StatusProxy} can be updated
4248 onContainerOver : function(dd, e, data){
4249 return this.dropNotAllowed;
4253 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
4254 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
4255 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
4256 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
4257 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4258 * @param {Event} e The event
4259 * @param {Object} data An object containing arbitrary data supplied by the drag source
4260 * @return {Boolean} True if the drop was valid, else false
4262 onContainerDrop : function(dd, e, data){
4267 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
4268 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
4269 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
4270 * you should override this method and provide a custom implementation.
4271 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4272 * @param {Event} e The event
4273 * @param {Object} data An object containing arbitrary data supplied by the drag source
4274 * @return {String} status The CSS class that communicates the drop status back to the source so that the
4275 * underlying {@link Roo.dd.StatusProxy} can be updated
4277 notifyEnter : function(dd, e, data){
4278 return this.dropNotAllowed;
4282 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
4283 * This method will be called on every mouse movement while the drag source is over the drop zone.
4284 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
4285 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
4286 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
4287 * registered node, it will call {@link #onContainerOver}.
4288 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4289 * @param {Event} e The event
4290 * @param {Object} data An object containing arbitrary data supplied by the drag source
4291 * @return {String} status The CSS class that communicates the drop status back to the source so that the
4292 * underlying {@link Roo.dd.StatusProxy} can be updated
4294 notifyOver : function(dd, e, data){
4295 var n = this.getTargetFromEvent(e);
4296 if(!n){ // not over valid drop target
4297 if(this.lastOverNode){
4298 this.onNodeOut(this.lastOverNode, dd, e, data);
4299 this.lastOverNode = null;
4301 return this.onContainerOver(dd, e, data);
4303 if(this.lastOverNode != n){
4304 if(this.lastOverNode){
4305 this.onNodeOut(this.lastOverNode, dd, e, data);
4307 this.onNodeEnter(n, dd, e, data);
4308 this.lastOverNode = n;
4310 return this.onNodeOver(n, dd, e, data);
4314 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
4315 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
4316 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
4317 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
4318 * @param {Event} e The event
4319 * @param {Object} data An object containing arbitrary data supplied by the drag zone
4321 notifyOut : function(dd, e, data){
4322 if(this.lastOverNode){
4323 this.onNodeOut(this.lastOverNode, dd, e, data);
4324 this.lastOverNode = null;
4329 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
4330 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
4331 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
4332 * otherwise it will call {@link #onContainerDrop}.
4333 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
4334 * @param {Event} e The event
4335 * @param {Object} data An object containing arbitrary data supplied by the drag source
4336 * @return {Boolean} True if the drop was valid, else false
4338 notifyDrop : function(dd, e, data){
4339 if(this.lastOverNode){
4340 this.onNodeOut(this.lastOverNode, dd, e, data);
4341 this.lastOverNode = null;
4343 var n = this.getTargetFromEvent(e);
4345 this.onNodeDrop(n, dd, e, data) :
4346 this.onContainerDrop(dd, e, data);
4350 triggerCacheRefresh : function(){
4351 Roo.dd.DDM.refreshCache(this.groups);
4355 * Ext JS Library 1.1.1
4356 * Copyright(c) 2006-2007, Ext JS, LLC.
4358 * Originally Released Under LGPL - original licence link has changed is not relivant.
4361 * <script type="text/javascript">
4366 * @class Roo.data.SortTypes
4368 * Defines the default sorting (casting?) comparison functions used when sorting data.
4370 Roo.data.SortTypes = {
4372 * Default sort that does nothing
4373 * @param {Mixed} s The value being converted
4374 * @return {Mixed} The comparison value
4381 * The regular expression used to strip tags
4385 stripTagsRE : /<\/?[^>]+>/gi,
4388 * Strips all HTML tags to sort on text only
4389 * @param {Mixed} s The value being converted
4390 * @return {String} The comparison value
4392 asText : function(s){
4393 return String(s).replace(this.stripTagsRE, "");
4397 * Strips all HTML tags to sort on text only - Case insensitive
4398 * @param {Mixed} s The value being converted
4399 * @return {String} The comparison value
4401 asUCText : function(s){
4402 return String(s).toUpperCase().replace(this.stripTagsRE, "");
4406 * Case insensitive string
4407 * @param {Mixed} s The value being converted
4408 * @return {String} The comparison value
4410 asUCString : function(s) {
4411 return String(s).toUpperCase();
4416 * @param {Mixed} s The value being converted
4417 * @return {Number} The comparison value
4419 asDate : function(s) {
4423 if(s instanceof Date){
4426 return Date.parse(String(s));
4431 * @param {Mixed} s The value being converted
4432 * @return {Float} The comparison value
4434 asFloat : function(s) {
4435 var val = parseFloat(String(s).replace(/,/g, ""));
4436 if(isNaN(val)) val = 0;
4442 * @param {Mixed} s The value being converted
4443 * @return {Number} The comparison value
4445 asInt : function(s) {
4446 var val = parseInt(String(s).replace(/,/g, ""));
4447 if(isNaN(val)) val = 0;
4452 * Ext JS Library 1.1.1
4453 * Copyright(c) 2006-2007, Ext JS, LLC.
4455 * Originally Released Under LGPL - original licence link has changed is not relivant.
4458 * <script type="text/javascript">
4462 * @class Roo.data.Record
4463 * Instances of this class encapsulate both record <em>definition</em> information, and record
4464 * <em>value</em> information for use in {@link Roo.data.Store} objects, or any code which needs
4465 * to access Records cached in an {@link Roo.data.Store} object.<br>
4467 * Constructors for this class are generated by passing an Array of field definition objects to {@link #create}.
4468 * Instances are usually only created by {@link Roo.data.Reader} implementations when processing unformatted data
4471 * Record objects generated by this constructor inherit all the methods of Roo.data.Record listed below.
4473 * This constructor should not be used to create Record objects. Instead, use the constructor generated by
4474 * {@link #create}. The parameters are the same.
4475 * @param {Array} data An associative Array of data values keyed by the field name.
4476 * @param {Object} id (Optional) The id of the record. This id should be unique, and is used by the
4477 * {@link Roo.data.Store} object which owns the Record to index its collection of Records. If
4478 * not specified an integer id is generated.
4480 Roo.data.Record = function(data, id){
4481 this.id = (id || id === 0) ? id : ++Roo.data.Record.AUTO_ID;
4486 * Generate a constructor for a specific record layout.
4487 * @param {Array} o An Array of field definition objects which specify field names, and optionally,
4488 * data types, and a mapping for an {@link Roo.data.Reader} to extract the field's value from a data object.
4489 * Each field definition object may contain the following properties: <ul>
4490 * <li><b>name</b> : String<p style="margin-left:1em">The name by which the field is referenced within the Record. This is referenced by,
4491 * for example the <em>dataIndex</em> property in column definition objects passed to {@link Roo.grid.ColumnModel}</p></li>
4492 * <li><b>mapping</b> : String<p style="margin-left:1em">(Optional) A path specification for use by the {@link Roo.data.Reader} implementation
4493 * that is creating the Record to access the data value from the data object. If an {@link Roo.data.JsonReader}
4494 * is being used, then this is a string containing the javascript expression to reference the data relative to
4495 * the record item's root. If an {@link Roo.data.XmlReader} is being used, this is an {@link Roo.DomQuery} path
4496 * to the data item relative to the record element. If the mapping expression is the same as the field name,
4497 * this may be omitted.</p></li>
4498 * <li><b>type</b> : String<p style="margin-left:1em">(Optional) The data type for conversion to displayable value. Possible values are
4499 * <ul><li>auto (Default, implies no conversion)</li>
4504 * <li>date</li></ul></p></li>
4505 * <li><b>sortType</b> : Mixed<p style="margin-left:1em">(Optional) A member of {@link Roo.data.SortTypes}.</p></li>
4506 * <li><b>sortDir</b> : String<p style="margin-left:1em">(Optional) Initial direction to sort. "ASC" or "DESC"</p></li>
4507 * <li><b>convert</b> : Function<p style="margin-left:1em">(Optional) A function which converts the value provided
4508 * by the Reader into an object that will be stored in the Record. It is passed the
4509 * following parameters:<ul>
4510 * <li><b>v</b> : Mixed<p style="margin-left:1em">The data value as read by the Reader.</p></li>
4512 * <li><b>dateFormat</b> : String<p style="margin-left:1em">(Optional) A format String for the Date.parseDate function.</p></li>
4514 * <br>usage:<br><pre><code>
4515 var TopicRecord = Roo.data.Record.create(
4516 {name: 'title', mapping: 'topic_title'},
4517 {name: 'author', mapping: 'username'},
4518 {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
4519 {name: 'lastPost', mapping: 'post_time', type: 'date'},
4520 {name: 'lastPoster', mapping: 'user2'},
4521 {name: 'excerpt', mapping: 'post_text'}
4524 var myNewRecord = new TopicRecord({
4525 title: 'Do my job please',
4528 lastPost: new Date(),
4529 lastPoster: 'Animal',
4530 excerpt: 'No way dude!'
4532 myStore.add(myNewRecord);
4537 Roo.data.Record.create = function(o){
4539 f.superclass.constructor.apply(this, arguments);
4541 Roo.extend(f, Roo.data.Record);
4542 var p = f.prototype;
4543 p.fields = new Roo.util.MixedCollection(false, function(field){
4546 for(var i = 0, len = o.length; i < len; i++){
4547 p.fields.add(new Roo.data.Field(o[i]));
4549 f.getField = function(name){
4550 return p.fields.get(name);
4555 Roo.data.Record.AUTO_ID = 1000;
4556 Roo.data.Record.EDIT = 'edit';
4557 Roo.data.Record.REJECT = 'reject';
4558 Roo.data.Record.COMMIT = 'commit';
4560 Roo.data.Record.prototype = {
4562 * Readonly flag - true if this record has been modified.
4571 join : function(store){
4576 * Set the named field to the specified value.
4577 * @param {String} name The name of the field to set.
4578 * @param {Object} value The value to set the field to.
4580 set : function(name, value){
4581 if(this.data[name] == value){
4588 if(typeof this.modified[name] == 'undefined'){
4589 this.modified[name] = this.data[name];
4591 this.data[name] = value;
4593 this.store.afterEdit(this);
4598 * Get the value of the named field.
4599 * @param {String} name The name of the field to get the value of.
4600 * @return {Object} The value of the field.
4602 get : function(name){
4603 return this.data[name];
4607 beginEdit : function(){
4608 this.editing = true;
4613 cancelEdit : function(){
4614 this.editing = false;
4615 delete this.modified;
4619 endEdit : function(){
4620 this.editing = false;
4621 if(this.dirty && this.store){
4622 this.store.afterEdit(this);
4627 * Usually called by the {@link Roo.data.Store} which owns the Record.
4628 * Rejects all changes made to the Record since either creation, or the last commit operation.
4629 * Modified fields are reverted to their original values.
4631 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
4632 * of reject operations.
4634 reject : function(){
4635 var m = this.modified;
4637 if(typeof m[n] != "function"){
4638 this.data[n] = m[n];
4642 delete this.modified;
4643 this.editing = false;
4645 this.store.afterReject(this);
4650 * Usually called by the {@link Roo.data.Store} which owns the Record.
4651 * Commits all changes made to the Record since either creation, or the last commit operation.
4653 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
4654 * of commit operations.
4656 commit : function(){
4658 delete this.modified;
4659 this.editing = false;
4661 this.store.afterCommit(this);
4666 hasError : function(){
4667 return this.error != null;
4671 clearError : function(){
4676 * Creates a copy of this record.
4677 * @param {String} id (optional) A new record id if you don't want to use this record's id
4680 copy : function(newId) {
4681 return new this.constructor(Roo.apply({}, this.data), newId || this.id);
4685 * Ext JS Library 1.1.1
4686 * Copyright(c) 2006-2007, Ext JS, LLC.
4688 * Originally Released Under LGPL - original licence link has changed is not relivant.
4691 * <script type="text/javascript">
4697 * @class Roo.data.Store
4698 * @extends Roo.util.Observable
4699 * The Store class encapsulates a client side cache of {@link Roo.data.Record} objects which provide input data
4700 * for widgets such as the Roo.grid.Grid, or the Roo.form.ComboBox.<br>
4702 * A Store object uses an implementation of {@link Roo.data.DataProxy} to access a data object unless you call loadData() directly and pass in your data. The Store object
4703 * has no knowledge of the format of the data returned by the Proxy.<br>
4705 * A Store object uses its configured implementation of {@link Roo.data.DataReader} to create {@link Roo.data.Record}
4706 * instances from the data object. These records are cached and made available through accessor functions.
4708 * Creates a new Store.
4709 * @param {Object} config A config object containing the objects needed for the Store to access data,
4710 * and read the data into Records.
4712 Roo.data.Store = function(config){
4713 this.data = new Roo.util.MixedCollection(false);
4714 this.data.getKey = function(o){
4717 this.baseParams = {};
4726 if(config && config.data){
4727 this.inlineData = config.data;
4731 Roo.apply(this, config);
4733 if(this.reader){ // reader passed
4734 this.reader = Roo.factory(this.reader, Roo.data);
4735 this.reader.xmodule = this.xmodule || false;
4736 if(!this.recordType){
4737 this.recordType = this.reader.recordType;
4739 if(this.reader.onMetaChange){
4740 this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
4744 if(this.recordType){
4745 this.fields = this.recordType.prototype.fields;
4751 * @event datachanged
4752 * Fires when the data cache has changed, and a widget which is using this Store
4753 * as a Record cache should refresh its view.
4754 * @param {Store} this
4759 * Fires when this store's reader provides new metadata (fields). This is currently only support for JsonReaders.
4760 * @param {Store} this
4761 * @param {Object} meta The JSON metadata
4766 * Fires when Records have been added to the Store
4767 * @param {Store} this
4768 * @param {Roo.data.Record[]} records The array of Records added
4769 * @param {Number} index The index at which the record(s) were added
4774 * Fires when a Record has been removed from the Store
4775 * @param {Store} this
4776 * @param {Roo.data.Record} record The Record that was removed
4777 * @param {Number} index The index at which the record was removed
4782 * Fires when a Record has been updated
4783 * @param {Store} this
4784 * @param {Roo.data.Record} record The Record that was updated
4785 * @param {String} operation The update operation being performed. Value may be one of:
4787 Roo.data.Record.EDIT
4788 Roo.data.Record.REJECT
4789 Roo.data.Record.COMMIT
4795 * Fires when the data cache has been cleared.
4796 * @param {Store} this
4801 * Fires before a request is made for a new data object. If the beforeload handler returns false
4802 * the load action will be canceled.
4803 * @param {Store} this
4804 * @param {Object} options The loading options that were specified (see {@link #load} for details)
4809 * Fires after a new set of Records has been loaded.
4810 * @param {Store} this
4811 * @param {Roo.data.Record[]} records The Records that were loaded
4812 * @param {Object} options The loading options that were specified (see {@link #load} for details)
4816 * @event loadexception
4817 * Fires if an exception occurs in the Proxy during loading.
4818 * Called with the signature of the Proxy's "loadexception" event.
4819 * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
4822 * @param {Object} return from JsonData.reader() - success, totalRecords, records
4823 * @param {Object} load options
4824 * @param {Object} jsonData from your request (normally this contains the Exception)
4826 loadexception : true
4830 this.proxy = Roo.factory(this.proxy, Roo.data);
4831 this.proxy.xmodule = this.xmodule || false;
4832 this.relayEvents(this.proxy, ["loadexception"]);
4834 this.sortToggle = {};
4836 Roo.data.Store.superclass.constructor.call(this);
4838 if(this.inlineData){
4839 this.loadData(this.inlineData);
4840 delete this.inlineData;
4843 Roo.extend(Roo.data.Store, Roo.util.Observable, {
4845 * @cfg {boolean} isLocal flag if data is locally available (and can be always looked up
4846 * without a remote query - used by combo/forms at present.
4850 * @cfg {Roo.data.DataProxy} proxy The Proxy object which provides access to a data object.
4853 * @cfg {Array} data Inline data to be loaded when the store is initialized.
4856 * @cfg {Roo.data.Reader} reader The Reader object which processes the data object and returns
4857 * an Array of Roo.data.record objects which are cached keyed by their <em>id</em> property.
4860 * @cfg {Object} baseParams An object containing properties which are to be sent as parameters
4861 * on any HTTP request
4864 * @cfg {Object} sortInfo A config object in the format: {field: "fieldName", direction: "ASC|DESC"}
4867 * @cfg {boolean} remoteSort True if sorting is to be handled by requesting the Proxy to provide a refreshed
4868 * version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false).
4873 * @cfg {boolean} pruneModifiedRecords True to clear all modified record information each time the store is
4874 * loaded or when a record is removed. (defaults to false).
4876 pruneModifiedRecords : false,
4882 * Add Records to the Store and fires the add event.
4883 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
4885 add : function(records){
4886 records = [].concat(records);
4887 for(var i = 0, len = records.length; i < len; i++){
4888 records[i].join(this);
4890 var index = this.data.length;
4891 this.data.addAll(records);
4892 this.fireEvent("add", this, records, index);
4896 * Remove a Record from the Store and fires the remove event.
4897 * @param {Ext.data.Record} record The Roo.data.Record object to remove from the cache.
4899 remove : function(record){
4900 var index = this.data.indexOf(record);
4901 this.data.removeAt(index);
4902 if(this.pruneModifiedRecords){
4903 this.modified.remove(record);
4905 this.fireEvent("remove", this, record, index);
4909 * Remove all Records from the Store and fires the clear event.
4911 removeAll : function(){
4913 if(this.pruneModifiedRecords){
4916 this.fireEvent("clear", this);
4920 * Inserts Records to the Store at the given index and fires the add event.
4921 * @param {Number} index The start index at which to insert the passed Records.
4922 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
4924 insert : function(index, records){
4925 records = [].concat(records);
4926 for(var i = 0, len = records.length; i < len; i++){
4927 this.data.insert(index, records[i]);
4928 records[i].join(this);
4930 this.fireEvent("add", this, records, index);
4934 * Get the index within the cache of the passed Record.
4935 * @param {Roo.data.Record} record The Roo.data.Record object to to find.
4936 * @return {Number} The index of the passed Record. Returns -1 if not found.
4938 indexOf : function(record){
4939 return this.data.indexOf(record);
4943 * Get the index within the cache of the Record with the passed id.
4944 * @param {String} id The id of the Record to find.
4945 * @return {Number} The index of the Record. Returns -1 if not found.
4947 indexOfId : function(id){
4948 return this.data.indexOfKey(id);
4952 * Get the Record with the specified id.
4953 * @param {String} id The id of the Record to find.
4954 * @return {Roo.data.Record} The Record with the passed id. Returns undefined if not found.
4956 getById : function(id){
4957 return this.data.key(id);
4961 * Get the Record at the specified index.
4962 * @param {Number} index The index of the Record to find.
4963 * @return {Roo.data.Record} The Record at the passed index. Returns undefined if not found.
4965 getAt : function(index){
4966 return this.data.itemAt(index);
4970 * Returns a range of Records between specified indices.
4971 * @param {Number} startIndex (optional) The starting index (defaults to 0)
4972 * @param {Number} endIndex (optional) The ending index (defaults to the last Record in the Store)
4973 * @return {Roo.data.Record[]} An array of Records
4975 getRange : function(start, end){
4976 return this.data.getRange(start, end);
4980 storeOptions : function(o){
4981 o = Roo.apply({}, o);
4984 this.lastOptions = o;
4988 * Loads the Record cache from the configured Proxy using the configured Reader.
4990 * If using remote paging, then the first load call must specify the <em>start</em>
4991 * and <em>limit</em> properties in the options.params property to establish the initial
4992 * position within the dataset, and the number of Records to cache on each read from the Proxy.
4994 * <strong>It is important to note that for remote data sources, loading is asynchronous,
4995 * and this call will return before the new data has been loaded. Perform any post-processing
4996 * in a callback function, or in a "load" event handler.</strong>
4998 * @param {Object} options An object containing properties which control loading options:<ul>
4999 * <li>params {Object} An object containing properties to pass as HTTP parameters to a remote data source.</li>
5000 * <li>callback {Function} A function to be called after the Records have been loaded. The callback is
5001 * passed the following arguments:<ul>
5002 * <li>r : Roo.data.Record[]</li>
5003 * <li>options: Options object from the load call</li>
5004 * <li>success: Boolean success indicator</li></ul></li>
5005 * <li>scope {Object} Scope with which to call the callback (defaults to the Store object)</li>
5006 * <li>add {Boolean} indicator to append loaded records rather than replace the current cache.</li>
5009 load : function(options){
5010 options = options || {};
5011 if(this.fireEvent("beforeload", this, options) !== false){
5012 this.storeOptions(options);
5013 var p = Roo.apply(options.params || {}, this.baseParams);
5014 // if meta was not loaded from remote source.. try requesting it.
5015 if (!this.reader.metaFromRemote) {
5018 if(this.sortInfo && this.remoteSort){
5019 var pn = this.paramNames;
5020 p[pn["sort"]] = this.sortInfo.field;
5021 p[pn["dir"]] = this.sortInfo.direction;
5023 this.proxy.load(p, this.reader, this.loadRecords, this, options);
5028 * Reloads the Record cache from the configured Proxy using the configured Reader and
5029 * the options from the last load operation performed.
5030 * @param {Object} options (optional) An object containing properties which may override the options
5031 * used in the last load operation. See {@link #load} for details (defaults to null, in which case
5032 * the most recently used options are reused).
5034 reload : function(options){
5035 this.load(Roo.applyIf(options||{}, this.lastOptions));
5039 // Called as a callback by the Reader during a load operation.
5040 loadRecords : function(o, options, success){
5041 if(!o || success === false){
5042 if(success !== false){
5043 this.fireEvent("load", this, [], options);
5045 if(options.callback){
5046 options.callback.call(options.scope || this, [], options, false);
5050 // if data returned failure - throw an exception.
5051 if (o.success === false) {
5052 this.fireEvent("loadexception", this, o, options, this.reader.jsonData);
5055 var r = o.records, t = o.totalRecords || r.length;
5056 if(!options || options.add !== true){
5057 if(this.pruneModifiedRecords){
5060 for(var i = 0, len = r.length; i < len; i++){
5064 this.data = this.snapshot;
5065 delete this.snapshot;
5068 this.data.addAll(r);
5069 this.totalLength = t;
5071 this.fireEvent("datachanged", this);
5073 this.totalLength = Math.max(t, this.data.length+r.length);
5076 this.fireEvent("load", this, r, options);
5077 if(options.callback){
5078 options.callback.call(options.scope || this, r, options, true);
5083 * Loads data from a passed data block. A Reader which understands the format of the data
5084 * must have been configured in the constructor.
5085 * @param {Object} data The data block from which to read the Records. The format of the data expected
5086 * is dependent on the type of Reader that is configured and should correspond to that Reader's readRecords parameter.
5087 * @param {Boolean} append (Optional) True to append the new Records rather than replace the existing cache.
5089 loadData : function(o, append){
5090 var r = this.reader.readRecords(o);
5091 this.loadRecords(r, {add: append}, true);
5095 * Gets the number of cached records.
5097 * <em>If using paging, this may not be the total size of the dataset. If the data object
5098 * used by the Reader contains the dataset size, then the getTotalCount() function returns
5099 * the data set size</em>
5101 getCount : function(){
5102 return this.data.length || 0;
5106 * Gets the total number of records in the dataset as returned by the server.
5108 * <em>If using paging, for this to be accurate, the data object used by the Reader must contain
5109 * the dataset size</em>
5111 getTotalCount : function(){
5112 return this.totalLength || 0;
5116 * Returns the sort state of the Store as an object with two properties:
5118 field {String} The name of the field by which the Records are sorted
5119 direction {String} The sort order, "ASC" or "DESC"
5122 getSortState : function(){
5123 return this.sortInfo;
5127 applySort : function(){
5128 if(this.sortInfo && !this.remoteSort){
5129 var s = this.sortInfo, f = s.field;
5130 var st = this.fields.get(f).sortType;
5131 var fn = function(r1, r2){
5132 var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
5133 return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
5135 this.data.sort(s.direction, fn);
5136 if(this.snapshot && this.snapshot != this.data){
5137 this.snapshot.sort(s.direction, fn);
5143 * Sets the default sort column and order to be used by the next load operation.
5144 * @param {String} fieldName The name of the field to sort by.
5145 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
5147 setDefaultSort : function(field, dir){
5148 this.sortInfo = {field: field, direction: dir ? dir.toUpperCase() : "ASC"};
5153 * If remote sorting is used, the sort is performed on the server, and the cache is
5154 * reloaded. If local sorting is used, the cache is sorted internally.
5155 * @param {String} fieldName The name of the field to sort by.
5156 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
5158 sort : function(fieldName, dir){
5159 var f = this.fields.get(fieldName);
5161 if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
5162 dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
5167 this.sortToggle[f.name] = dir;
5168 this.sortInfo = {field: f.name, direction: dir};
5169 if(!this.remoteSort){
5171 this.fireEvent("datachanged", this);
5173 this.load(this.lastOptions);
5178 * Calls the specified function for each of the Records in the cache.
5179 * @param {Function} fn The function to call. The Record is passed as the first parameter.
5180 * Returning <em>false</em> aborts and exits the iteration.
5181 * @param {Object} scope (optional) The scope in which to call the function (defaults to the Record).
5183 each : function(fn, scope){
5184 this.data.each(fn, scope);
5188 * Gets all records modified since the last commit. Modified records are persisted across load operations
5189 * (e.g., during paging).
5190 * @return {Roo.data.Record[]} An array of Records containing outstanding modifications.
5192 getModifiedRecords : function(){
5193 return this.modified;
5197 createFilterFn : function(property, value, anyMatch){
5198 if(!value.exec){ // not a regex
5199 value = String(value);
5200 if(value.length == 0){
5203 value = new RegExp((anyMatch === true ? '' : '^') + Roo.escapeRe(value), "i");
5206 return value.test(r.data[property]);
5211 * Sums the value of <i>property</i> for each record between start and end and returns the result.
5212 * @param {String} property A field on your records
5213 * @param {Number} start The record index to start at (defaults to 0)
5214 * @param {Number} end The last record index to include (defaults to length - 1)
5215 * @return {Number} The sum
5217 sum : function(property, start, end){
5218 var rs = this.data.items, v = 0;
5220 end = (end || end === 0) ? end : rs.length-1;
5222 for(var i = start; i <= end; i++){
5223 v += (rs[i].data[property] || 0);
5229 * Filter the records by a specified property.
5230 * @param {String} field A field on your records
5231 * @param {String/RegExp} value Either a string that the field
5232 * should start with or a RegExp to test against the field
5233 * @param {Boolean} anyMatch True to match any part not just the beginning
5235 filter : function(property, value, anyMatch){
5236 var fn = this.createFilterFn(property, value, anyMatch);
5237 return fn ? this.filterBy(fn) : this.clearFilter();
5241 * Filter by a function. The specified function will be called with each
5242 * record in this data source. If the function returns true the record is included,
5243 * otherwise it is filtered.
5244 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
5245 * @param {Object} scope (optional) The scope of the function (defaults to this)
5247 filterBy : function(fn, scope){
5248 this.snapshot = this.snapshot || this.data;
5249 this.data = this.queryBy(fn, scope||this);
5250 this.fireEvent("datachanged", this);
5254 * Query the records by a specified property.
5255 * @param {String} field A field on your records
5256 * @param {String/RegExp} value Either a string that the field
5257 * should start with or a RegExp to test against the field
5258 * @param {Boolean} anyMatch True to match any part not just the beginning
5259 * @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
5261 query : function(property, value, anyMatch){
5262 var fn = this.createFilterFn(property, value, anyMatch);
5263 return fn ? this.queryBy(fn) : this.data.clone();
5267 * Query by a function. The specified function will be called with each
5268 * record in this data source. If the function returns true the record is included
5270 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
5271 * @param {Object} scope (optional) The scope of the function (defaults to this)
5272 @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
5274 queryBy : function(fn, scope){
5275 var data = this.snapshot || this.data;
5276 return data.filterBy(fn, scope||this);
5280 * Collects unique values for a particular dataIndex from this store.
5281 * @param {String} dataIndex The property to collect
5282 * @param {Boolean} allowNull (optional) Pass true to allow null, undefined or empty string values
5283 * @param {Boolean} bypassFilter (optional) Pass true to collect from all records, even ones which are filtered
5284 * @return {Array} An array of the unique values
5286 collect : function(dataIndex, allowNull, bypassFilter){
5287 var d = (bypassFilter === true && this.snapshot) ?
5288 this.snapshot.items : this.data.items;
5289 var v, sv, r = [], l = {};
5290 for(var i = 0, len = d.length; i < len; i++){
5291 v = d[i].data[dataIndex];
5293 if((allowNull || !Roo.isEmpty(v)) && !l[sv]){
5302 * Revert to a view of the Record cache with no filtering applied.
5303 * @param {Boolean} suppressEvent If true the filter is cleared silently without notifying listeners
5305 clearFilter : function(suppressEvent){
5306 if(this.snapshot && this.snapshot != this.data){
5307 this.data = this.snapshot;
5308 delete this.snapshot;
5309 if(suppressEvent !== true){
5310 this.fireEvent("datachanged", this);
5316 afterEdit : function(record){
5317 if(this.modified.indexOf(record) == -1){
5318 this.modified.push(record);
5320 this.fireEvent("update", this, record, Roo.data.Record.EDIT);
5324 afterReject : function(record){
5325 this.modified.remove(record);
5326 this.fireEvent("update", this, record, Roo.data.Record.REJECT);
5330 afterCommit : function(record){
5331 this.modified.remove(record);
5332 this.fireEvent("update", this, record, Roo.data.Record.COMMIT);
5336 * Commit all Records with outstanding changes. To handle updates for changes, subscribe to the
5337 * Store's "update" event, and perform updating when the third parameter is Roo.data.Record.COMMIT.
5339 commitChanges : function(){
5340 var m = this.modified.slice(0);
5342 for(var i = 0, len = m.length; i < len; i++){
5348 * Cancel outstanding changes on all changed records.
5350 rejectChanges : function(){
5351 var m = this.modified.slice(0);
5353 for(var i = 0, len = m.length; i < len; i++){
5358 onMetaChange : function(meta, rtype, o){
5359 this.recordType = rtype;
5360 this.fields = rtype.prototype.fields;
5361 delete this.snapshot;
5362 this.sortInfo = meta.sortInfo || this.sortInfo;
5364 this.fireEvent('metachange', this, this.reader.meta);
5368 * Ext JS Library 1.1.1
5369 * Copyright(c) 2006-2007, Ext JS, LLC.
5371 * Originally Released Under LGPL - original licence link has changed is not relivant.
5374 * <script type="text/javascript">
5378 * @class Roo.data.SimpleStore
5379 * @extends Roo.data.Store
5380 * Small helper class to make creating Stores from Array data easier.
5381 * @cfg {Number} id The array index of the record id. Leave blank to auto generate ids.
5382 * @cfg {Array} fields An array of field definition objects, or field name strings.
5383 * @cfg {Array} data The multi-dimensional array of data
5385 * @param {Object} config
5387 Roo.data.SimpleStore = function(config){
5388 Roo.data.SimpleStore.superclass.constructor.call(this, {
5390 reader: new Roo.data.ArrayReader({
5393 Roo.data.Record.create(config.fields)
5395 proxy : new Roo.data.MemoryProxy(config.data)
5399 Roo.extend(Roo.data.SimpleStore, Roo.data.Store);/*
5401 * Ext JS Library 1.1.1
5402 * Copyright(c) 2006-2007, Ext JS, LLC.
5404 * Originally Released Under LGPL - original licence link has changed is not relivant.
5407 * <script type="text/javascript">
5412 * @extends Roo.data.Store
5413 * @class Roo.data.JsonStore
5414 * Small helper class to make creating Stores for JSON data easier. <br/>
5416 var store = new Roo.data.JsonStore({
5417 url: 'get-images.php',
5419 fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}]
5422 * <b>Note: Although they are not listed, this class inherits all of the config options of Store,
5423 * JsonReader and HttpProxy (unless inline data is provided).</b>
5424 * @cfg {Array} fields An array of field definition objects, or field name strings.
5426 * @param {Object} config
5428 Roo.data.JsonStore = function(c){
5429 Roo.data.JsonStore.superclass.constructor.call(this, Roo.apply(c, {
5430 proxy: !c.data ? new Roo.data.HttpProxy({url: c.url}) : undefined,
5431 reader: new Roo.data.JsonReader(c, c.fields)
5434 Roo.extend(Roo.data.JsonStore, Roo.data.Store);/*
5436 * Ext JS Library 1.1.1
5437 * Copyright(c) 2006-2007, Ext JS, LLC.
5439 * Originally Released Under LGPL - original licence link has changed is not relivant.
5442 * <script type="text/javascript">
5446 Roo.data.Field = function(config){
5447 if(typeof config == "string"){
5448 config = {name: config};
5450 Roo.apply(this, config);
5456 var st = Roo.data.SortTypes;
5457 // named sortTypes are supported, here we look them up
5458 if(typeof this.sortType == "string"){
5459 this.sortType = st[this.sortType];
5462 // set default sortType for strings and dates
5466 this.sortType = st.asUCString;
5469 this.sortType = st.asDate;
5472 this.sortType = st.none;
5477 var stripRe = /[\$,%]/g;
5479 // prebuilt conversion function for this field, instead of
5480 // switching every time we're reading a value
5482 var cv, dateFormat = this.dateFormat;
5487 cv = function(v){ return v; };
5490 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
5494 return v !== undefined && v !== null && v !== '' ?
5495 parseInt(String(v).replace(stripRe, ""), 10) : '';
5500 return v !== undefined && v !== null && v !== '' ?
5501 parseFloat(String(v).replace(stripRe, ""), 10) : '';
5506 cv = function(v){ return v === true || v === "true" || v == 1; };
5513 if(v instanceof Date){
5517 if(dateFormat == "timestamp"){
5518 return new Date(v*1000);
5520 return Date.parseDate(v, dateFormat);
5522 var parsed = Date.parse(v);
5523 return parsed ? new Date(parsed) : null;
5532 Roo.data.Field.prototype = {
5540 * Ext JS Library 1.1.1
5541 * Copyright(c) 2006-2007, Ext JS, LLC.
5543 * Originally Released Under LGPL - original licence link has changed is not relivant.
5546 * <script type="text/javascript">
5549 // Base class for reading structured data from a data source. This class is intended to be
5550 // extended (see ArrayReader, JsonReader and XmlReader) and should not be created directly.
5553 * @class Roo.data.DataReader
5554 * Base class for reading structured data from a data source. This class is intended to be
5555 * extended (see {Roo.data.ArrayReader}, {Roo.data.JsonReader} and {Roo.data.XmlReader}) and should not be created directly.
5558 Roo.data.DataReader = function(meta, recordType){
5562 this.recordType = recordType instanceof Array ?
5563 Roo.data.Record.create(recordType) : recordType;
5566 Roo.data.DataReader.prototype = {
5568 * Create an empty record
5569 * @param {Object} data (optional) - overlay some values
5570 * @return {Roo.data.Record} record created.
5572 newRow : function(d) {
5574 this.recordType.prototype.fields.each(function(c) {
5576 case 'int' : da[c.name] = 0; break;
5577 case 'date' : da[c.name] = new Date(); break;
5578 case 'float' : da[c.name] = 0.0; break;
5579 case 'boolean' : da[c.name] = false; break;
5580 default : da[c.name] = ""; break;
5584 return new this.recordType(Roo.apply(da, d));
5589 * Ext JS Library 1.1.1
5590 * Copyright(c) 2006-2007, Ext JS, LLC.
5592 * Originally Released Under LGPL - original licence link has changed is not relivant.
5595 * <script type="text/javascript">
5599 * @class Roo.data.DataProxy
5600 * @extends Roo.data.Observable
5601 * This class is an abstract base class for implementations which provide retrieval of
5602 * unformatted data objects.<br>
5604 * DataProxy implementations are usually used in conjunction with an implementation of Roo.data.DataReader
5605 * (of the appropriate type which knows how to parse the data object) to provide a block of
5606 * {@link Roo.data.Records} to an {@link Roo.data.Store}.<br>
5608 * Custom implementations must implement the load method as described in
5609 * {@link Roo.data.HttpProxy#load}.
5611 Roo.data.DataProxy = function(){
5615 * Fires before a network request is made to retrieve a data object.
5616 * @param {Object} This DataProxy object.
5617 * @param {Object} params The params parameter to the load function.
5622 * Fires before the load method's callback is called.
5623 * @param {Object} This DataProxy object.
5624 * @param {Object} o The data object.
5625 * @param {Object} arg The callback argument object passed to the load function.
5629 * @event loadexception
5630 * Fires if an Exception occurs during data retrieval.
5631 * @param {Object} This DataProxy object.
5632 * @param {Object} o The data object.
5633 * @param {Object} arg The callback argument object passed to the load function.
5634 * @param {Object} e The Exception.
5636 loadexception : true
5638 Roo.data.DataProxy.superclass.constructor.call(this);
5641 Roo.extend(Roo.data.DataProxy, Roo.util.Observable);
5644 * @cfg {void} listeners (Not available) Constructor blocks listeners from being set
5648 * Ext JS Library 1.1.1
5649 * Copyright(c) 2006-2007, Ext JS, LLC.
5651 * Originally Released Under LGPL - original licence link has changed is not relivant.
5654 * <script type="text/javascript">
5657 * @class Roo.data.MemoryProxy
5658 * An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
5659 * to the Reader when its load method is called.
5661 * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
5663 Roo.data.MemoryProxy = function(data){
5667 Roo.data.MemoryProxy.superclass.constructor.call(this);
5671 Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
5673 * Load data from the requested source (in this case an in-memory
5674 * data object passed to the constructor), read the data object into
5675 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
5676 * process that block using the passed callback.
5677 * @param {Object} params This parameter is not used by the MemoryProxy class.
5678 * @param {Roo.data.DataReader} reader The Reader object which converts the data
5679 * object into a block of Roo.data.Records.
5680 * @param {Function} callback The function into which to pass the block of Roo.data.records.
5681 * The function must be passed <ul>
5682 * <li>The Record block object</li>
5683 * <li>The "arg" argument from the load function</li>
5684 * <li>A boolean success indicator</li>
5686 * @param {Object} scope The scope in which to call the callback
5687 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
5689 load : function(params, reader, callback, scope, arg){
5690 params = params || {};
5693 result = reader.readRecords(this.data);
5695 this.fireEvent("loadexception", this, arg, null, e);
5696 callback.call(scope, null, arg, false);
5699 callback.call(scope, result, arg, true);
5703 update : function(params, records){
5708 * Ext JS Library 1.1.1
5709 * Copyright(c) 2006-2007, Ext JS, LLC.
5711 * Originally Released Under LGPL - original licence link has changed is not relivant.
5714 * <script type="text/javascript">
5717 * @class Roo.data.HttpProxy
5718 * @extends Roo.data.DataProxy
5719 * An implementation of {@link Roo.data.DataProxy} that reads a data object from an {@link Roo.data.Connection} object
5720 * configured to reference a certain URL.<br><br>
5722 * <em>Note that this class cannot be used to retrieve data from a domain other than the domain
5723 * from which the running page was served.<br><br>
5725 * For cross-domain access to remote data, use an {@link Roo.data.ScriptTagProxy}.</em><br><br>
5727 * Be aware that to enable the browser to parse an XML document, the server must set
5728 * the Content-Type header in the HTTP response to "text/xml".
5730 * @param {Object} conn Connection config options to add to each request (e.g. {url: 'foo.php'} or
5731 * an {@link Roo.data.Connection} object. If a Connection config is passed, the singleton {@link Roo.Ajax} object
5732 * will be used to make the request.
5734 Roo.data.HttpProxy = function(conn){
5735 Roo.data.HttpProxy.superclass.constructor.call(this);
5736 // is conn a conn config or a real conn?
5738 this.useAjax = !conn || !conn.events;
5742 Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
5743 // thse are take from connection...
5746 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
5749 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
5750 * extra parameters to each request made by this object. (defaults to undefined)
5753 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
5754 * to each request made by this object. (defaults to undefined)
5757 * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
5760 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
5763 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
5769 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
5773 * Return the {@link Roo.data.Connection} object being used by this Proxy.
5774 * @return {Connection} The Connection object. This object may be used to subscribe to events on
5775 * a finer-grained basis than the DataProxy events.
5777 getConnection : function(){
5778 return this.useAjax ? Roo.Ajax : this.conn;
5782 * Load data from the configured {@link Roo.data.Connection}, read the data object into
5783 * a block of Roo.data.Records using the passed {@link Roo.data.DataReader} implementation, and
5784 * process that block using the passed callback.
5785 * @param {Object} params An object containing properties which are to be used as HTTP parameters
5786 * for the request to the remote server.
5787 * @param {Roo.data.DataReader} reader The Reader object which converts the data
5788 * object into a block of Roo.data.Records.
5789 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
5790 * The function must be passed <ul>
5791 * <li>The Record block object</li>
5792 * <li>The "arg" argument from the load function</li>
5793 * <li>A boolean success indicator</li>
5795 * @param {Object} scope The scope in which to call the callback
5796 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
5798 load : function(params, reader, callback, scope, arg){
5799 if(this.fireEvent("beforeload", this, params) !== false){
5801 params : params || {},
5803 callback : callback,
5808 callback : this.loadResponse,
5812 Roo.applyIf(o, this.conn);
5813 if(this.activeRequest){
5814 Roo.Ajax.abort(this.activeRequest);
5816 this.activeRequest = Roo.Ajax.request(o);
5818 this.conn.request(o);
5821 callback.call(scope||this, null, arg, false);
5826 loadResponse : function(o, success, response){
5827 delete this.activeRequest;
5829 this.fireEvent("loadexception", this, o, response);
5830 o.request.callback.call(o.request.scope, null, o.request.arg, false);
5835 result = o.reader.read(response);
5837 this.fireEvent("loadexception", this, o, response, e);
5838 o.request.callback.call(o.request.scope, null, o.request.arg, false);
5842 this.fireEvent("load", this, o, o.request.arg);
5843 o.request.callback.call(o.request.scope, result, o.request.arg, true);
5847 update : function(dataSet){
5852 updateResponse : function(dataSet){
5857 * Ext JS Library 1.1.1
5858 * Copyright(c) 2006-2007, Ext JS, LLC.
5860 * Originally Released Under LGPL - original licence link has changed is not relivant.
5863 * <script type="text/javascript">
5867 * @class Roo.data.ScriptTagProxy
5868 * An implementation of Roo.data.DataProxy that reads a data object from a URL which may be in a domain
5869 * other than the originating domain of the running page.<br><br>
5871 * <em>Note that if you are retrieving data from a page that is in a domain that is NOT the same as the originating domain
5872 * of the running page, you must use this class, rather than DataProxy.</em><br><br>
5874 * The content passed back from a server resource requested by a ScriptTagProxy is executable JavaScript
5875 * source code that is used as the source inside a <script> tag.<br><br>
5877 * In order for the browser to process the returned data, the server must wrap the data object
5878 * with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
5879 * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
5880 * depending on whether the callback name was passed:
5883 boolean scriptTag = false;
5884 String cb = request.getParameter("callback");
5887 response.setContentType("text/javascript");
5889 response.setContentType("application/x-json");
5891 Writer out = response.getWriter();
5893 out.write(cb + "(");
5895 out.print(dataBlock.toJsonString());
5902 * @param {Object} config A configuration object.
5904 Roo.data.ScriptTagProxy = function(config){
5905 Roo.data.ScriptTagProxy.superclass.constructor.call(this);
5906 Roo.apply(this, config);
5907 this.head = document.getElementsByTagName("head")[0];
5910 Roo.data.ScriptTagProxy.TRANS_ID = 1000;
5912 Roo.extend(Roo.data.ScriptTagProxy, Roo.data.DataProxy, {
5914 * @cfg {String} url The URL from which to request the data object.
5917 * @cfg {Number} timeout (Optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
5921 * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
5922 * the server the name of the callback function set up by the load call to process the returned data object.
5923 * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
5924 * javascript output which calls this named function passing the data object as its only parameter.
5926 callbackParam : "callback",
5928 * @cfg {Boolean} nocache (Optional) Defaults to true. Disable cacheing by adding a unique parameter
5929 * name to the request.
5934 * Load data from the configured URL, read the data object into
5935 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
5936 * process that block using the passed callback.
5937 * @param {Object} params An object containing properties which are to be used as HTTP parameters
5938 * for the request to the remote server.
5939 * @param {Roo.data.DataReader} reader The Reader object which converts the data
5940 * object into a block of Roo.data.Records.
5941 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
5942 * The function must be passed <ul>
5943 * <li>The Record block object</li>
5944 * <li>The "arg" argument from the load function</li>
5945 * <li>A boolean success indicator</li>
5947 * @param {Object} scope The scope in which to call the callback
5948 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
5950 load : function(params, reader, callback, scope, arg){
5951 if(this.fireEvent("beforeload", this, params) !== false){
5953 var p = Roo.urlEncode(Roo.apply(params, this.extraParams));
5956 url += (url.indexOf("?") != -1 ? "&" : "?") + p;
5958 url += "&_dc=" + (new Date().getTime());
5960 var transId = ++Roo.data.ScriptTagProxy.TRANS_ID;
5963 cb : "stcCallback"+transId,
5964 scriptId : "stcScript"+transId,
5968 callback : callback,
5974 window[trans.cb] = function(o){
5975 conn.handleResponse(o, trans);
5978 url += String.format("&{0}={1}", this.callbackParam, trans.cb);
5980 if(this.autoAbort !== false){
5984 trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
5986 var script = document.createElement("script");
5987 script.setAttribute("src", url);
5988 script.setAttribute("type", "text/javascript");
5989 script.setAttribute("id", trans.scriptId);
5990 this.head.appendChild(script);
5994 callback.call(scope||this, null, arg, false);
5999 isLoading : function(){
6000 return this.trans ? true : false;
6004 * Abort the current server request.
6007 if(this.isLoading()){
6008 this.destroyTrans(this.trans);
6013 destroyTrans : function(trans, isLoaded){
6014 this.head.removeChild(document.getElementById(trans.scriptId));
6015 clearTimeout(trans.timeoutId);
6017 window[trans.cb] = undefined;
6019 delete window[trans.cb];
6022 // if hasn't been loaded, wait for load to remove it to prevent script error
6023 window[trans.cb] = function(){
6024 window[trans.cb] = undefined;
6026 delete window[trans.cb];
6033 handleResponse : function(o, trans){
6035 this.destroyTrans(trans, true);
6038 result = trans.reader.readRecords(o);
6040 this.fireEvent("loadexception", this, o, trans.arg, e);
6041 trans.callback.call(trans.scope||window, null, trans.arg, false);
6044 this.fireEvent("load", this, o, trans.arg);
6045 trans.callback.call(trans.scope||window, result, trans.arg, true);
6049 handleFailure : function(trans){
6051 this.destroyTrans(trans, false);
6052 this.fireEvent("loadexception", this, null, trans.arg);
6053 trans.callback.call(trans.scope||window, null, trans.arg, false);
6057 * Ext JS Library 1.1.1
6058 * Copyright(c) 2006-2007, Ext JS, LLC.
6060 * Originally Released Under LGPL - original licence link has changed is not relivant.
6063 * <script type="text/javascript">
6067 * @class Roo.data.JsonReader
6068 * @extends Roo.data.DataReader
6069 * Data reader class to create an Array of Roo.data.Record objects from a JSON response
6070 * based on mappings in a provided Roo.data.Record constructor.
6072 * The default behaviour of a store is to send ?_requestMeta=1, unless the class has recieved 'metaData' property
6073 * in the reply previously.
6078 var RecordDef = Roo.data.Record.create([
6079 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
6080 {name: 'occupation'} // This field will use "occupation" as the mapping.
6082 var myReader = new Roo.data.JsonReader({
6083 totalProperty: "results", // The property which contains the total dataset size (optional)
6084 root: "rows", // The property which contains an Array of row objects
6085 id: "id" // The property within each row object that provides an ID for the record (optional)
6089 * This would consume a JSON file like this:
6091 { 'results': 2, 'rows': [
6092 { 'id': 1, 'name': 'Bill', occupation: 'Gardener' },
6093 { 'id': 2, 'name': 'Ben', occupation: 'Horticulturalist' } ]
6096 * @cfg {String} totalProperty Name of the property from which to retrieve the total number of records
6097 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
6098 * paged from the remote server.
6099 * @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
6100 * @cfg {String} root name of the property which contains the Array of row objects.
6101 * @cfg {String} id Name of the property within a row object that contains a record identifier value.
6103 * Create a new JsonReader
6104 * @param {Object} meta Metadata configuration options
6105 * @param {Object} recordType Either an Array of field definition objects,
6106 * or an {@link Roo.data.Record} object created using {@link Roo.data.Record#create}.
6108 Roo.data.JsonReader = function(meta, recordType){
6111 // set some defaults:
6113 totalProperty: 'total',
6114 successProperty : 'success',
6119 Roo.data.JsonReader.superclass.constructor.call(this, meta, recordType||meta.fields);
6121 Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
6124 * @prop {Boolean} metaFromRemote - if the meta data was loaded from the remote source.
6125 * Used by Store query builder to append _requestMeta to params.
6128 metaFromRemote : false,
6130 * This method is only used by a DataProxy which has retrieved data from a remote server.
6131 * @param {Object} response The XHR object which contains the JSON data in its responseText.
6132 * @return {Object} data A data block which is used by an Roo.data.Store object as
6133 * a cache of Roo.data.Records.
6135 read : function(response){
6136 var json = response.responseText;
6138 var o = /* eval:var:o */ eval("("+json+")");
6140 throw {message: "JsonReader.read: Json object not found"};
6146 this.metaFromRemote = true;
6147 this.meta = o.metaData;
6148 this.recordType = Roo.data.Record.create(o.metaData.fields);
6149 this.onMetaChange(this.meta, this.recordType, o);
6151 return this.readRecords(o);
6154 // private function a store will implement
6155 onMetaChange : function(meta, recordType, o){
6162 simpleAccess: function(obj, subsc) {
6169 getJsonAccessor: function(){
6171 return function(expr) {
6173 return(re.test(expr))
6174 ? new Function("obj", "return obj." + expr)
6184 * Create a data block containing Roo.data.Records from an XML document.
6185 * @param {Object} o An object which contains an Array of row objects in the property specified
6186 * in the config as 'root, and optionally a property, specified in the config as 'totalProperty'
6187 * which contains the total size of the dataset.
6188 * @return {Object} data A data block which is used by an Roo.data.Store object as
6189 * a cache of Roo.data.Records.
6191 readRecords : function(o){
6193 * After any data loads, the raw JSON data is available for further custom processing.
6197 var s = this.meta, Record = this.recordType,
6198 f = Record.prototype.fields, fi = f.items, fl = f.length;
6200 // Generate extraction functions for the totalProperty, the root, the id, and for each field
6202 if(s.totalProperty) {
6203 this.getTotal = this.getJsonAccessor(s.totalProperty);
6205 if(s.successProperty) {
6206 this.getSuccess = this.getJsonAccessor(s.successProperty);
6208 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
6210 var g = this.getJsonAccessor(s.id);
6211 this.getId = function(rec) {
6213 return (r === undefined || r === "") ? null : r;
6216 this.getId = function(){return null;};
6219 for(var jj = 0; jj < fl; jj++){
6221 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
6222 this.ef[jj] = this.getJsonAccessor(map);
6226 var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
6227 if(s.totalProperty){
6228 var vt = parseInt(this.getTotal(o), 10);
6233 if(s.successProperty){
6234 var vs = this.getSuccess(o);
6235 if(vs === false || vs === 'false'){
6240 for(var i = 0; i < c; i++){
6243 var id = this.getId(n);
6244 for(var j = 0; j < fl; j++){
6246 var v = this.ef[j](n);
6248 Roo.log('missing convert for ' + f.name);
6252 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
6254 var record = new Record(values, id);
6256 records[i] = record;
6261 totalRecords : totalRecords
6266 * Ext JS Library 1.1.1
6267 * Copyright(c) 2006-2007, Ext JS, LLC.
6269 * Originally Released Under LGPL - original licence link has changed is not relivant.
6272 * <script type="text/javascript">
6276 * @class Roo.data.XmlReader
6277 * @extends Roo.data.DataReader
6278 * Data reader class to create an Array of {@link Roo.data.Record} objects from an XML document
6279 * based on mappings in a provided Roo.data.Record constructor.<br><br>
6281 * <em>Note that in order for the browser to parse a returned XML document, the Content-Type
6282 * header in the HTTP response must be set to "text/xml".</em>
6286 var RecordDef = Roo.data.Record.create([
6287 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
6288 {name: 'occupation'} // This field will use "occupation" as the mapping.
6290 var myReader = new Roo.data.XmlReader({
6291 totalRecords: "results", // The element which contains the total dataset size (optional)
6292 record: "row", // The repeated element which contains row information
6293 id: "id" // The element within the row that provides an ID for the record (optional)
6297 * This would consume an XML file like this:
6301 <results>2</results>
6304 <name>Bill</name>
6305 <occupation>Gardener</occupation>
6309 <name>Ben</name>
6310 <occupation>Horticulturalist</occupation>
6314 * @cfg {String} totalRecords The DomQuery path from which to retrieve the total number of records
6315 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
6316 * paged from the remote server.
6317 * @cfg {String} record The DomQuery path to the repeated element which contains record information.
6318 * @cfg {String} success The DomQuery path to the success attribute used by forms.
6319 * @cfg {String} id The DomQuery path relative from the record element to the element that contains
6320 * a record identifier value.
6322 * Create a new XmlReader
6323 * @param {Object} meta Metadata configuration options
6324 * @param {Mixed} recordType The definition of the data record type to produce. This can be either a valid
6325 * Record subclass created with {@link Roo.data.Record#create}, or an array of objects with which to call
6326 * Roo.data.Record.create. See the {@link Roo.data.Record} class for more details.
6328 Roo.data.XmlReader = function(meta, recordType){
6330 Roo.data.XmlReader.superclass.constructor.call(this, meta, recordType||meta.fields);
6332 Roo.extend(Roo.data.XmlReader, Roo.data.DataReader, {
6334 * This method is only used by a DataProxy which has retrieved data from a remote server.
6335 * @param {Object} response The XHR object which contains the parsed XML document. The response is expected
6336 * to contain a method called 'responseXML' that returns an XML document object.
6337 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
6338 * a cache of Roo.data.Records.
6340 read : function(response){
6341 var doc = response.responseXML;
6343 throw {message: "XmlReader.read: XML Document not available"};
6345 return this.readRecords(doc);
6349 * Create a data block containing Roo.data.Records from an XML document.
6350 * @param {Object} doc A parsed XML document.
6351 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
6352 * a cache of Roo.data.Records.
6354 readRecords : function(doc){
6356 * After any data loads/reads, the raw XML Document is available for further custom processing.
6360 var root = doc.documentElement || doc;
6361 var q = Roo.DomQuery;
6362 var recordType = this.recordType, fields = recordType.prototype.fields;
6363 var sid = this.meta.id;
6364 var totalRecords = 0, success = true;
6365 if(this.meta.totalRecords){
6366 totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
6369 if(this.meta.success){
6370 var sv = q.selectValue(this.meta.success, root, true);
6371 success = sv !== false && sv !== 'false';
6374 var ns = q.select(this.meta.record, root);
6375 for(var i = 0, len = ns.length; i < len; i++) {
6378 var id = sid ? q.selectValue(sid, n) : undefined;
6379 for(var j = 0, jlen = fields.length; j < jlen; j++){
6380 var f = fields.items[j];
6381 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
6385 var record = new recordType(values, id);
6387 records[records.length] = record;
6393 totalRecords : totalRecords || records.length
6398 * Ext JS Library 1.1.1
6399 * Copyright(c) 2006-2007, Ext JS, LLC.
6401 * Originally Released Under LGPL - original licence link has changed is not relivant.
6404 * <script type="text/javascript">
6408 * @class Roo.data.ArrayReader
6409 * @extends Roo.data.DataReader
6410 * Data reader class to create an Array of Roo.data.Record objects from an Array.
6411 * Each element of that Array represents a row of data fields. The
6412 * fields are pulled into a Record object using as a subscript, the <em>mapping</em> property
6413 * of the field definition if it exists, or the field's ordinal position in the definition.<br>
6417 var RecordDef = Roo.data.Record.create([
6418 {name: 'name', mapping: 1}, // "mapping" only needed if an "id" field is present which
6419 {name: 'occupation', mapping: 2} // precludes using the ordinal position as the index.
6421 var myReader = new Roo.data.ArrayReader({
6422 id: 0 // The subscript within row Array that provides an ID for the Record (optional)
6426 * This would consume an Array like this:
6428 [ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ]
6430 * @cfg {String} id (optional) The subscript within row Array that provides an ID for the Record
6432 * Create a new JsonReader
6433 * @param {Object} meta Metadata configuration options.
6434 * @param {Object} recordType Either an Array of field definition objects
6435 * as specified to {@link Roo.data.Record#create},
6436 * or an {@link Roo.data.Record} object
6437 * created using {@link Roo.data.Record#create}.
6439 Roo.data.ArrayReader = function(meta, recordType){
6440 Roo.data.ArrayReader.superclass.constructor.call(this, meta, recordType);
6443 Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
6445 * Create a data block containing Roo.data.Records from an XML document.
6446 * @param {Object} o An Array of row objects which represents the dataset.
6447 * @return {Object} data A data block which is used by an Roo.data.Store object as
6448 * a cache of Roo.data.Records.
6450 readRecords : function(o){
6451 var sid = this.meta ? this.meta.id : null;
6452 var recordType = this.recordType, fields = recordType.prototype.fields;
6455 for(var i = 0; i < root.length; i++){
6458 var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
6459 for(var j = 0, jlen = fields.length; j < jlen; j++){
6460 var f = fields.items[j];
6461 var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
6462 var v = n[k] !== undefined ? n[k] : f.defaultValue;
6466 var record = new recordType(values, id);
6468 records[records.length] = record;
6472 totalRecords : records.length
6477 * Ext JS Library 1.1.1
6478 * Copyright(c) 2006-2007, Ext JS, LLC.
6480 * Originally Released Under LGPL - original licence link has changed is not relivant.
6483 * <script type="text/javascript">
6488 * @class Roo.data.Tree
6489 * @extends Roo.util.Observable
6490 * Represents a tree data structure and bubbles all the events for its nodes. The nodes
6491 * in the tree have most standard DOM functionality.
6493 * @param {Node} root (optional) The root node
6495 Roo.data.Tree = function(root){
6498 * The root node for this tree
6503 this.setRootNode(root);
6508 * Fires when a new child node is appended to a node in this tree.
6509 * @param {Tree} tree The owner tree
6510 * @param {Node} parent The parent node
6511 * @param {Node} node The newly appended node
6512 * @param {Number} index The index of the newly appended node
6517 * Fires when a child node is removed from a node in this tree.
6518 * @param {Tree} tree The owner tree
6519 * @param {Node} parent The parent node
6520 * @param {Node} node The child node removed
6525 * Fires when a node is moved to a new location in the tree
6526 * @param {Tree} tree The owner tree
6527 * @param {Node} node The node moved
6528 * @param {Node} oldParent The old parent of this node
6529 * @param {Node} newParent The new parent of this node
6530 * @param {Number} index The index it was moved to
6535 * Fires when a new child node is inserted in a node in this tree.
6536 * @param {Tree} tree The owner tree
6537 * @param {Node} parent The parent node
6538 * @param {Node} node The child node inserted
6539 * @param {Node} refNode The child node the node was inserted before
6543 * @event beforeappend
6544 * Fires before a new child is appended to a node in this tree, return false to cancel the append.
6545 * @param {Tree} tree The owner tree
6546 * @param {Node} parent The parent node
6547 * @param {Node} node The child node to be appended
6549 "beforeappend" : true,
6551 * @event beforeremove
6552 * Fires before a child is removed from a node in this tree, return false to cancel the remove.
6553 * @param {Tree} tree The owner tree
6554 * @param {Node} parent The parent node
6555 * @param {Node} node The child node to be removed
6557 "beforeremove" : true,
6560 * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
6561 * @param {Tree} tree The owner tree
6562 * @param {Node} node The node being moved
6563 * @param {Node} oldParent The parent of the node
6564 * @param {Node} newParent The new parent the node is moving to
6565 * @param {Number} index The index it is being moved to
6567 "beforemove" : true,
6569 * @event beforeinsert
6570 * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
6571 * @param {Tree} tree The owner tree
6572 * @param {Node} parent The parent node
6573 * @param {Node} node The child node to be inserted
6574 * @param {Node} refNode The child node the node is being inserted before
6576 "beforeinsert" : true
6579 Roo.data.Tree.superclass.constructor.call(this);
6582 Roo.extend(Roo.data.Tree, Roo.util.Observable, {
6585 proxyNodeEvent : function(){
6586 return this.fireEvent.apply(this, arguments);
6590 * Returns the root node for this tree.
6593 getRootNode : function(){
6598 * Sets the root node for this tree.
6599 * @param {Node} node
6602 setRootNode : function(node){
6604 node.ownerTree = this;
6606 this.registerNode(node);
6611 * Gets a node in this tree by its id.
6612 * @param {String} id
6615 getNodeById : function(id){
6616 return this.nodeHash[id];
6619 registerNode : function(node){
6620 this.nodeHash[node.id] = node;
6623 unregisterNode : function(node){
6624 delete this.nodeHash[node.id];
6627 toString : function(){
6628 return "[Tree"+(this.id?" "+this.id:"")+"]";
6633 * @class Roo.data.Node
6634 * @extends Roo.util.Observable
6635 * @cfg {Boolean} leaf true if this node is a leaf and does not have children
6636 * @cfg {String} id The id for this node. If one is not specified, one is generated.
6638 * @param {Object} attributes The attributes/config for the node
6640 Roo.data.Node = function(attributes){
6642 * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
6645 this.attributes = attributes || {};
6646 this.leaf = this.attributes.leaf;
6648 * The node id. @type String
6650 this.id = this.attributes.id;
6652 this.id = Roo.id(null, "ynode-");
6653 this.attributes.id = this.id;
6656 * All child nodes of this node. @type Array
6658 this.childNodes = [];
6659 if(!this.childNodes.indexOf){ // indexOf is a must
6660 this.childNodes.indexOf = function(o){
6661 for(var i = 0, len = this.length; i < len; i++){
6670 * The parent node for this node. @type Node
6672 this.parentNode = null;
6674 * The first direct child node of this node, or null if this node has no child nodes. @type Node
6676 this.firstChild = null;
6678 * The last direct child node of this node, or null if this node has no child nodes. @type Node
6680 this.lastChild = null;
6682 * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
6684 this.previousSibling = null;
6686 * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
6688 this.nextSibling = null;
6693 * Fires when a new child node is appended
6694 * @param {Tree} tree The owner tree
6695 * @param {Node} this This node
6696 * @param {Node} node The newly appended node
6697 * @param {Number} index The index of the newly appended node
6702 * Fires when a child node is removed
6703 * @param {Tree} tree The owner tree
6704 * @param {Node} this This node
6705 * @param {Node} node The removed node
6710 * Fires when this node is moved to a new location in the tree
6711 * @param {Tree} tree The owner tree
6712 * @param {Node} this This node
6713 * @param {Node} oldParent The old parent of this node
6714 * @param {Node} newParent The new parent of this node
6715 * @param {Number} index The index it was moved to
6720 * Fires when a new child node is inserted.
6721 * @param {Tree} tree The owner tree
6722 * @param {Node} this This node
6723 * @param {Node} node The child node inserted
6724 * @param {Node} refNode The child node the node was inserted before
6728 * @event beforeappend
6729 * Fires before a new child is appended, return false to cancel the append.
6730 * @param {Tree} tree The owner tree
6731 * @param {Node} this This node
6732 * @param {Node} node The child node to be appended
6734 "beforeappend" : true,
6736 * @event beforeremove
6737 * Fires before a child is removed, return false to cancel the remove.
6738 * @param {Tree} tree The owner tree
6739 * @param {Node} this This node
6740 * @param {Node} node The child node to be removed
6742 "beforeremove" : true,
6745 * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
6746 * @param {Tree} tree The owner tree
6747 * @param {Node} this This node
6748 * @param {Node} oldParent The parent of this node
6749 * @param {Node} newParent The new parent this node is moving to
6750 * @param {Number} index The index it is being moved to
6752 "beforemove" : true,
6754 * @event beforeinsert
6755 * Fires before a new child is inserted, return false to cancel the insert.
6756 * @param {Tree} tree The owner tree
6757 * @param {Node} this This node
6758 * @param {Node} node The child node to be inserted
6759 * @param {Node} refNode The child node the node is being inserted before
6761 "beforeinsert" : true
6763 this.listeners = this.attributes.listeners;
6764 Roo.data.Node.superclass.constructor.call(this);
6767 Roo.extend(Roo.data.Node, Roo.util.Observable, {
6768 fireEvent : function(evtName){
6769 // first do standard event for this node
6770 if(Roo.data.Node.superclass.fireEvent.apply(this, arguments) === false){
6773 // then bubble it up to the tree if the event wasn't cancelled
6774 var ot = this.getOwnerTree();
6776 if(ot.proxyNodeEvent.apply(ot, arguments) === false){
6784 * Returns true if this node is a leaf
6787 isLeaf : function(){
6788 return this.leaf === true;
6792 setFirstChild : function(node){
6793 this.firstChild = node;
6797 setLastChild : function(node){
6798 this.lastChild = node;
6803 * Returns true if this node is the last child of its parent
6806 isLast : function(){
6807 return (!this.parentNode ? true : this.parentNode.lastChild == this);
6811 * Returns true if this node is the first child of its parent
6814 isFirst : function(){
6815 return (!this.parentNode ? true : this.parentNode.firstChild == this);
6818 hasChildNodes : function(){
6819 return !this.isLeaf() && this.childNodes.length > 0;
6823 * Insert node(s) as the last child node of this node.
6824 * @param {Node/Array} node The node or Array of nodes to append
6825 * @return {Node} The appended node if single append, or null if an array was passed
6827 appendChild : function(node){
6829 if(node instanceof Array){
6831 }else if(arguments.length > 1){
6834 // if passed an array or multiple args do them one by one
6836 for(var i = 0, len = multi.length; i < len; i++) {
6837 this.appendChild(multi[i]);
6840 if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
6843 var index = this.childNodes.length;
6844 var oldParent = node.parentNode;
6845 // it's a move, make sure we move it cleanly
6847 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
6850 oldParent.removeChild(node);
6852 index = this.childNodes.length;
6854 this.setFirstChild(node);
6856 this.childNodes.push(node);
6857 node.parentNode = this;
6858 var ps = this.childNodes[index-1];
6860 node.previousSibling = ps;
6861 ps.nextSibling = node;
6863 node.previousSibling = null;
6865 node.nextSibling = null;
6866 this.setLastChild(node);
6867 node.setOwnerTree(this.getOwnerTree());
6868 this.fireEvent("append", this.ownerTree, this, node, index);
6870 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
6877 * Removes a child node from this node.
6878 * @param {Node} node The node to remove
6879 * @return {Node} The removed node
6881 removeChild : function(node){
6882 var index = this.childNodes.indexOf(node);
6886 if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
6890 // remove it from childNodes collection
6891 this.childNodes.splice(index, 1);
6894 if(node.previousSibling){
6895 node.previousSibling.nextSibling = node.nextSibling;
6897 if(node.nextSibling){
6898 node.nextSibling.previousSibling = node.previousSibling;
6901 // update child refs
6902 if(this.firstChild == node){
6903 this.setFirstChild(node.nextSibling);
6905 if(this.lastChild == node){
6906 this.setLastChild(node.previousSibling);
6909 node.setOwnerTree(null);
6910 // clear any references from the node
6911 node.parentNode = null;
6912 node.previousSibling = null;
6913 node.nextSibling = null;
6914 this.fireEvent("remove", this.ownerTree, this, node);
6919 * Inserts the first node before the second node in this nodes childNodes collection.
6920 * @param {Node} node The node to insert
6921 * @param {Node} refNode The node to insert before (if null the node is appended)
6922 * @return {Node} The inserted node
6924 insertBefore : function(node, refNode){
6925 if(!refNode){ // like standard Dom, refNode can be null for append
6926 return this.appendChild(node);
6929 if(node == refNode){
6933 if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
6936 var index = this.childNodes.indexOf(refNode);
6937 var oldParent = node.parentNode;
6938 var refIndex = index;
6940 // when moving internally, indexes will change after remove
6941 if(oldParent == this && this.childNodes.indexOf(node) < index){
6945 // it's a move, make sure we move it cleanly
6947 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
6950 oldParent.removeChild(node);
6953 this.setFirstChild(node);
6955 this.childNodes.splice(refIndex, 0, node);
6956 node.parentNode = this;
6957 var ps = this.childNodes[refIndex-1];
6959 node.previousSibling = ps;
6960 ps.nextSibling = node;
6962 node.previousSibling = null;
6964 node.nextSibling = refNode;
6965 refNode.previousSibling = node;
6966 node.setOwnerTree(this.getOwnerTree());
6967 this.fireEvent("insert", this.ownerTree, this, node, refNode);
6969 node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
6975 * Returns the child node at the specified index.
6976 * @param {Number} index
6979 item : function(index){
6980 return this.childNodes[index];
6984 * Replaces one child node in this node with another.
6985 * @param {Node} newChild The replacement node
6986 * @param {Node} oldChild The node to replace
6987 * @return {Node} The replaced node
6989 replaceChild : function(newChild, oldChild){
6990 this.insertBefore(newChild, oldChild);
6991 this.removeChild(oldChild);
6996 * Returns the index of a child node
6997 * @param {Node} node
6998 * @return {Number} The index of the node or -1 if it was not found
7000 indexOf : function(child){
7001 return this.childNodes.indexOf(child);
7005 * Returns the tree this node is in.
7008 getOwnerTree : function(){
7009 // if it doesn't have one, look for one
7010 if(!this.ownerTree){
7014 this.ownerTree = p.ownerTree;
7020 return this.ownerTree;
7024 * Returns depth of this node (the root node has a depth of 0)
7027 getDepth : function(){
7030 while(p.parentNode){
7038 setOwnerTree : function(tree){
7039 // if it's move, we need to update everyone
7040 if(tree != this.ownerTree){
7042 this.ownerTree.unregisterNode(this);
7044 this.ownerTree = tree;
7045 var cs = this.childNodes;
7046 for(var i = 0, len = cs.length; i < len; i++) {
7047 cs[i].setOwnerTree(tree);
7050 tree.registerNode(this);
7056 * Returns the path for this node. The path can be used to expand or select this node programmatically.
7057 * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
7058 * @return {String} The path
7060 getPath : function(attr){
7061 attr = attr || "id";
7062 var p = this.parentNode;
7063 var b = [this.attributes[attr]];
7065 b.unshift(p.attributes[attr]);
7068 var sep = this.getOwnerTree().pathSeparator;
7069 return sep + b.join(sep);
7073 * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
7074 * function call will be the scope provided or the current node. The arguments to the function
7075 * will be the args provided or the current node. If the function returns false at any point,
7076 * the bubble is stopped.
7077 * @param {Function} fn The function to call
7078 * @param {Object} scope (optional) The scope of the function (defaults to current node)
7079 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
7081 bubble : function(fn, scope, args){
7084 if(fn.call(scope || p, args || p) === false){
7092 * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
7093 * function call will be the scope provided or the current node. The arguments to the function
7094 * will be the args provided or the current node. If the function returns false at any point,
7095 * the cascade is stopped on that branch.
7096 * @param {Function} fn The function to call
7097 * @param {Object} scope (optional) The scope of the function (defaults to current node)
7098 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
7100 cascade : function(fn, scope, args){
7101 if(fn.call(scope || this, args || this) !== false){
7102 var cs = this.childNodes;
7103 for(var i = 0, len = cs.length; i < len; i++) {
7104 cs[i].cascade(fn, scope, args);
7110 * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
7111 * function call will be the scope provided or the current node. The arguments to the function
7112 * will be the args provided or the current node. If the function returns false at any point,
7113 * the iteration stops.
7114 * @param {Function} fn The function to call
7115 * @param {Object} scope (optional) The scope of the function (defaults to current node)
7116 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
7118 eachChild : function(fn, scope, args){
7119 var cs = this.childNodes;
7120 for(var i = 0, len = cs.length; i < len; i++) {
7121 if(fn.call(scope || this, args || cs[i]) === false){
7128 * Finds the first child that has the attribute with the specified value.
7129 * @param {String} attribute The attribute name
7130 * @param {Mixed} value The value to search for
7131 * @return {Node} The found child or null if none was found
7133 findChild : function(attribute, value){
7134 var cs = this.childNodes;
7135 for(var i = 0, len = cs.length; i < len; i++) {
7136 if(cs[i].attributes[attribute] == value){
7144 * Finds the first child by a custom function. The child matches if the function passed
7146 * @param {Function} fn
7147 * @param {Object} scope (optional)
7148 * @return {Node} The found child or null if none was found
7150 findChildBy : function(fn, scope){
7151 var cs = this.childNodes;
7152 for(var i = 0, len = cs.length; i < len; i++) {
7153 if(fn.call(scope||cs[i], cs[i]) === true){
7161 * Sorts this nodes children using the supplied sort function
7162 * @param {Function} fn
7163 * @param {Object} scope (optional)
7165 sort : function(fn, scope){
7166 var cs = this.childNodes;
7167 var len = cs.length;
7169 var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
7171 for(var i = 0; i < len; i++){
7173 n.previousSibling = cs[i-1];
7174 n.nextSibling = cs[i+1];
7176 this.setFirstChild(n);
7179 this.setLastChild(n);
7186 * Returns true if this node is an ancestor (at any point) of the passed node.
7187 * @param {Node} node
7190 contains : function(node){
7191 return node.isAncestor(this);
7195 * Returns true if the passed node is an ancestor (at any point) of this node.
7196 * @param {Node} node
7199 isAncestor : function(node){
7200 var p = this.parentNode;
7210 toString : function(){
7211 return "[Node"+(this.id?" "+this.id:"")+"]";
7215 * Ext JS Library 1.1.1
7216 * Copyright(c) 2006-2007, Ext JS, LLC.
7218 * Originally Released Under LGPL - original licence link has changed is not relivant.
7221 * <script type="text/javascript">
7226 * @class Roo.ComponentMgr
7227 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
7230 Roo.ComponentMgr = function(){
7231 var all = new Roo.util.MixedCollection();
7235 * Registers a component.
7236 * @param {Roo.Component} c The component
7238 register : function(c){
7243 * Unregisters a component.
7244 * @param {Roo.Component} c The component
7246 unregister : function(c){
7251 * Returns a component by id
7252 * @param {String} id The component id
7259 * Registers a function that will be called when a specified component is added to ComponentMgr
7260 * @param {String} id The component id
7261 * @param {Funtction} fn The callback function
7262 * @param {Object} scope The scope of the callback
7264 onAvailable : function(id, fn, scope){
7265 all.on("add", function(index, o){
7267 fn.call(scope || o, o);
7268 all.un("add", fn, scope);
7275 * Ext JS Library 1.1.1
7276 * Copyright(c) 2006-2007, Ext JS, LLC.
7278 * Originally Released Under LGPL - original licence link has changed is not relivant.
7281 * <script type="text/javascript">
7285 * @class Roo.Component
7286 * @extends Roo.util.Observable
7287 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
7288 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
7289 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
7290 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
7291 * All visual components (widgets) that require rendering into a layout should subclass Component.
7293 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
7294 * element and its id used as the component id. If a string is passed, it is assumed to be the id of an existing element
7295 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
7297 Roo.Component = function(config){
7298 config = config || {};
7299 if(config.tagName || config.dom || typeof config == "string"){ // element object
7300 config = {el: config, id: config.id || config};
7302 this.initialConfig = config;
7304 Roo.apply(this, config);
7308 * Fires after the component is disabled.
7309 * @param {Roo.Component} this
7314 * Fires after the component is enabled.
7315 * @param {Roo.Component} this
7320 * Fires before the component is shown. Return false to stop the show.
7321 * @param {Roo.Component} this
7326 * Fires after the component is shown.
7327 * @param {Roo.Component} this
7332 * Fires before the component is hidden. Return false to stop the hide.
7333 * @param {Roo.Component} this
7338 * Fires after the component is hidden.
7339 * @param {Roo.Component} this
7343 * @event beforerender
7344 * Fires before the component is rendered. Return false to stop the render.
7345 * @param {Roo.Component} this
7347 beforerender : true,
7350 * Fires after the component is rendered.
7351 * @param {Roo.Component} this
7355 * @event beforedestroy
7356 * Fires before the component is destroyed. Return false to stop the destroy.
7357 * @param {Roo.Component} this
7359 beforedestroy : true,
7362 * Fires after the component is destroyed.
7363 * @param {Roo.Component} this
7368 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
7370 Roo.ComponentMgr.register(this);
7371 Roo.Component.superclass.constructor.call(this);
7372 this.initComponent();
7373 if(this.renderTo){ // not supported by all components yet. use at your own risk!
7374 this.render(this.renderTo);
7375 delete this.renderTo;
7380 Roo.Component.AUTO_ID = 1000;
7382 Roo.extend(Roo.Component, Roo.util.Observable, {
7384 * @property {Boolean} hidden
7385 * true if this component is hidden. Read-only.
7389 * true if this component is disabled. Read-only.
7393 * true if this component has been rendered. Read-only.
7397 /** @cfg {String} disableClass
7398 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
7400 disabledClass : "x-item-disabled",
7401 /** @cfg {Boolean} allowDomMove
7402 * Whether the component can move the Dom node when rendering (defaults to true).
7404 allowDomMove : true,
7405 /** @cfg {String} hideMode
7406 * How this component should hidden. Supported values are
7407 * "visibility" (css visibility), "offsets" (negative offset position) and
7408 * "display" (css display) - defaults to "display".
7410 hideMode: 'display',
7413 ctype : "Roo.Component",
7415 /** @cfg {String} actionMode
7416 * which property holds the element that used for hide() / show() / disable() / enable()
7422 getActionEl : function(){
7423 return this[this.actionMode];
7426 initComponent : Roo.emptyFn,
7428 * If this is a lazy rendering component, render it to its container element.
7429 * @param {String/HTMLElement/Element} container (optional) The element this component should be rendered into. If it is being applied to existing markup, this should be left off.
7431 render : function(container, position){
7432 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
7433 if(!container && this.el){
7434 this.el = Roo.get(this.el);
7435 container = this.el.dom.parentNode;
7436 this.allowDomMove = false;
7438 this.container = Roo.get(container);
7439 this.rendered = true;
7440 if(position !== undefined){
7441 if(typeof position == 'number'){
7442 position = this.container.dom.childNodes[position];
7444 position = Roo.getDom(position);
7447 this.onRender(this.container, position || null);
7449 this.el.addClass(this.cls);
7453 this.el.applyStyles(this.style);
7456 this.fireEvent("render", this);
7457 this.afterRender(this.container);
7469 // default function is not really useful
7470 onRender : function(ct, position){
7472 this.el = Roo.get(this.el);
7473 if(this.allowDomMove !== false){
7474 ct.dom.insertBefore(this.el.dom, position);
7480 getAutoCreate : function(){
7481 var cfg = typeof this.autoCreate == "object" ?
7482 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
7483 if(this.id && !cfg.id){
7490 afterRender : Roo.emptyFn,
7493 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
7494 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
7496 destroy : function(){
7497 if(this.fireEvent("beforedestroy", this) !== false){
7498 this.purgeListeners();
7499 this.beforeDestroy();
7501 this.el.removeAllListeners();
7503 if(this.actionMode == "container"){
7504 this.container.remove();
7508 Roo.ComponentMgr.unregister(this);
7509 this.fireEvent("destroy", this);
7514 beforeDestroy : function(){
7519 onDestroy : function(){
7524 * Returns the underlying {@link Roo.Element}.
7525 * @return {Roo.Element} The element
7532 * Returns the id of this component.
7540 * Try to focus this component.
7541 * @param {Boolean} selectText True to also select the text in this component (if applicable)
7542 * @return {Roo.Component} this
7544 focus : function(selectText){
7547 if(selectText === true){
7548 this.el.dom.select();
7563 * Disable this component.
7564 * @return {Roo.Component} this
7566 disable : function(){
7570 this.disabled = true;
7571 this.fireEvent("disable", this);
7576 onDisable : function(){
7577 this.getActionEl().addClass(this.disabledClass);
7578 this.el.dom.disabled = true;
7582 * Enable this component.
7583 * @return {Roo.Component} this
7585 enable : function(){
7589 this.disabled = false;
7590 this.fireEvent("enable", this);
7595 onEnable : function(){
7596 this.getActionEl().removeClass(this.disabledClass);
7597 this.el.dom.disabled = false;
7601 * Convenience function for setting disabled/enabled by boolean.
7602 * @param {Boolean} disabled
7604 setDisabled : function(disabled){
7605 this[disabled ? "disable" : "enable"]();
7609 * Show this component.
7610 * @return {Roo.Component} this
7613 if(this.fireEvent("beforeshow", this) !== false){
7614 this.hidden = false;
7618 this.fireEvent("show", this);
7624 onShow : function(){
7625 var ae = this.getActionEl();
7626 if(this.hideMode == 'visibility'){
7627 ae.dom.style.visibility = "visible";
7628 }else if(this.hideMode == 'offsets'){
7629 ae.removeClass('x-hidden');
7631 ae.dom.style.display = "";
7636 * Hide this component.
7637 * @return {Roo.Component} this
7640 if(this.fireEvent("beforehide", this) !== false){
7645 this.fireEvent("hide", this);
7651 onHide : function(){
7652 var ae = this.getActionEl();
7653 if(this.hideMode == 'visibility'){
7654 ae.dom.style.visibility = "hidden";
7655 }else if(this.hideMode == 'offsets'){
7656 ae.addClass('x-hidden');
7658 ae.dom.style.display = "none";
7663 * Convenience function to hide or show this component by boolean.
7664 * @param {Boolean} visible True to show, false to hide
7665 * @return {Roo.Component} this
7667 setVisible: function(visible){
7677 * Returns true if this component is visible.
7679 isVisible : function(){
7680 return this.getActionEl().isVisible();
7683 cloneConfig : function(overrides){
7684 overrides = overrides || {};
7685 var id = overrides.id || Roo.id();
7686 var cfg = Roo.applyIf(overrides, this.initialConfig);
7687 cfg.id = id; // prevent dup id
7688 return new this.constructor(cfg);
7692 * Ext JS Library 1.1.1
7693 * Copyright(c) 2006-2007, Ext JS, LLC.
7695 * Originally Released Under LGPL - original licence link has changed is not relivant.
7698 * <script type="text/javascript">
7703 * @extends Roo.Element
7704 * An extended {@link Roo.Element} object that supports a shadow and shim, constrain to viewport and
7705 * automatic maintaining of shadow/shim positions.
7706 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
7707 * @cfg {String/Boolean} shadow True to create a shadow element with default class "x-layer-shadow", or
7708 * you can pass a string with a CSS class name. False turns off the shadow.
7709 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: "div", cls: "x-layer"}).
7710 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
7711 * @cfg {String} cls CSS class to add to the element
7712 * @cfg {Number} zindex Starting z-index (defaults to 11000)
7713 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 3)
7715 * @param {Object} config An object with config options.
7716 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
7719 Roo.Layer = function(config, existingEl){
7720 config = config || {};
7721 var dh = Roo.DomHelper;
7722 var cp = config.parentEl, pel = cp ? Roo.getDom(cp) : document.body;
7724 this.dom = Roo.getDom(existingEl);
7727 var o = config.dh || {tag: "div", cls: "x-layer"};
7728 this.dom = dh.append(pel, o);
7731 this.addClass(config.cls);
7733 this.constrain = config.constrain !== false;
7734 this.visibilityMode = Roo.Element.VISIBILITY;
7736 this.id = this.dom.id = config.id;
7738 this.id = Roo.id(this.dom);
7740 this.zindex = config.zindex || this.getZIndex();
7741 this.position("absolute", this.zindex);
7743 this.shadowOffset = config.shadowOffset || 4;
7744 this.shadow = new Roo.Shadow({
7745 offset : this.shadowOffset,
7746 mode : config.shadow
7749 this.shadowOffset = 0;
7751 this.useShim = config.shim !== false && Roo.useShims;
7752 this.useDisplay = config.useDisplay;
7756 var supr = Roo.Element.prototype;
7758 // shims are shared among layer to keep from having 100 iframes
7761 Roo.extend(Roo.Layer, Roo.Element, {
7763 getZIndex : function(){
7764 return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
7767 getShim : function(){
7774 var shim = shims.shift();
7776 shim = this.createShim();
7777 shim.enableDisplayMode('block');
7778 shim.dom.style.display = 'none';
7779 shim.dom.style.visibility = 'visible';
7781 var pn = this.dom.parentNode;
7782 if(shim.dom.parentNode != pn){
7783 pn.insertBefore(shim.dom, this.dom);
7785 shim.setStyle('z-index', this.getZIndex()-2);
7790 hideShim : function(){
7792 this.shim.setDisplayed(false);
7793 shims.push(this.shim);
7798 disableShadow : function(){
7800 this.shadowDisabled = true;
7802 this.lastShadowOffset = this.shadowOffset;
7803 this.shadowOffset = 0;
7807 enableShadow : function(show){
7809 this.shadowDisabled = false;
7810 this.shadowOffset = this.lastShadowOffset;
7811 delete this.lastShadowOffset;
7819 // this code can execute repeatedly in milliseconds (i.e. during a drag) so
7820 // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
7821 sync : function(doShow){
7822 var sw = this.shadow;
7823 if(!this.updating && this.isVisible() && (sw || this.useShim)){
7824 var sh = this.getShim();
7826 var w = this.getWidth(),
7827 h = this.getHeight();
7829 var l = this.getLeft(true),
7830 t = this.getTop(true);
7832 if(sw && !this.shadowDisabled){
7833 if(doShow && !sw.isVisible()){
7836 sw.realign(l, t, w, h);
7842 // fit the shim behind the shadow, so it is shimmed too
7843 var a = sw.adjusts, s = sh.dom.style;
7844 s.left = (Math.min(l, l+a.l))+"px";
7845 s.top = (Math.min(t, t+a.t))+"px";
7846 s.width = (w+a.w)+"px";
7847 s.height = (h+a.h)+"px";
7854 sh.setLeftTop(l, t);
7861 destroy : function(){
7866 this.removeAllListeners();
7867 var pn = this.dom.parentNode;
7869 pn.removeChild(this.dom);
7871 Roo.Element.uncache(this.id);
7874 remove : function(){
7879 beginUpdate : function(){
7880 this.updating = true;
7884 endUpdate : function(){
7885 this.updating = false;
7890 hideUnders : function(negOffset){
7898 constrainXY : function(){
7900 var vw = Roo.lib.Dom.getViewWidth(),
7901 vh = Roo.lib.Dom.getViewHeight();
7902 var s = Roo.get(document).getScroll();
7904 var xy = this.getXY();
7905 var x = xy[0], y = xy[1];
7906 var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
7907 // only move it if it needs it
7909 // first validate right/bottom
7910 if((x + w) > vw+s.left){
7911 x = vw - w - this.shadowOffset;
7914 if((y + h) > vh+s.top){
7915 y = vh - h - this.shadowOffset;
7918 // then make sure top/left isn't negative
7929 var ay = this.avoidY;
7930 if(y <= ay && (y+h) >= ay){
7936 supr.setXY.call(this, xy);
7942 isVisible : function(){
7943 return this.visible;
7947 showAction : function(){
7948 this.visible = true; // track visibility to prevent getStyle calls
7949 if(this.useDisplay === true){
7950 this.setDisplayed("");
7951 }else if(this.lastXY){
7952 supr.setXY.call(this, this.lastXY);
7953 }else if(this.lastLT){
7954 supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
7959 hideAction : function(){
7960 this.visible = false;
7961 if(this.useDisplay === true){
7962 this.setDisplayed(false);
7964 this.setLeftTop(-10000,-10000);
7968 // overridden Element method
7969 setVisible : function(v, a, d, c, e){
7974 var cb = function(){
7979 }.createDelegate(this);
7980 supr.setVisible.call(this, true, true, d, cb, e);
7983 this.hideUnders(true);
7992 }.createDelegate(this);
7994 supr.setVisible.call(this, v, a, d, cb, e);
8003 storeXY : function(xy){
8008 storeLeftTop : function(left, top){
8010 this.lastLT = [left, top];
8014 beforeFx : function(){
8015 this.beforeAction();
8016 return Roo.Layer.superclass.beforeFx.apply(this, arguments);
8020 afterFx : function(){
8021 Roo.Layer.superclass.afterFx.apply(this, arguments);
8022 this.sync(this.isVisible());
8026 beforeAction : function(){
8027 if(!this.updating && this.shadow){
8032 // overridden Element method
8033 setLeft : function(left){
8034 this.storeLeftTop(left, this.getTop(true));
8035 supr.setLeft.apply(this, arguments);
8039 setTop : function(top){
8040 this.storeLeftTop(this.getLeft(true), top);
8041 supr.setTop.apply(this, arguments);
8045 setLeftTop : function(left, top){
8046 this.storeLeftTop(left, top);
8047 supr.setLeftTop.apply(this, arguments);
8051 setXY : function(xy, a, d, c, e){
8053 this.beforeAction();
8055 var cb = this.createCB(c);
8056 supr.setXY.call(this, xy, a, d, cb, e);
8063 createCB : function(c){
8074 // overridden Element method
8075 setX : function(x, a, d, c, e){
8076 this.setXY([x, this.getY()], a, d, c, e);
8079 // overridden Element method
8080 setY : function(y, a, d, c, e){
8081 this.setXY([this.getX(), y], a, d, c, e);
8084 // overridden Element method
8085 setSize : function(w, h, a, d, c, e){
8086 this.beforeAction();
8087 var cb = this.createCB(c);
8088 supr.setSize.call(this, w, h, a, d, cb, e);
8094 // overridden Element method
8095 setWidth : function(w, a, d, c, e){
8096 this.beforeAction();
8097 var cb = this.createCB(c);
8098 supr.setWidth.call(this, w, a, d, cb, e);
8104 // overridden Element method
8105 setHeight : function(h, a, d, c, e){
8106 this.beforeAction();
8107 var cb = this.createCB(c);
8108 supr.setHeight.call(this, h, a, d, cb, e);
8114 // overridden Element method
8115 setBounds : function(x, y, w, h, a, d, c, e){
8116 this.beforeAction();
8117 var cb = this.createCB(c);
8119 this.storeXY([x, y]);
8120 supr.setXY.call(this, [x, y]);
8121 supr.setSize.call(this, w, h, a, d, cb, e);
8124 supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
8130 * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
8131 * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
8132 * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
8133 * @param {Number} zindex The new z-index to set
8134 * @return {this} The Layer
8136 setZIndex : function(zindex){
8137 this.zindex = zindex;
8138 this.setStyle("z-index", zindex + 2);
8140 this.shadow.setZIndex(zindex + 1);
8143 this.shim.setStyle("z-index", zindex);