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">
14 * @class Roo.ComponentMgr
15 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
18 Roo.ComponentMgr = function(){
19 var all = new Roo.util.MixedCollection();
23 * Registers a component.
24 * @param {Roo.Component} c The component
26 register : function(c){
31 * Unregisters a component.
32 * @param {Roo.Component} c The component
34 unregister : function(c){
39 * Returns a component by id
40 * @param {String} id The component id
47 * Registers a function that will be called when a specified component is added to ComponentMgr
48 * @param {String} id The component id
49 * @param {Funtction} fn The callback function
50 * @param {Object} scope The scope of the callback
52 onAvailable : function(id, fn, scope){
53 all.on("add", function(index, o){
55 fn.call(scope || o, o);
56 all.un("add", fn, scope);
63 * Ext JS Library 1.1.1
64 * Copyright(c) 2006-2007, Ext JS, LLC.
66 * Originally Released Under LGPL - original licence link has changed is not relivant.
69 * <script type="text/javascript">
73 * @class Roo.Component
74 * @extends Roo.util.Observable
75 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
76 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
77 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
78 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
79 * All visual components (widgets) that require rendering into a layout should subclass Component.
81 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
82 * 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
83 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
85 Roo.Component = function(config){
86 config = config || {};
87 if(config.tagName || config.dom || typeof config == "string"){ // element object
88 config = {el: config, id: config.id || config};
90 this.initialConfig = config;
92 Roo.apply(this, config);
96 * Fires after the component is disabled.
97 * @param {Roo.Component} this
102 * Fires after the component is enabled.
103 * @param {Roo.Component} this
108 * Fires before the component is shown. Return false to stop the show.
109 * @param {Roo.Component} this
114 * Fires after the component is shown.
115 * @param {Roo.Component} this
120 * Fires before the component is hidden. Return false to stop the hide.
121 * @param {Roo.Component} this
126 * Fires after the component is hidden.
127 * @param {Roo.Component} this
131 * @event beforerender
132 * Fires before the component is rendered. Return false to stop the render.
133 * @param {Roo.Component} this
138 * Fires after the component is rendered.
139 * @param {Roo.Component} this
143 * @event beforedestroy
144 * Fires before the component is destroyed. Return false to stop the destroy.
145 * @param {Roo.Component} this
147 beforedestroy : true,
150 * Fires after the component is destroyed.
151 * @param {Roo.Component} this
156 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
158 Roo.ComponentMgr.register(this);
159 Roo.Component.superclass.constructor.call(this);
160 this.initComponent();
161 if(this.renderTo){ // not supported by all components yet. use at your own risk!
162 this.render(this.renderTo);
163 delete this.renderTo;
168 Roo.Component.AUTO_ID = 1000;
170 Roo.extend(Roo.Component, Roo.util.Observable, {
172 * @property {Boolean} hidden
173 * true if this component is hidden. Read-only.
177 * true if this component is disabled. Read-only.
181 * true if this component has been rendered. Read-only.
185 /** @cfg {String} disableClass
186 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
188 disabledClass : "x-item-disabled",
189 /** @cfg {Boolean} allowDomMove
190 * Whether the component can move the Dom node when rendering (defaults to true).
193 /** @cfg {String} hideMode
194 * How this component should hidden. Supported values are
195 * "visibility" (css visibility), "offsets" (negative offset position) and
196 * "display" (css display) - defaults to "display".
201 ctype : "Roo.Component",
203 /** @cfg {String} actionMode
204 * which property holds the element that used for hide() / show() / disable() / enable()
210 getActionEl : function(){
211 return this[this.actionMode];
214 initComponent : Roo.emptyFn,
216 * If this is a lazy rendering component, render it to its container element.
217 * @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.
219 render : function(container, position){
220 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
221 if(!container && this.el){
222 this.el = Roo.get(this.el);
223 container = this.el.dom.parentNode;
224 this.allowDomMove = false;
226 this.container = Roo.get(container);
227 this.rendered = true;
228 if(position !== undefined){
229 if(typeof position == 'number'){
230 position = this.container.dom.childNodes[position];
232 position = Roo.getDom(position);
235 this.onRender(this.container, position || null);
237 this.el.addClass(this.cls);
241 this.el.applyStyles(this.style);
244 this.fireEvent("render", this);
245 this.afterRender(this.container);
257 // default function is not really useful
258 onRender : function(ct, position){
260 this.el = Roo.get(this.el);
261 if(this.allowDomMove !== false){
262 ct.dom.insertBefore(this.el.dom, position);
268 getAutoCreate : function(){
269 var cfg = typeof this.autoCreate == "object" ?
270 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
271 if(this.id && !cfg.id){
278 afterRender : Roo.emptyFn,
281 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
282 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
284 destroy : function(){
285 if(this.fireEvent("beforedestroy", this) !== false){
286 this.purgeListeners();
287 this.beforeDestroy();
289 this.el.removeAllListeners();
291 if(this.actionMode == "container"){
292 this.container.remove();
296 Roo.ComponentMgr.unregister(this);
297 this.fireEvent("destroy", this);
302 beforeDestroy : function(){
307 onDestroy : function(){
312 * Returns the underlying {@link Roo.Element}.
313 * @return {Roo.Element} The element
320 * Returns the id of this component.
328 * Try to focus this component.
329 * @param {Boolean} selectText True to also select the text in this component (if applicable)
330 * @return {Roo.Component} this
332 focus : function(selectText){
335 if(selectText === true){
336 this.el.dom.select();
351 * Disable this component.
352 * @return {Roo.Component} this
354 disable : function(){
358 this.disabled = true;
359 this.fireEvent("disable", this);
364 onDisable : function(){
365 this.getActionEl().addClass(this.disabledClass);
366 this.el.dom.disabled = true;
370 * Enable this component.
371 * @return {Roo.Component} this
377 this.disabled = false;
378 this.fireEvent("enable", this);
383 onEnable : function(){
384 this.getActionEl().removeClass(this.disabledClass);
385 this.el.dom.disabled = false;
389 * Convenience function for setting disabled/enabled by boolean.
390 * @param {Boolean} disabled
392 setDisabled : function(disabled){
393 this[disabled ? "disable" : "enable"]();
397 * Show this component.
398 * @return {Roo.Component} this
401 if(this.fireEvent("beforeshow", this) !== false){
406 this.fireEvent("show", this);
413 var ae = this.getActionEl();
414 if(this.hideMode == 'visibility'){
415 ae.dom.style.visibility = "visible";
416 }else if(this.hideMode == 'offsets'){
417 ae.removeClass('x-hidden');
419 ae.dom.style.display = "";
424 * Hide this component.
425 * @return {Roo.Component} this
428 if(this.fireEvent("beforehide", this) !== false){
433 this.fireEvent("hide", this);
440 var ae = this.getActionEl();
441 if(this.hideMode == 'visibility'){
442 ae.dom.style.visibility = "hidden";
443 }else if(this.hideMode == 'offsets'){
444 ae.addClass('x-hidden');
446 ae.dom.style.display = "none";
451 * Convenience function to hide or show this component by boolean.
452 * @param {Boolean} visible True to show, false to hide
453 * @return {Roo.Component} this
455 setVisible: function(visible){
465 * Returns true if this component is visible.
467 isVisible : function(){
468 return this.getActionEl().isVisible();
471 cloneConfig : function(overrides){
472 overrides = overrides || {};
473 var id = overrides.id || Roo.id();
474 var cfg = Roo.applyIf(overrides, this.initialConfig);
475 cfg.id = id; // prevent dup id
476 return new this.constructor(cfg);
480 * Ext JS Library 1.1.1
481 * Copyright(c) 2006-2007, Ext JS, LLC.
483 * Originally Released Under LGPL - original licence link has changed is not relivant.
486 * <script type="text/javascript">
491 * @extends Roo.Element
492 * An extended {@link Roo.Element} object that supports a shadow and shim, constrain to viewport and
493 * automatic maintaining of shadow/shim positions.
494 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
495 * @cfg {String/Boolean} shadow True to create a shadow element with default class "x-layer-shadow", or
496 * you can pass a string with a CSS class name. False turns off the shadow.
497 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: "div", cls: "x-layer"}).
498 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
499 * @cfg {String} cls CSS class to add to the element
500 * @cfg {Number} zindex Starting z-index (defaults to 11000)
501 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 3)
503 * @param {Object} config An object with config options.
504 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
507 Roo.Layer = function(config, existingEl){
508 config = config || {};
509 var dh = Roo.DomHelper;
510 var cp = config.parentEl, pel = cp ? Roo.getDom(cp) : document.body;
512 this.dom = Roo.getDom(existingEl);
515 var o = config.dh || {tag: "div", cls: "x-layer"};
516 this.dom = dh.append(pel, o);
519 this.addClass(config.cls);
521 this.constrain = config.constrain !== false;
522 this.visibilityMode = Roo.Element.VISIBILITY;
524 this.id = this.dom.id = config.id;
526 this.id = Roo.id(this.dom);
528 this.zindex = config.zindex || this.getZIndex();
529 this.position("absolute", this.zindex);
531 this.shadowOffset = config.shadowOffset || 4;
532 this.shadow = new Roo.Shadow({
533 offset : this.shadowOffset,
537 this.shadowOffset = 0;
539 this.useShim = config.shim !== false && Roo.useShims;
540 this.useDisplay = config.useDisplay;
544 var supr = Roo.Element.prototype;
546 // shims are shared among layer to keep from having 100 iframes
549 Roo.extend(Roo.Layer, Roo.Element, {
551 getZIndex : function(){
552 return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
555 getShim : function(){
562 var shim = shims.shift();
564 shim = this.createShim();
565 shim.enableDisplayMode('block');
566 shim.dom.style.display = 'none';
567 shim.dom.style.visibility = 'visible';
569 var pn = this.dom.parentNode;
570 if(shim.dom.parentNode != pn){
571 pn.insertBefore(shim.dom, this.dom);
573 shim.setStyle('z-index', this.getZIndex()-2);
578 hideShim : function(){
580 this.shim.setDisplayed(false);
581 shims.push(this.shim);
586 disableShadow : function(){
588 this.shadowDisabled = true;
590 this.lastShadowOffset = this.shadowOffset;
591 this.shadowOffset = 0;
595 enableShadow : function(show){
597 this.shadowDisabled = false;
598 this.shadowOffset = this.lastShadowOffset;
599 delete this.lastShadowOffset;
607 // this code can execute repeatedly in milliseconds (i.e. during a drag) so
608 // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
609 sync : function(doShow){
610 var sw = this.shadow;
611 if(!this.updating && this.isVisible() && (sw || this.useShim)){
612 var sh = this.getShim();
614 var w = this.getWidth(),
615 h = this.getHeight();
617 var l = this.getLeft(true),
618 t = this.getTop(true);
620 if(sw && !this.shadowDisabled){
621 if(doShow && !sw.isVisible()){
624 sw.realign(l, t, w, h);
630 // fit the shim behind the shadow, so it is shimmed too
631 var a = sw.adjusts, s = sh.dom.style;
632 s.left = (Math.min(l, l+a.l))+"px";
633 s.top = (Math.min(t, t+a.t))+"px";
634 s.width = (w+a.w)+"px";
635 s.height = (h+a.h)+"px";
649 destroy : function(){
654 this.removeAllListeners();
655 var pn = this.dom.parentNode;
657 pn.removeChild(this.dom);
659 Roo.Element.uncache(this.id);
667 beginUpdate : function(){
668 this.updating = true;
672 endUpdate : function(){
673 this.updating = false;
678 hideUnders : function(negOffset){
686 constrainXY : function(){
688 var vw = Roo.lib.Dom.getViewWidth(),
689 vh = Roo.lib.Dom.getViewHeight();
690 var s = Roo.get(document).getScroll();
692 var xy = this.getXY();
693 var x = xy[0], y = xy[1];
694 var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
695 // only move it if it needs it
697 // first validate right/bottom
698 if((x + w) > vw+s.left){
699 x = vw - w - this.shadowOffset;
702 if((y + h) > vh+s.top){
703 y = vh - h - this.shadowOffset;
706 // then make sure top/left isn't negative
717 var ay = this.avoidY;
718 if(y <= ay && (y+h) >= ay){
724 supr.setXY.call(this, xy);
730 isVisible : function(){
735 showAction : function(){
736 this.visible = true; // track visibility to prevent getStyle calls
737 if(this.useDisplay === true){
738 this.setDisplayed("");
739 }else if(this.lastXY){
740 supr.setXY.call(this, this.lastXY);
741 }else if(this.lastLT){
742 supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
747 hideAction : function(){
748 this.visible = false;
749 if(this.useDisplay === true){
750 this.setDisplayed(false);
752 this.setLeftTop(-10000,-10000);
756 // overridden Element method
757 setVisible : function(v, a, d, c, e){
767 }.createDelegate(this);
768 supr.setVisible.call(this, true, true, d, cb, e);
771 this.hideUnders(true);
780 }.createDelegate(this);
782 supr.setVisible.call(this, v, a, d, cb, e);
791 storeXY : function(xy){
796 storeLeftTop : function(left, top){
798 this.lastLT = [left, top];
802 beforeFx : function(){
804 return Roo.Layer.superclass.beforeFx.apply(this, arguments);
808 afterFx : function(){
809 Roo.Layer.superclass.afterFx.apply(this, arguments);
810 this.sync(this.isVisible());
814 beforeAction : function(){
815 if(!this.updating && this.shadow){
820 // overridden Element method
821 setLeft : function(left){
822 this.storeLeftTop(left, this.getTop(true));
823 supr.setLeft.apply(this, arguments);
827 setTop : function(top){
828 this.storeLeftTop(this.getLeft(true), top);
829 supr.setTop.apply(this, arguments);
833 setLeftTop : function(left, top){
834 this.storeLeftTop(left, top);
835 supr.setLeftTop.apply(this, arguments);
839 setXY : function(xy, a, d, c, e){
843 var cb = this.createCB(c);
844 supr.setXY.call(this, xy, a, d, cb, e);
851 createCB : function(c){
862 // overridden Element method
863 setX : function(x, a, d, c, e){
864 this.setXY([x, this.getY()], a, d, c, e);
867 // overridden Element method
868 setY : function(y, a, d, c, e){
869 this.setXY([this.getX(), y], a, d, c, e);
872 // overridden Element method
873 setSize : function(w, h, a, d, c, e){
875 var cb = this.createCB(c);
876 supr.setSize.call(this, w, h, a, d, cb, e);
882 // overridden Element method
883 setWidth : function(w, a, d, c, e){
885 var cb = this.createCB(c);
886 supr.setWidth.call(this, w, a, d, cb, e);
892 // overridden Element method
893 setHeight : function(h, a, d, c, e){
895 var cb = this.createCB(c);
896 supr.setHeight.call(this, h, a, d, cb, e);
902 // overridden Element method
903 setBounds : function(x, y, w, h, a, d, c, e){
905 var cb = this.createCB(c);
907 this.storeXY([x, y]);
908 supr.setXY.call(this, [x, y]);
909 supr.setSize.call(this, w, h, a, d, cb, e);
912 supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
918 * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
919 * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
920 * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
921 * @param {Number} zindex The new z-index to set
922 * @return {this} The Layer
924 setZIndex : function(zindex){
925 this.zindex = zindex;
926 this.setStyle("z-index", zindex + 2);
928 this.shadow.setZIndex(zindex + 1);
931 this.shim.setStyle("z-index", zindex);
937 * Ext JS Library 1.1.1
938 * Copyright(c) 2006-2007, Ext JS, LLC.
940 * Originally Released Under LGPL - original licence link has changed is not relivant.
943 * <script type="text/javascript">
949 * Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned,
950 * and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced
951 * functionality that can also provide the same shadow effect, see the {@link Roo.Layer} class.
953 * Create a new Shadow
954 * @param {Object} config The config object
956 Roo.Shadow = function(config){
957 Roo.apply(this, config);
958 if(typeof this.mode != "string"){
959 this.mode = this.defaultMode;
961 var o = this.offset, a = {h: 0};
962 var rad = Math.floor(this.offset/2);
963 switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
969 a.l -= this.offset + rad;
970 a.t -= this.offset + rad;
981 a.l -= (this.offset - rad);
982 a.t -= this.offset + rad;
984 a.w -= (this.offset - rad)*2;
995 a.l -= (this.offset - rad);
996 a.t -= (this.offset - rad);
998 a.w -= (this.offset + rad + 1);
999 a.h -= (this.offset + rad);
1008 Roo.Shadow.prototype = {
1010 * @cfg {String} mode
1011 * The shadow display mode. Supports the following options:<br />
1012 * sides: Shadow displays on both sides and bottom only<br />
1013 * frame: Shadow displays equally on all four sides<br />
1014 * drop: Traditional bottom-right drop shadow (default)
1017 * @cfg {String} offset
1018 * The number of pixels to offset the shadow from the element (defaults to 4)
1023 defaultMode: "drop",
1026 * Displays the shadow under the target element
1027 * @param {String/HTMLElement/Element} targetEl The id or element under which the shadow should display
1029 show : function(target){
1030 target = Roo.get(target);
1032 this.el = Roo.Shadow.Pool.pull();
1033 if(this.el.dom.nextSibling != target.dom){
1034 this.el.insertBefore(target);
1037 this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
1039 this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
1042 target.getLeft(true),
1043 target.getTop(true),
1047 this.el.dom.style.display = "block";
1051 * Returns true if the shadow is visible, else false
1053 isVisible : function(){
1054 return this.el ? true : false;
1058 * Direct alignment when values are already available. Show must be called at least once before
1059 * calling this method to ensure it is initialized.
1060 * @param {Number} left The target element left position
1061 * @param {Number} top The target element top position
1062 * @param {Number} width The target element width
1063 * @param {Number} height The target element height
1065 realign : function(l, t, w, h){
1069 var a = this.adjusts, d = this.el.dom, s = d.style;
1071 s.left = (l+a.l)+"px";
1072 s.top = (t+a.t)+"px";
1073 var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
1074 if(s.width != sws || s.height != shs){
1078 var cn = d.childNodes;
1079 var sww = Math.max(0, (sw-12))+"px";
1080 cn[0].childNodes[1].style.width = sww;
1081 cn[1].childNodes[1].style.width = sww;
1082 cn[2].childNodes[1].style.width = sww;
1083 cn[1].style.height = Math.max(0, (sh-12))+"px";
1093 this.el.dom.style.display = "none";
1094 Roo.Shadow.Pool.push(this.el);
1100 * Adjust the z-index of this shadow
1101 * @param {Number} zindex The new z-index
1103 setZIndex : function(z){
1106 this.el.setStyle("z-index", z);
1111 // Private utility class that manages the internal Shadow cache
1112 Roo.Shadow.Pool = function(){
1114 var markup = Roo.isIE ?
1115 '<div class="x-ie-shadow"></div>' :
1116 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
1121 sh = Roo.get(Roo.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
1122 sh.autoBoxAdjust = false;
1127 push : function(sh){
1133 * Ext JS Library 1.1.1
1134 * Copyright(c) 2006-2007, Ext JS, LLC.
1136 * Originally Released Under LGPL - original licence link has changed is not relivant.
1139 * <script type="text/javascript">
1143 * @class Roo.BoxComponent
1144 * @extends Roo.Component
1145 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
1146 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
1147 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
1148 * layout containers.
1150 * @param {Roo.Element/String/Object} config The configuration options.
1152 Roo.BoxComponent = function(config){
1153 Roo.Component.call(this, config);
1157 * Fires after the component is resized.
1158 * @param {Roo.Component} this
1159 * @param {Number} adjWidth The box-adjusted width that was set
1160 * @param {Number} adjHeight The box-adjusted height that was set
1161 * @param {Number} rawWidth The width that was originally specified
1162 * @param {Number} rawHeight The height that was originally specified
1167 * Fires after the component is moved.
1168 * @param {Roo.Component} this
1169 * @param {Number} x The new x position
1170 * @param {Number} y The new y position
1176 Roo.extend(Roo.BoxComponent, Roo.Component, {
1177 // private, set in afterRender to signify that the component has been rendered
1179 // private, used to defer height settings to subclasses
1181 /** @cfg {Number} width
1182 * width (optional) size of component
1184 /** @cfg {Number} height
1185 * height (optional) size of component
1189 * Sets the width and height of the component. This method fires the resize event. This method can accept
1190 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
1191 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
1192 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
1193 * @return {Roo.BoxComponent} this
1195 setSize : function(w, h){
1196 // support for standard size objects
1197 if(typeof w == 'object'){
1208 // prevent recalcs when not needed
1209 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
1212 this.lastSize = {width: w, height: h};
1214 var adj = this.adjustSize(w, h);
1215 var aw = adj.width, ah = adj.height;
1216 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
1217 var rz = this.getResizeEl();
1218 if(!this.deferHeight && aw !== undefined && ah !== undefined){
1220 }else if(!this.deferHeight && ah !== undefined){
1222 }else if(aw !== undefined){
1225 this.onResize(aw, ah, w, h);
1226 this.fireEvent('resize', this, aw, ah, w, h);
1232 * Gets the current size of the component's underlying element.
1233 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
1235 getSize : function(){
1236 return this.el.getSize();
1240 * Gets the current XY position of the component's underlying element.
1241 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
1242 * @return {Array} The XY position of the element (e.g., [100, 200])
1244 getPosition : function(local){
1246 return [this.el.getLeft(true), this.el.getTop(true)];
1248 return this.xy || this.el.getXY();
1252 * Gets the current box measurements of the component's underlying element.
1253 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
1254 * @returns {Object} box An object in the format {x, y, width, height}
1256 getBox : function(local){
1257 var s = this.el.getSize();
1259 s.x = this.el.getLeft(true);
1260 s.y = this.el.getTop(true);
1262 var xy = this.xy || this.el.getXY();
1270 * Sets the current box measurements of the component's underlying element.
1271 * @param {Object} box An object in the format {x, y, width, height}
1272 * @returns {Roo.BoxComponent} this
1274 updateBox : function(box){
1275 this.setSize(box.width, box.height);
1276 this.setPagePosition(box.x, box.y);
1281 getResizeEl : function(){
1282 return this.resizeEl || this.el;
1286 getPositionEl : function(){
1287 return this.positionEl || this.el;
1291 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
1292 * This method fires the move event.
1293 * @param {Number} left The new left
1294 * @param {Number} top The new top
1295 * @returns {Roo.BoxComponent} this
1297 setPosition : function(x, y){
1303 var adj = this.adjustPosition(x, y);
1304 var ax = adj.x, ay = adj.y;
1306 var el = this.getPositionEl();
1307 if(ax !== undefined || ay !== undefined){
1308 if(ax !== undefined && ay !== undefined){
1309 el.setLeftTop(ax, ay);
1310 }else if(ax !== undefined){
1312 }else if(ay !== undefined){
1315 this.onPosition(ax, ay);
1316 this.fireEvent('move', this, ax, ay);
1322 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
1323 * This method fires the move event.
1324 * @param {Number} x The new x position
1325 * @param {Number} y The new y position
1326 * @returns {Roo.BoxComponent} this
1328 setPagePosition : function(x, y){
1334 if(x === undefined || y === undefined){ // cannot translate undefined points
1337 var p = this.el.translatePoints(x, y);
1338 this.setPosition(p.left, p.top);
1343 onRender : function(ct, position){
1344 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
1346 this.resizeEl = Roo.get(this.resizeEl);
1348 if(this.positionEl){
1349 this.positionEl = Roo.get(this.positionEl);
1354 afterRender : function(){
1355 Roo.BoxComponent.superclass.afterRender.call(this);
1356 this.boxReady = true;
1357 this.setSize(this.width, this.height);
1358 if(this.x || this.y){
1359 this.setPosition(this.x, this.y);
1361 if(this.pageX || this.pageY){
1362 this.setPagePosition(this.pageX, this.pageY);
1367 * Force the component's size to recalculate based on the underlying element's current height and width.
1368 * @returns {Roo.BoxComponent} this
1370 syncSize : function(){
1371 delete this.lastSize;
1372 this.setSize(this.el.getWidth(), this.el.getHeight());
1377 * Called after the component is resized, this method is empty by default but can be implemented by any
1378 * subclass that needs to perform custom logic after a resize occurs.
1379 * @param {Number} adjWidth The box-adjusted width that was set
1380 * @param {Number} adjHeight The box-adjusted height that was set
1381 * @param {Number} rawWidth The width that was originally specified
1382 * @param {Number} rawHeight The height that was originally specified
1384 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
1389 * Called after the component is moved, this method is empty by default but can be implemented by any
1390 * subclass that needs to perform custom logic after a move occurs.
1391 * @param {Number} x The new x position
1392 * @param {Number} y The new y position
1394 onPosition : function(x, y){
1399 adjustSize : function(w, h){
1403 if(this.autoHeight){
1406 return {width : w, height: h};
1410 adjustPosition : function(x, y){
1411 return {x : x, y: y};
1415 * Ext JS Library 1.1.1
1416 * Copyright(c) 2006-2007, Ext JS, LLC.
1418 * Originally Released Under LGPL - original licence link has changed is not relivant.
1421 * <script type="text/javascript">
1426 * @class Roo.SplitBar
1427 * @extends Roo.util.Observable
1428 * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
1432 var split = new Roo.SplitBar("elementToDrag", "elementToSize",
1433 Roo.SplitBar.HORIZONTAL, Roo.SplitBar.LEFT);
1434 split.setAdapter(new Roo.SplitBar.AbsoluteLayoutAdapter("container"));
1435 split.minSize = 100;
1436 split.maxSize = 600;
1437 split.animate = true;
1438 split.on('moved', splitterMoved);
1441 * Create a new SplitBar
1442 * @param {String/HTMLElement/Roo.Element} dragElement The element to be dragged and act as the SplitBar.
1443 * @param {String/HTMLElement/Roo.Element} resizingElement The element to be resized based on where the SplitBar element is dragged
1444 * @param {Number} orientation (optional) Either Roo.SplitBar.HORIZONTAL or Roo.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
1445 * @param {Number} placement (optional) Either Roo.SplitBar.LEFT or Roo.SplitBar.RIGHT for horizontal or
1446 Roo.SplitBar.TOP or Roo.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
1447 position of the SplitBar).
1449 Roo.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
1452 this.el = Roo.get(dragElement, true);
1453 this.el.dom.unselectable = "on";
1455 this.resizingEl = Roo.get(resizingElement, true);
1459 * The orientation of the split. Either Roo.SplitBar.HORIZONTAL or Roo.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
1460 * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
1463 this.orientation = orientation || Roo.SplitBar.HORIZONTAL;
1466 * The minimum size of the resizing element. (Defaults to 0)
1472 * The maximum size of the resizing element. (Defaults to 2000)
1475 this.maxSize = 2000;
1478 * Whether to animate the transition to the new size
1481 this.animate = false;
1484 * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
1487 this.useShim = false;
1494 this.proxy = Roo.SplitBar.createProxy(this.orientation);
1496 this.proxy = Roo.get(existingProxy).dom;
1499 this.dd = new Roo.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
1502 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
1505 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
1508 this.dragSpecs = {};
1511 * @private The adapter to use to positon and resize elements
1513 this.adapter = new Roo.SplitBar.BasicLayoutAdapter();
1514 this.adapter.init(this);
1516 if(this.orientation == Roo.SplitBar.HORIZONTAL){
1518 this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Roo.SplitBar.LEFT : Roo.SplitBar.RIGHT);
1519 this.el.addClass("x-splitbar-h");
1522 this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Roo.SplitBar.TOP : Roo.SplitBar.BOTTOM);
1523 this.el.addClass("x-splitbar-v");
1529 * Fires when the splitter is moved (alias for {@link #event-moved})
1530 * @param {Roo.SplitBar} this
1531 * @param {Number} newSize the new width or height
1536 * Fires when the splitter is moved
1537 * @param {Roo.SplitBar} this
1538 * @param {Number} newSize the new width or height
1542 * @event beforeresize
1543 * Fires before the splitter is dragged
1544 * @param {Roo.SplitBar} this
1546 "beforeresize" : true,
1548 "beforeapply" : true
1551 Roo.util.Observable.call(this);
1554 Roo.extend(Roo.SplitBar, Roo.util.Observable, {
1555 onStartProxyDrag : function(x, y){
1556 this.fireEvent("beforeresize", this);
1558 var o = Roo.DomHelper.insertFirst(document.body, {cls: "x-drag-overlay", html: " "}, true);
1560 o.enableDisplayMode("block");
1561 // all splitbars share the same overlay
1562 Roo.SplitBar.prototype.overlay = o;
1564 this.overlay.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
1565 this.overlay.show();
1566 Roo.get(this.proxy).setDisplayed("block");
1567 var size = this.adapter.getElementSize(this);
1568 this.activeMinSize = this.getMinimumSize();;
1569 this.activeMaxSize = this.getMaximumSize();;
1570 var c1 = size - this.activeMinSize;
1571 var c2 = Math.max(this.activeMaxSize - size, 0);
1572 if(this.orientation == Roo.SplitBar.HORIZONTAL){
1573 this.dd.resetConstraints();
1574 this.dd.setXConstraint(
1575 this.placement == Roo.SplitBar.LEFT ? c1 : c2,
1576 this.placement == Roo.SplitBar.LEFT ? c2 : c1
1578 this.dd.setYConstraint(0, 0);
1580 this.dd.resetConstraints();
1581 this.dd.setXConstraint(0, 0);
1582 this.dd.setYConstraint(
1583 this.placement == Roo.SplitBar.TOP ? c1 : c2,
1584 this.placement == Roo.SplitBar.TOP ? c2 : c1
1587 this.dragSpecs.startSize = size;
1588 this.dragSpecs.startPoint = [x, y];
1589 Roo.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
1593 * @private Called after the drag operation by the DDProxy
1595 onEndProxyDrag : function(e){
1596 Roo.get(this.proxy).setDisplayed(false);
1597 var endPoint = Roo.lib.Event.getXY(e);
1599 this.overlay.hide();
1602 if(this.orientation == Roo.SplitBar.HORIZONTAL){
1603 newSize = this.dragSpecs.startSize +
1604 (this.placement == Roo.SplitBar.LEFT ?
1605 endPoint[0] - this.dragSpecs.startPoint[0] :
1606 this.dragSpecs.startPoint[0] - endPoint[0]
1609 newSize = this.dragSpecs.startSize +
1610 (this.placement == Roo.SplitBar.TOP ?
1611 endPoint[1] - this.dragSpecs.startPoint[1] :
1612 this.dragSpecs.startPoint[1] - endPoint[1]
1615 newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
1616 if(newSize != this.dragSpecs.startSize){
1617 if(this.fireEvent('beforeapply', this, newSize) !== false){
1618 this.adapter.setElementSize(this, newSize);
1619 this.fireEvent("moved", this, newSize);
1620 this.fireEvent("resize", this, newSize);
1626 * Get the adapter this SplitBar uses
1627 * @return The adapter object
1629 getAdapter : function(){
1630 return this.adapter;
1634 * Set the adapter this SplitBar uses
1635 * @param {Object} adapter A SplitBar adapter object
1637 setAdapter : function(adapter){
1638 this.adapter = adapter;
1639 this.adapter.init(this);
1643 * Gets the minimum size for the resizing element
1644 * @return {Number} The minimum size
1646 getMinimumSize : function(){
1647 return this.minSize;
1651 * Sets the minimum size for the resizing element
1652 * @param {Number} minSize The minimum size
1654 setMinimumSize : function(minSize){
1655 this.minSize = minSize;
1659 * Gets the maximum size for the resizing element
1660 * @return {Number} The maximum size
1662 getMaximumSize : function(){
1663 return this.maxSize;
1667 * Sets the maximum size for the resizing element
1668 * @param {Number} maxSize The maximum size
1670 setMaximumSize : function(maxSize){
1671 this.maxSize = maxSize;
1675 * Sets the initialize size for the resizing element
1676 * @param {Number} size The initial size
1678 setCurrentSize : function(size){
1679 var oldAnimate = this.animate;
1680 this.animate = false;
1681 this.adapter.setElementSize(this, size);
1682 this.animate = oldAnimate;
1686 * Destroy this splitbar.
1687 * @param {Boolean} removeEl True to remove the element
1689 destroy : function(removeEl){
1694 this.proxy.parentNode.removeChild(this.proxy);
1702 * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
1704 Roo.SplitBar.createProxy = function(dir){
1705 var proxy = new Roo.Element(document.createElement("div"));
1706 proxy.unselectable();
1707 var cls = 'x-splitbar-proxy';
1708 proxy.addClass(cls + ' ' + (dir == Roo.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
1709 document.body.appendChild(proxy.dom);
1714 * @class Roo.SplitBar.BasicLayoutAdapter
1715 * Default Adapter. It assumes the splitter and resizing element are not positioned
1716 * elements and only gets/sets the width of the element. Generally used for table based layouts.
1718 Roo.SplitBar.BasicLayoutAdapter = function(){
1721 Roo.SplitBar.BasicLayoutAdapter.prototype = {
1722 // do nothing for now
1727 * Called before drag operations to get the current size of the resizing element.
1728 * @param {Roo.SplitBar} s The SplitBar using this adapter
1730 getElementSize : function(s){
1731 if(s.orientation == Roo.SplitBar.HORIZONTAL){
1732 return s.resizingEl.getWidth();
1734 return s.resizingEl.getHeight();
1739 * Called after drag operations to set the size of the resizing element.
1740 * @param {Roo.SplitBar} s The SplitBar using this adapter
1741 * @param {Number} newSize The new size to set
1742 * @param {Function} onComplete A function to be invoked when resizing is complete
1744 setElementSize : function(s, newSize, onComplete){
1745 if(s.orientation == Roo.SplitBar.HORIZONTAL){
1747 s.resizingEl.setWidth(newSize);
1749 onComplete(s, newSize);
1752 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
1757 s.resizingEl.setHeight(newSize);
1759 onComplete(s, newSize);
1762 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
1769 *@class Roo.SplitBar.AbsoluteLayoutAdapter
1770 * @extends Roo.SplitBar.BasicLayoutAdapter
1771 * Adapter that moves the splitter element to align with the resized sizing element.
1772 * Used with an absolute positioned SplitBar.
1773 * @param {String/HTMLElement/Roo.Element} container The container that wraps around the absolute positioned content. If it's
1774 * document.body, make sure you assign an id to the body element.
1776 Roo.SplitBar.AbsoluteLayoutAdapter = function(container){
1777 this.basic = new Roo.SplitBar.BasicLayoutAdapter();
1778 this.container = Roo.get(container);
1781 Roo.SplitBar.AbsoluteLayoutAdapter.prototype = {
1786 getElementSize : function(s){
1787 return this.basic.getElementSize(s);
1790 setElementSize : function(s, newSize, onComplete){
1791 this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
1794 moveSplitter : function(s){
1795 var yes = Roo.SplitBar;
1796 switch(s.placement){
1798 s.el.setX(s.resizingEl.getRight());
1801 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
1804 s.el.setY(s.resizingEl.getBottom());
1807 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
1814 * Orientation constant - Create a vertical SplitBar
1818 Roo.SplitBar.VERTICAL = 1;
1821 * Orientation constant - Create a horizontal SplitBar
1825 Roo.SplitBar.HORIZONTAL = 2;
1828 * Placement constant - The resizing element is to the left of the splitter element
1832 Roo.SplitBar.LEFT = 1;
1835 * Placement constant - The resizing element is to the right of the splitter element
1839 Roo.SplitBar.RIGHT = 2;
1842 * Placement constant - The resizing element is positioned above the splitter element
1846 Roo.SplitBar.TOP = 3;
1849 * Placement constant - The resizing element is positioned under splitter element
1853 Roo.SplitBar.BOTTOM = 4;
1856 * Ext JS Library 1.1.1
1857 * Copyright(c) 2006-2007, Ext JS, LLC.
1859 * Originally Released Under LGPL - original licence link has changed is not relivant.
1862 * <script type="text/javascript">
1867 * @extends Roo.util.Observable
1868 * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
1869 * This class also supports single and multi selection modes. <br>
1870 * Create a data model bound view:
1872 var store = new Roo.data.Store(...);
1874 var view = new Roo.View("my-element",
1875 '<div id="{0}">{2} - {1}</div>', // auto create template
1878 selectedClass: "ydataview-selected",
1882 // listen for node click?
1883 view.on("click", function(vw, index, node, e){
1884 alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
1888 dataModel.load("foobar.xml");
1890 For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
1892 * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
1893 * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
1896 * @param {String/HTMLElement/Element} container The container element where the view is to be rendered.
1897 * @param {String/DomHelper.Template} tpl The rendering template or a string to create a template with
1898 * @param {Object} config The config object
1900 Roo.View = function(container, tpl, config){
1901 this.el = Roo.get(container);
1902 if(typeof tpl == "string"){
1903 tpl = new Roo.Template(tpl);
1907 * The template used by this View
1908 * @type {Roo.DomHelper.Template}
1912 Roo.apply(this, config);
1917 * @event beforeclick
1918 * Fires before a click is processed. Returns false to cancel the default action.
1919 * @param {Roo.View} this
1920 * @param {Number} index The index of the target node
1921 * @param {HTMLElement} node The target node
1922 * @param {Roo.EventObject} e The raw event object
1924 "beforeclick" : true,
1927 * Fires when a template node is clicked.
1928 * @param {Roo.View} this
1929 * @param {Number} index The index of the target node
1930 * @param {HTMLElement} node The target node
1931 * @param {Roo.EventObject} e The raw event object
1936 * Fires when a template node is double clicked.
1937 * @param {Roo.View} this
1938 * @param {Number} index The index of the target node
1939 * @param {HTMLElement} node The target node
1940 * @param {Roo.EventObject} e The raw event object
1944 * @event contextmenu
1945 * Fires when a template node is right clicked.
1946 * @param {Roo.View} this
1947 * @param {Number} index The index of the target node
1948 * @param {HTMLElement} node The target node
1949 * @param {Roo.EventObject} e The raw event object
1951 "contextmenu" : true,
1953 * @event selectionchange
1954 * Fires when the selected nodes change.
1955 * @param {Roo.View} this
1956 * @param {Array} selections Array of the selected nodes
1958 "selectionchange" : true,
1961 * @event beforeselect
1962 * Fires before a selection is made. If any handlers return false, the selection is cancelled.
1963 * @param {Roo.View} this
1964 * @param {HTMLElement} node The node to be selected
1965 * @param {Array} selections Array of currently selected nodes
1967 "beforeselect" : true
1971 "click": this.onClick,
1972 "dblclick": this.onDblClick,
1973 "contextmenu": this.onContextMenu,
1977 this.selections = [];
1979 this.cmp = new Roo.CompositeElementLite([]);
1981 this.store = Roo.factory(this.store, Roo.data);
1982 this.setStore(this.store, true);
1984 Roo.View.superclass.constructor.call(this);
1987 Roo.extend(Roo.View, Roo.util.Observable, {
1989 * The css class to add to selected nodes
1990 * @type {Roo.DomHelper.Template}
1992 selectedClass : "x-view-selected",
1996 * Returns the element this view is bound to.
1997 * @return {Roo.Element}
2004 * Refreshes the view.
2006 refresh : function(){
2008 this.clearSelections();
2011 var records = this.store.getRange();
2012 if(records.length < 1){
2013 this.el.update(this.emptyText);
2016 for(var i = 0, len = records.length; i < len; i++){
2017 var data = this.prepareData(records[i].data, i, records[i]);
2018 html[html.length] = t.apply(data);
2020 this.el.update(html.join(""));
2021 this.nodes = this.el.dom.childNodes;
2022 this.updateIndexes(0);
2026 * Function to override to reformat the data that is sent to
2027 * the template for each node.
2028 * @param {Array/Object} data The raw data (array of colData for a data model bound view or
2029 * a JSON object for an UpdateManager bound view).
2031 prepareData : function(data){
2035 onUpdate : function(ds, record){
2036 this.clearSelections();
2037 var index = this.store.indexOf(record);
2038 var n = this.nodes[index];
2039 this.tpl.insertBefore(n, this.prepareData(record.data));
2040 n.parentNode.removeChild(n);
2041 this.updateIndexes(index, index);
2044 onAdd : function(ds, records, index){
2045 this.clearSelections();
2046 if(this.nodes.length == 0){
2050 var n = this.nodes[index];
2051 for(var i = 0, len = records.length; i < len; i++){
2052 var d = this.prepareData(records[i].data);
2054 this.tpl.insertBefore(n, d);
2056 this.tpl.append(this.el, d);
2059 this.updateIndexes(index);
2062 onRemove : function(ds, record, index){
2063 this.clearSelections();
2064 this.el.dom.removeChild(this.nodes[index]);
2065 this.updateIndexes(index);
2069 * Refresh an individual node.
2070 * @param {Number} index
2072 refreshNode : function(index){
2073 this.onUpdate(this.store, this.store.getAt(index));
2076 updateIndexes : function(startIndex, endIndex){
2077 var ns = this.nodes;
2078 startIndex = startIndex || 0;
2079 endIndex = endIndex || ns.length - 1;
2080 for(var i = startIndex; i <= endIndex; i++){
2081 ns[i].nodeIndex = i;
2086 * Changes the data store this view uses and refresh the view.
2087 * @param {Store} store
2089 setStore : function(store, initial){
2090 if(!initial && this.store){
2091 this.store.un("datachanged", this.refresh);
2092 this.store.un("add", this.onAdd);
2093 this.store.un("remove", this.onRemove);
2094 this.store.un("update", this.onUpdate);
2095 this.store.un("clear", this.refresh);
2099 store.on("datachanged", this.refresh, this);
2100 store.on("add", this.onAdd, this);
2101 store.on("remove", this.onRemove, this);
2102 store.on("update", this.onUpdate, this);
2103 store.on("clear", this.refresh, this);
2112 * Returns the template node the passed child belongs to or null if it doesn't belong to one.
2113 * @param {HTMLElement} node
2114 * @return {HTMLElement} The template node
2116 findItemFromChild : function(node){
2117 var el = this.el.dom;
2118 if(!node || node.parentNode == el){
2121 var p = node.parentNode;
2122 while(p && p != el){
2123 if(p.parentNode == el){
2132 onClick : function(e){
2133 var item = this.findItemFromChild(e.getTarget());
2135 var index = this.indexOf(item);
2136 if(this.onItemClick(item, index, e) !== false){
2137 this.fireEvent("click", this, index, item, e);
2140 this.clearSelections();
2145 onContextMenu : function(e){
2146 var item = this.findItemFromChild(e.getTarget());
2148 this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
2153 onDblClick : function(e){
2154 var item = this.findItemFromChild(e.getTarget());
2156 this.fireEvent("dblclick", this, this.indexOf(item), item, e);
2160 onItemClick : function(item, index, e){
2161 if(this.fireEvent("beforeclick", this, index, item, e) === false){
2164 if(this.multiSelect || this.singleSelect){
2165 if(this.multiSelect && e.shiftKey && this.lastSelection){
2166 this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
2168 this.select(item, this.multiSelect && e.ctrlKey);
2169 this.lastSelection = item;
2177 * Get the number of selected nodes.
2180 getSelectionCount : function(){
2181 return this.selections.length;
2185 * Get the currently selected nodes.
2186 * @return {Array} An array of HTMLElements
2188 getSelectedNodes : function(){
2189 return this.selections;
2193 * Get the indexes of the selected nodes.
2196 getSelectedIndexes : function(){
2197 var indexes = [], s = this.selections;
2198 for(var i = 0, len = s.length; i < len; i++){
2199 indexes.push(s[i].nodeIndex);
2205 * Clear all selections
2206 * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange event
2208 clearSelections : function(suppressEvent){
2209 if(this.nodes && (this.multiSelect || this.singleSelect) && this.selections.length > 0){
2210 this.cmp.elements = this.selections;
2211 this.cmp.removeClass(this.selectedClass);
2212 this.selections = [];
2214 this.fireEvent("selectionchange", this, this.selections);
2220 * Returns true if the passed node is selected
2221 * @param {HTMLElement/Number} node The node or node index
2224 isSelected : function(node){
2225 var s = this.selections;
2229 node = this.getNode(node);
2230 return s.indexOf(node) !== -1;
2235 * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
2236 * @param {Boolean} keepExisting (optional) true to keep existing selections
2237 * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
2239 select : function(nodeInfo, keepExisting, suppressEvent){
2240 if(nodeInfo instanceof Array){
2242 this.clearSelections(true);
2244 for(var i = 0, len = nodeInfo.length; i < len; i++){
2245 this.select(nodeInfo[i], true, true);
2248 var node = this.getNode(nodeInfo);
2249 if(node && !this.isSelected(node)){
2251 this.clearSelections(true);
2253 if(this.fireEvent("beforeselect", this, node, this.selections) !== false){
2254 Roo.fly(node).addClass(this.selectedClass);
2255 this.selections.push(node);
2257 this.fireEvent("selectionchange", this, this.selections);
2265 * Gets a template node.
2266 * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
2267 * @return {HTMLElement} The node or null if it wasn't found
2269 getNode : function(nodeInfo){
2270 if(typeof nodeInfo == "string"){
2271 return document.getElementById(nodeInfo);
2272 }else if(typeof nodeInfo == "number"){
2273 return this.nodes[nodeInfo];
2279 * Gets a range template nodes.
2280 * @param {Number} startIndex
2281 * @param {Number} endIndex
2282 * @return {Array} An array of nodes
2284 getNodes : function(start, end){
2285 var ns = this.nodes;
2287 end = typeof end == "undefined" ? ns.length - 1 : end;
2290 for(var i = start; i <= end; i++){
2294 for(var i = start; i >= end; i--){
2302 * Finds the index of the passed node
2303 * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
2304 * @return {Number} The index of the node or -1
2306 indexOf : function(node){
2307 node = this.getNode(node);
2308 if(typeof node.nodeIndex == "number"){
2309 return node.nodeIndex;
2311 var ns = this.nodes;
2312 for(var i = 0, len = ns.length; i < len; i++){
2322 * Ext JS Library 1.1.1
2323 * Copyright(c) 2006-2007, Ext JS, LLC.
2325 * Originally Released Under LGPL - original licence link has changed is not relivant.
2328 * <script type="text/javascript">
2332 * @class Roo.JsonView
2334 * Shortcut class to create a JSON + {@link Roo.UpdateManager} template view. Usage:
2336 var view = new Roo.JsonView("my-element",
2337 '<div id="{id}">{foo} - {bar}</div>', // auto create template
2338 { multiSelect: true, jsonRoot: "data" }
2341 // listen for node click?
2342 view.on("click", function(vw, index, node, e){
2343 alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
2346 // direct load of JSON data
2347 view.load("foobar.php");
2349 // Example from my blog list
2350 var tpl = new Roo.Template(
2351 '<div class="entry">' +
2352 '<a class="entry-title" href="{link}">{title}</a>' +
2353 "<h4>{date} by {author} | {comments} Comments</h4>{description}" +
2354 "</div><hr />"
2357 var moreView = new Roo.JsonView("entry-list", tpl, {
2360 moreView.on("beforerender", this.sortEntries, this);
2362 url: "/blog/get-posts.php",
2363 params: "allposts=true",
2364 text: "Loading Blog Entries..."
2368 * Create a new JsonView
2369 * @param {String/HTMLElement/Element} container The container element where the view is to be rendered.
2370 * @param {Template} tpl The rendering template
2371 * @param {Object} config The config object
2373 Roo.JsonView = function(container, tpl, config){
2374 Roo.JsonView.superclass.constructor.call(this, container, tpl, config);
2376 var um = this.el.getUpdateManager();
2377 um.setRenderer(this);
2378 um.on("update", this.onLoad, this);
2379 um.on("failure", this.onLoadException, this);
2382 * @event beforerender
2383 * Fires before rendering of the downloaded JSON data.
2384 * @param {Roo.JsonView} this
2385 * @param {Object} data The JSON data loaded
2389 * Fires when data is loaded.
2390 * @param {Roo.JsonView} this
2391 * @param {Object} data The JSON data loaded
2392 * @param {Object} response The raw Connect response object
2395 * @event loadexception
2396 * Fires when loading fails.
2397 * @param {Roo.JsonView} this
2398 * @param {Object} response The raw Connect response object
2401 'beforerender' : true,
2403 'loadexception' : true
2406 Roo.extend(Roo.JsonView, Roo.View, {
2408 * The root property in the loaded JSON object that contains the data
2414 * Refreshes the view.
2416 refresh : function(){
2417 this.clearSelections();
2420 var o = this.jsonData;
2421 if(o && o.length > 0){
2422 for(var i = 0, len = o.length; i < len; i++){
2423 var data = this.prepareData(o[i], i, o);
2424 html[html.length] = this.tpl.apply(data);
2427 html.push(this.emptyText);
2429 this.el.update(html.join(""));
2430 this.nodes = this.el.dom.childNodes;
2431 this.updateIndexes(0);
2435 * Performs an async HTTP request, and loads the JSON from the response. If <i>params</i> are specified it uses POST, otherwise it uses GET.
2436 * @param {Object/String/Function} url The URL for this request, or a function to call to get the URL, or a config object containing any of the following options:
2439 url: "your-url.php",
2440 params: {param1: "foo", param2: "bar"}, // or a URL encoded string
2441 callback: yourFunction,
2442 scope: yourObject, //(optional scope)
2450 * The only required property is <i>url</i>. The optional properties <i>nocache</i>, <i>text</i> and <i>scripts</i>
2451 * are respectively shorthand for <i>disableCaching</i>, <i>indicatorText</i>, and <i>loadScripts</i> and are used to set their associated property on this UpdateManager instance.
2452 * @param {String/Object} params (optional) The parameters to pass, as either a URL encoded string "param1=1&param2=2" or an object {param1: 1, param2: 2}
2453 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
2454 * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used URL. If true, it will not store the URL.
2457 var um = this.el.getUpdateManager();
2458 um.update.apply(um, arguments);
2461 render : function(el, response){
2462 this.clearSelections();
2466 o = Roo.util.JSON.decode(response.responseText);
2469 o = /** eval:var:o */ eval("o." + this.jsonRoot);
2474 * The current JSON data or null
2477 this.beforeRender();
2482 * Get the number of records in the current JSON dataset
2485 getCount : function(){
2486 return this.jsonData ? this.jsonData.length : 0;
2490 * Returns the JSON object for the specified node(s)
2491 * @param {HTMLElement/Array} node The node or an array of nodes
2492 * @return {Object/Array} If you pass in an array, you get an array back, otherwise
2493 * you get the JSON object for the node
2495 getNodeData : function(node){
2496 if(node instanceof Array){
2498 for(var i = 0, len = node.length; i < len; i++){
2499 data.push(this.getNodeData(node[i]));
2503 return this.jsonData[this.indexOf(node)] || null;
2506 beforeRender : function(){
2507 this.snapshot = this.jsonData;
2509 this.sort.apply(this, this.sortInfo);
2511 this.fireEvent("beforerender", this, this.jsonData);
2514 onLoad : function(el, o){
2515 this.fireEvent("load", this, this.jsonData, o);
2518 onLoadException : function(el, o){
2519 this.fireEvent("loadexception", this, o);
2523 * Filter the data by a specific property.
2524 * @param {String} property A property on your JSON objects
2525 * @param {String/RegExp} value Either string that the property values
2526 * should start with, or a RegExp to test against the property
2528 filter : function(property, value){
2531 var ss = this.snapshot;
2532 if(typeof value == "string"){
2533 var vlen = value.length;
2538 value = value.toLowerCase();
2539 for(var i = 0, len = ss.length; i < len; i++){
2541 if(o[property].substr(0, vlen).toLowerCase() == value){
2545 } else if(value.exec){ // regex?
2546 for(var i = 0, len = ss.length; i < len; i++){
2548 if(value.test(o[property])){
2555 this.jsonData = data;
2561 * Filter by a function. The passed function will be called with each
2562 * object in the current dataset. If the function returns true the value is kept,
2563 * otherwise it is filtered.
2564 * @param {Function} fn
2565 * @param {Object} scope (optional) The scope of the function (defaults to this JsonView)
2567 filterBy : function(fn, scope){
2570 var ss = this.snapshot;
2571 for(var i = 0, len = ss.length; i < len; i++){
2573 if(fn.call(scope || this, o)){
2577 this.jsonData = data;
2583 * Clears the current filter.
2585 clearFilter : function(){
2586 if(this.snapshot && this.jsonData != this.snapshot){
2587 this.jsonData = this.snapshot;
2594 * Sorts the data for this view and refreshes it.
2595 * @param {String} property A property on your JSON objects to sort on
2596 * @param {String} direction (optional) "desc" or "asc" (defaults to "asc")
2597 * @param {Function} sortType (optional) A function to call to convert the data to a sortable value.
2599 sort : function(property, dir, sortType){
2600 this.sortInfo = Array.prototype.slice.call(arguments, 0);
2603 var dsc = dir && dir.toLowerCase() == "desc";
2604 var f = function(o1, o2){
2605 var v1 = sortType ? sortType(o1[p]) : o1[p];
2606 var v2 = sortType ? sortType(o2[p]) : o2[p];
2609 return dsc ? +1 : -1;
2611 return dsc ? -1 : +1;
2616 this.jsonData.sort(f);
2618 if(this.jsonData != this.snapshot){
2619 this.snapshot.sort(f);
2625 * Ext JS Library 1.1.1
2626 * Copyright(c) 2006-2007, Ext JS, LLC.
2628 * Originally Released Under LGPL - original licence link has changed is not relivant.
2631 * <script type="text/javascript">
2636 * @class Roo.ColorPalette
2637 * @extends Roo.Component
2638 * Simple color palette class for choosing colors. The palette can be rendered to any container.<br />
2639 * Here's an example of typical usage:
2641 var cp = new Roo.ColorPalette({value:'993300'}); // initial selected color
2642 cp.render('my-div');
2644 cp.on('select', function(palette, selColor){
2645 // do something with selColor
2649 * Create a new ColorPalette
2650 * @param {Object} config The config object
2652 Roo.ColorPalette = function(config){
2653 Roo.ColorPalette.superclass.constructor.call(this, config);
2657 * Fires when a color is selected
2658 * @param {ColorPalette} this
2659 * @param {String} color The 6-digit color hex code (without the # symbol)
2665 this.on("select", this.handler, this.scope, true);
2668 Roo.extend(Roo.ColorPalette, Roo.Component, {
2670 * @cfg {String} itemCls
2671 * The CSS class to apply to the containing element (defaults to "x-color-palette")
2673 itemCls : "x-color-palette",
2675 * @cfg {String} value
2676 * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that
2677 * the hex codes are case-sensitive.
2682 ctype: "Roo.ColorPalette",
2685 * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the selection event
2687 allowReselect : false,
2690 * <p>An array of 6-digit color hex code strings (without the # symbol). This array can contain any number
2691 * of colors, and each hex code should be unique. The width of the palette is controlled via CSS by adjusting
2692 * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
2693 * of colors with the width setting until the box is symmetrical.</p>
2694 * <p>You can override individual colors if needed:</p>
2696 var cp = new Roo.ColorPalette();
2697 cp.colors[0] = "FF0000"; // change the first box to red
2700 Or you can provide a custom array of your own for complete control:
2702 var cp = new Roo.ColorPalette();
2703 cp.colors = ["000000", "993300", "333300"];
2708 "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
2709 "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
2710 "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
2711 "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
2712 "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
2716 onRender : function(container, position){
2717 var t = new Roo.MasterTemplate(
2718 '<tpl><a href="#" class="color-{0}" hidefocus="on"><em><span style="background:#{0}" unselectable="on"> </span></em></a></tpl>'
2720 var c = this.colors;
2721 for(var i = 0, len = c.length; i < len; i++){
2724 var el = document.createElement("div");
2725 el.className = this.itemCls;
2727 container.dom.insertBefore(el, position);
2728 this.el = Roo.get(el);
2729 this.el.on(this.clickEvent, this.handleClick, this, {delegate: "a"});
2730 if(this.clickEvent != 'click'){
2731 this.el.on('click', Roo.emptyFn, this, {delegate: "a", preventDefault:true});
2736 afterRender : function(){
2737 Roo.ColorPalette.superclass.afterRender.call(this);
2746 handleClick : function(e, t){
2749 var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
2750 this.select(c.toUpperCase());
2755 * Selects the specified color in the palette (fires the select event)
2756 * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
2758 select : function(color){
2759 color = color.replace("#", "");
2760 if(color != this.value || this.allowReselect){
2763 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
2765 el.child("a.color-"+color).addClass("x-color-palette-sel");
2767 this.fireEvent("select", this, color);
2772 * Ext JS Library 1.1.1
2773 * Copyright(c) 2006-2007, Ext JS, LLC.
2775 * Originally Released Under LGPL - original licence link has changed is not relivant.
2778 * <script type="text/javascript">
2782 * @class Roo.DatePicker
2783 * @extends Roo.Component
2784 * Simple date picker class.
2786 * Create a new DatePicker
2787 * @param {Object} config The config object
2789 Roo.DatePicker = function(config){
2790 Roo.DatePicker.superclass.constructor.call(this, config);
2792 this.value = config && config.value ?
2793 config.value.clearTime() : new Date().clearTime();
2798 * Fires when a date is selected
2799 * @param {DatePicker} this
2800 * @param {Date} date The selected date
2806 this.on("select", this.handler, this.scope || this);
2808 // build the disabledDatesRE
2809 if(!this.disabledDatesRE && this.disabledDates){
2810 var dd = this.disabledDates;
2812 for(var i = 0; i < dd.length; i++){
2814 if(i != dd.length-1) re += "|";
2816 this.disabledDatesRE = new RegExp(re + ")");
2820 Roo.extend(Roo.DatePicker, Roo.Component, {
2822 * @cfg {String} todayText
2823 * The text to display on the button that selects the current date (defaults to "Today")
2825 todayText : "Today",
2827 * @cfg {String} okText
2828 * The text to display on the ok button
2830 okText : " OK ", //   to give the user extra clicking room
2832 * @cfg {String} cancelText
2833 * The text to display on the cancel button
2835 cancelText : "Cancel",
2837 * @cfg {String} todayTip
2838 * The tooltip to display for the button that selects the current date (defaults to "{current date} (Spacebar)")
2840 todayTip : "{0} (Spacebar)",
2842 * @cfg {Date} minDate
2843 * Minimum allowable date (JavaScript date object, defaults to null)
2847 * @cfg {Date} maxDate
2848 * Maximum allowable date (JavaScript date object, defaults to null)
2852 * @cfg {String} minText
2853 * The error text to display if the minDate validation fails (defaults to "This date is before the minimum date")
2855 minText : "This date is before the minimum date",
2857 * @cfg {String} maxText
2858 * The error text to display if the maxDate validation fails (defaults to "This date is after the maximum date")
2860 maxText : "This date is after the maximum date",
2862 * @cfg {String} format
2863 * The default date format string which can be overriden for localization support. The format must be
2864 * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
2868 * @cfg {Array} disabledDays
2869 * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
2871 disabledDays : null,
2873 * @cfg {String} disabledDaysText
2874 * The tooltip to display when the date falls on a disabled day (defaults to "")
2876 disabledDaysText : "",
2878 * @cfg {RegExp} disabledDatesRE
2879 * JavaScript regular expression used to disable a pattern of dates (defaults to null)
2881 disabledDatesRE : null,
2883 * @cfg {String} disabledDatesText
2884 * The tooltip text to display when the date falls on a disabled date (defaults to "")
2886 disabledDatesText : "",
2888 * @cfg {Boolean} constrainToViewport
2889 * True to constrain the date picker to the viewport (defaults to true)
2891 constrainToViewport : true,
2893 * @cfg {Array} monthNames
2894 * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
2896 monthNames : Date.monthNames,
2898 * @cfg {Array} dayNames
2899 * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
2901 dayNames : Date.dayNames,
2903 * @cfg {String} nextText
2904 * The next month navigation button tooltip (defaults to 'Next Month (Control+Right)')
2906 nextText: 'Next Month (Control+Right)',
2908 * @cfg {String} prevText
2909 * The previous month navigation button tooltip (defaults to 'Previous Month (Control+Left)')
2911 prevText: 'Previous Month (Control+Left)',
2913 * @cfg {String} monthYearText
2914 * The header month selector tooltip (defaults to 'Choose a month (Control+Up/Down to move years)')
2916 monthYearText: 'Choose a month (Control+Up/Down to move years)',
2918 * @cfg {Number} startDay
2919 * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
2923 * @cfg {Bool} showClear
2924 * Show a clear button (usefull for date form elements that can be blank.)
2930 * Sets the value of the date field
2931 * @param {Date} value The date to set
2933 setValue : function(value){
2934 var old = this.value;
2935 this.value = value.clearTime(true);
2937 this.update(this.value);
2942 * Gets the current selected value of the date field
2943 * @return {Date} The selected date
2945 getValue : function(){
2952 this.update(this.activeDate);
2957 onRender : function(container, position){
2959 '<table cellspacing="0">',
2960 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',
2961 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
2962 var dn = this.dayNames;
2963 for(var i = 0; i < 7; i++){
2964 var d = this.startDay+i;
2968 m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
2970 m[m.length] = "</tr></thead><tbody><tr>";
2971 for(var i = 0; i < 42; i++) {
2972 if(i % 7 == 0 && i != 0){
2973 m[m.length] = "</tr><tr>";
2975 m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
2977 m[m.length] = '</tr></tbody></table></td></tr><tr>'+
2978 '<td colspan="3" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';
2980 var el = document.createElement("div");
2981 el.className = "x-date-picker";
2982 el.innerHTML = m.join("");
2984 container.dom.insertBefore(el, position);
2986 this.el = Roo.get(el);
2987 this.eventEl = Roo.get(el.firstChild);
2989 new Roo.util.ClickRepeater(this.el.child("td.x-date-left a"), {
2990 handler: this.showPrevMonth,
2992 preventDefault:true,
2996 new Roo.util.ClickRepeater(this.el.child("td.x-date-right a"), {
2997 handler: this.showNextMonth,
2999 preventDefault:true,
3003 this.eventEl.on("mousewheel", this.handleMouseWheel, this);
3005 this.monthPicker = this.el.down('div.x-date-mp');
3006 this.monthPicker.enableDisplayMode('block');
3008 var kn = new Roo.KeyNav(this.eventEl, {
3009 "left" : function(e){
3011 this.showPrevMonth() :
3012 this.update(this.activeDate.add("d", -1));
3015 "right" : function(e){
3017 this.showNextMonth() :
3018 this.update(this.activeDate.add("d", 1));
3023 this.showNextYear() :
3024 this.update(this.activeDate.add("d", -7));
3027 "down" : function(e){
3029 this.showPrevYear() :
3030 this.update(this.activeDate.add("d", 7));
3033 "pageUp" : function(e){
3034 this.showNextMonth();
3037 "pageDown" : function(e){
3038 this.showPrevMonth();
3041 "enter" : function(e){
3042 e.stopPropagation();
3049 this.eventEl.on("click", this.handleDateClick, this, {delegate: "a.x-date-date"});
3051 this.eventEl.addKeyListener(Roo.EventObject.SPACE, this.selectToday, this);
3053 this.el.unselectable();
3055 this.cells = this.el.select("table.x-date-inner tbody td");
3056 this.textNodes = this.el.query("table.x-date-inner tbody span");
3058 this.mbtn = new Roo.Button(this.el.child("td.x-date-middle", true), {
3060 tooltip: this.monthYearText
3063 this.mbtn.on('click', this.showMonthPicker, this);
3064 this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");
3067 var today = (new Date()).dateFormat(this.format);
3069 var baseTb = new Roo.Toolbar(this.el.child("td.x-date-bottom", true));
3071 text: String.format(this.todayText, today),
3072 tooltip: String.format(this.todayTip, today),
3073 handler: this.selectToday,
3077 //var todayBtn = new Roo.Button(this.el.child("td.x-date-bottom", true), {
3080 if (this.showClear) {
3082 baseTb.add( new Roo.Toolbar.Fill());
3085 cls: 'x-btn-icon x-btn-clear',
3086 handler: function() {
3088 this.fireEvent("select", this, '');
3098 this.update(this.value);
3101 createMonthPicker : function(){
3102 if(!this.monthPicker.dom.firstChild){
3103 var buf = ['<table border="0" cellspacing="0">'];
3104 for(var i = 0; i < 6; i++){
3106 '<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
3107 '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
3109 '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
3110 '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
3114 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
3116 '</button><button type="button" class="x-date-mp-cancel">',
3118 '</button></td></tr>',
3121 this.monthPicker.update(buf.join(''));
3122 this.monthPicker.on('click', this.onMonthClick, this);
3123 this.monthPicker.on('dblclick', this.onMonthDblClick, this);
3125 this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
3126 this.mpYears = this.monthPicker.select('td.x-date-mp-year');
3128 this.mpMonths.each(function(m, a, i){
3131 m.dom.xmonth = 5 + Math.round(i * .5);
3133 m.dom.xmonth = Math.round((i-1) * .5);
3139 showMonthPicker : function(){
3140 this.createMonthPicker();
3141 var size = this.el.getSize();
3142 this.monthPicker.setSize(size);
3143 this.monthPicker.child('table').setSize(size);
3145 this.mpSelMonth = (this.activeDate || this.value).getMonth();
3146 this.updateMPMonth(this.mpSelMonth);
3147 this.mpSelYear = (this.activeDate || this.value).getFullYear();
3148 this.updateMPYear(this.mpSelYear);
3150 this.monthPicker.slideIn('t', {duration:.2});
3153 updateMPYear : function(y){
3155 var ys = this.mpYears.elements;
3156 for(var i = 1; i <= 10; i++){
3157 var td = ys[i-1], y2;
3159 y2 = y + Math.round(i * .5);
3160 td.firstChild.innerHTML = y2;
3163 y2 = y - (5-Math.round(i * .5));
3164 td.firstChild.innerHTML = y2;
3167 this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
3171 updateMPMonth : function(sm){
3172 this.mpMonths.each(function(m, a, i){
3173 m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
3177 selectMPMonth: function(m){
3181 onMonthClick : function(e, t){
3183 var el = new Roo.Element(t), pn;
3184 if(el.is('button.x-date-mp-cancel')){
3185 this.hideMonthPicker();
3187 else if(el.is('button.x-date-mp-ok')){
3188 this.update(new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
3189 this.hideMonthPicker();
3191 else if(pn = el.up('td.x-date-mp-month', 2)){
3192 this.mpMonths.removeClass('x-date-mp-sel');
3193 pn.addClass('x-date-mp-sel');
3194 this.mpSelMonth = pn.dom.xmonth;
3196 else if(pn = el.up('td.x-date-mp-year', 2)){
3197 this.mpYears.removeClass('x-date-mp-sel');
3198 pn.addClass('x-date-mp-sel');
3199 this.mpSelYear = pn.dom.xyear;
3201 else if(el.is('a.x-date-mp-prev')){
3202 this.updateMPYear(this.mpyear-10);
3204 else if(el.is('a.x-date-mp-next')){
3205 this.updateMPYear(this.mpyear+10);
3209 onMonthDblClick : function(e, t){
3211 var el = new Roo.Element(t), pn;
3212 if(pn = el.up('td.x-date-mp-month', 2)){
3213 this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
3214 this.hideMonthPicker();
3216 else if(pn = el.up('td.x-date-mp-year', 2)){
3217 this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
3218 this.hideMonthPicker();
3222 hideMonthPicker : function(disableAnim){
3223 if(this.monthPicker){
3224 if(disableAnim === true){
3225 this.monthPicker.hide();
3227 this.monthPicker.slideOut('t', {duration:.2});
3233 showPrevMonth : function(e){
3234 this.update(this.activeDate.add("mo", -1));
3238 showNextMonth : function(e){
3239 this.update(this.activeDate.add("mo", 1));
3243 showPrevYear : function(){
3244 this.update(this.activeDate.add("y", -1));
3248 showNextYear : function(){
3249 this.update(this.activeDate.add("y", 1));
3253 handleMouseWheel : function(e){
3254 var delta = e.getWheelDelta();
3256 this.showPrevMonth();
3258 } else if(delta < 0){
3259 this.showNextMonth();
3265 handleDateClick : function(e, t){
3267 if(t.dateValue && !Roo.fly(t.parentNode).hasClass("x-date-disabled")){
3268 this.setValue(new Date(t.dateValue));
3269 this.fireEvent("select", this, this.value);
3274 selectToday : function(){
3275 this.setValue(new Date().clearTime());
3276 this.fireEvent("select", this, this.value);
3280 update : function(date){
3281 var vd = this.activeDate;
3282 this.activeDate = date;
3284 var t = date.getTime();
3285 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
3286 this.cells.removeClass("x-date-selected");
3287 this.cells.each(function(c){
3288 if(c.dom.firstChild.dateValue == t){
3289 c.addClass("x-date-selected");
3290 setTimeout(function(){
3291 try{c.dom.firstChild.focus();}catch(e){}
3299 var days = date.getDaysInMonth();
3300 var firstOfMonth = date.getFirstDateOfMonth();
3301 var startingPos = firstOfMonth.getDay()-this.startDay;
3303 if(startingPos <= this.startDay){
3307 var pm = date.add("mo", -1);
3308 var prevStart = pm.getDaysInMonth()-startingPos;
3310 var cells = this.cells.elements;
3311 var textEls = this.textNodes;
3312 days += startingPos;
3314 // convert everything to numbers so it's fast
3316 var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
3317 var today = new Date().clearTime().getTime();
3318 var sel = date.clearTime().getTime();
3319 var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
3320 var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
3321 var ddMatch = this.disabledDatesRE;
3322 var ddText = this.disabledDatesText;
3323 var ddays = this.disabledDays ? this.disabledDays.join("") : false;
3324 var ddaysText = this.disabledDaysText;
3325 var format = this.format;
3327 var setCellClass = function(cal, cell){
3329 var t = d.getTime();
3330 cell.firstChild.dateValue = t;
3332 cell.className += " x-date-today";
3333 cell.title = cal.todayText;
3336 cell.className += " x-date-selected";
3337 setTimeout(function(){
3338 try{cell.firstChild.focus();}catch(e){}
3343 cell.className = " x-date-disabled";
3344 cell.title = cal.minText;
3348 cell.className = " x-date-disabled";
3349 cell.title = cal.maxText;
3353 if(ddays.indexOf(d.getDay()) != -1){
3354 cell.title = ddaysText;
3355 cell.className = " x-date-disabled";
3358 if(ddMatch && format){
3359 var fvalue = d.dateFormat(format);
3360 if(ddMatch.test(fvalue)){
3361 cell.title = ddText.replace("%0", fvalue);
3362 cell.className = " x-date-disabled";
3368 for(; i < startingPos; i++) {
3369 textEls[i].innerHTML = (++prevStart);
3370 d.setDate(d.getDate()+1);
3371 cells[i].className = "x-date-prevday";
3372 setCellClass(this, cells[i]);
3374 for(; i < days; i++){
3375 intDay = i - startingPos + 1;
3376 textEls[i].innerHTML = (intDay);
3377 d.setDate(d.getDate()+1);
3378 cells[i].className = "x-date-active";
3379 setCellClass(this, cells[i]);
3382 for(; i < 42; i++) {
3383 textEls[i].innerHTML = (++extraDays);
3384 d.setDate(d.getDate()+1);
3385 cells[i].className = "x-date-nextday";
3386 setCellClass(this, cells[i]);
3389 this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());
3391 if(!this.internalRender){
3392 var main = this.el.dom.firstChild;
3393 var w = main.offsetWidth;
3394 this.el.setWidth(w + this.el.getBorderWidth("lr"));
3395 Roo.fly(main).setWidth(w);
3396 this.internalRender = true;
3397 // opera does not respect the auto grow header center column
3398 // then, after it gets a width opera refuses to recalculate
3399 // without a second pass
3400 if(Roo.isOpera && !this.secondPass){
3401 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
3402 this.secondPass = true;
3403 this.update.defer(10, this, [date]);
3409 * Ext JS Library 1.1.1
3410 * Copyright(c) 2006-2007, Ext JS, LLC.
3412 * Originally Released Under LGPL - original licence link has changed is not relivant.
3415 * <script type="text/javascript">
3418 * @class Roo.TabPanel
3419 * @extends Roo.util.Observable
3420 * A lightweight tab container.
3424 // basic tabs 1, built from existing content
3425 var tabs = new Roo.TabPanel("tabs1");
3426 tabs.addTab("script", "View Script");
3427 tabs.addTab("markup", "View Markup");
3428 tabs.activate("script");
3430 // more advanced tabs, built from javascript
3431 var jtabs = new Roo.TabPanel("jtabs");
3432 jtabs.addTab("jtabs-1", "Normal Tab", "My content was added during construction.");
3434 // set up the UpdateManager
3435 var tab2 = jtabs.addTab("jtabs-2", "Ajax Tab 1");
3436 var updater = tab2.getUpdateManager();
3437 updater.setDefaultUrl("ajax1.htm");
3438 tab2.on('activate', updater.refresh, updater, true);
3440 // Use setUrl for Ajax loading
3441 var tab3 = jtabs.addTab("jtabs-3", "Ajax Tab 2");
3442 tab3.setUrl("ajax2.htm", null, true);
3445 var tab4 = jtabs.addTab("tabs1-5", "Disabled Tab", "Can't see me cause I'm disabled");
3448 jtabs.activate("jtabs-1");
3451 * Create a new TabPanel.
3452 * @param {String/HTMLElement/Roo.Element} container The id, DOM element or Roo.Element container where this TabPanel is to be rendered.
3453 * @param {Object/Boolean} config Config object to set any properties for this TabPanel, or true to render the tabs on the bottom.
3455 Roo.TabPanel = function(container, config){
3457 * The container element for this TabPanel.
3460 this.el = Roo.get(container, true);
3462 if(typeof config == "boolean"){
3463 this.tabPosition = config ? "bottom" : "top";
3465 Roo.apply(this, config);
3468 if(this.tabPosition == "bottom"){
3469 this.bodyEl = Roo.get(this.createBody(this.el.dom));
3470 this.el.addClass("x-tabs-bottom");
3472 this.stripWrap = Roo.get(this.createStrip(this.el.dom), true);
3473 this.stripEl = Roo.get(this.createStripList(this.stripWrap.dom), true);
3474 this.stripBody = Roo.get(this.stripWrap.dom.firstChild.firstChild, true);
3476 Roo.fly(this.stripWrap.dom.firstChild).setStyle("overflow-x", "hidden");
3478 if(this.tabPosition != "bottom"){
3479 /** The body element that contains {@link Roo.TabPanelItem} bodies.
3482 this.bodyEl = Roo.get(this.createBody(this.el.dom));
3483 this.el.addClass("x-tabs-top");
3487 this.bodyEl.setStyle("position", "relative");
3490 this.activateDelegate = this.activate.createDelegate(this);
3495 * Fires when the active tab changes
3496 * @param {Roo.TabPanel} this
3497 * @param {Roo.TabPanelItem} activePanel The new active tab
3501 * @event beforetabchange
3502 * Fires before the active tab changes, set cancel to true on the "e" parameter to cancel the change
3503 * @param {Roo.TabPanel} this
3504 * @param {Object} e Set cancel to true on this object to cancel the tab change
3505 * @param {Roo.TabPanelItem} tab The tab being changed to
3507 "beforetabchange" : true
3510 Roo.EventManager.onWindowResize(this.onResize, this);
3511 this.cpad = this.el.getPadding("lr");
3512 this.hiddenCount = 0;
3514 Roo.TabPanel.superclass.constructor.call(this);
3517 Roo.extend(Roo.TabPanel, Roo.util.Observable, {
3519 *@cfg {String} tabPosition "top" or "bottom" (defaults to "top")
3521 tabPosition : "top",
3523 *@cfg {Number} currentTabWidth The width of the current tab (defaults to 0)
3525 currentTabWidth : 0,
3527 *@cfg {Number} minTabWidth The minimum width of a tab (defaults to 40) (ignored if {@link #resizeTabs} is not true)
3531 *@cfg {Number} maxTabWidth The maximum width of a tab (defaults to 250) (ignored if {@link #resizeTabs} is not true)
3535 *@cfg {Number} preferredTabWidth The preferred (default) width of a tab (defaults to 175) (ignored if {@link #resizeTabs} is not true)
3537 preferredTabWidth : 175,
3539 *@cfg {Boolean} resizeTabs True to enable dynamic tab resizing (defaults to false)
3543 *@cfg {Boolean} monitorResize Set this to true to turn on window resize monitoring (ignored if {@link #resizeTabs} is not true) (defaults to true)
3545 monitorResize : true,
3548 * Creates a new {@link Roo.TabPanelItem} by looking for an existing element with the provided id -- if it's not found it creates one.
3549 * @param {String} id The id of the div to use <b>or create</b>
3550 * @param {String} text The text for the tab
3551 * @param {String} content (optional) Content to put in the TabPanelItem body
3552 * @param {Boolean} closable (optional) True to create a close icon on the tab
3553 * @return {Roo.TabPanelItem} The created TabPanelItem
3555 addTab : function(id, text, content, closable){
3556 var item = new Roo.TabPanelItem(this, id, text, closable);
3557 this.addTabItem(item);
3559 item.setContent(content);
3565 * Returns the {@link Roo.TabPanelItem} with the specified id/index
3566 * @param {String/Number} id The id or index of the TabPanelItem to fetch.
3567 * @return {Roo.TabPanelItem}
3569 getTab : function(id){
3570 return this.items[id];
3574 * Hides the {@link Roo.TabPanelItem} with the specified id/index
3575 * @param {String/Number} id The id or index of the TabPanelItem to hide.
3577 hideTab : function(id){
3578 var t = this.items[id];
3582 this.autoSizeTabs();
3587 * "Unhides" the {@link Roo.TabPanelItem} with the specified id/index.
3588 * @param {String/Number} id The id or index of the TabPanelItem to unhide.
3590 unhideTab : function(id){
3591 var t = this.items[id];
3595 this.autoSizeTabs();
3600 * Adds an existing {@link Roo.TabPanelItem}.
3601 * @param {Roo.TabPanelItem} item The TabPanelItem to add
3603 addTabItem : function(item){
3604 this.items[item.id] = item;
3605 this.items.push(item);
3606 if(this.resizeTabs){
3607 item.setWidth(this.currentTabWidth || this.preferredTabWidth);
3608 this.autoSizeTabs();
3615 * Removes a {@link Roo.TabPanelItem}.
3616 * @param {String/Number} id The id or index of the TabPanelItem to remove.
3618 removeTab : function(id){
3619 var items = this.items;
3620 var tab = items[id];
3622 var index = items.indexOf(tab);
3623 if(this.active == tab && items.length > 1){
3624 var newTab = this.getNextAvailable(index);
3625 if(newTab)newTab.activate();
3627 this.stripEl.dom.removeChild(tab.pnode.dom);
3628 if(tab.bodyEl.dom.parentNode == this.bodyEl.dom){ // if it was moved already prevent error
3629 this.bodyEl.dom.removeChild(tab.bodyEl.dom);
3631 items.splice(index, 1);
3632 delete this.items[tab.id];
3633 tab.fireEvent("close", tab);
3634 tab.purgeListeners();
3635 this.autoSizeTabs();
3638 getNextAvailable : function(start){
3639 var items = this.items;
3641 // look for a next tab that will slide over to
3642 // replace the one being removed
3643 while(index < items.length){
3644 var item = items[++index];
3645 if(item && !item.isHidden()){
3649 // if one isn't found select the previous tab (on the left)
3652 var item = items[--index];
3653 if(item && !item.isHidden()){
3661 * Disables a {@link Roo.TabPanelItem}. It cannot be the active tab, if it is this call is ignored.
3662 * @param {String/Number} id The id or index of the TabPanelItem to disable.
3664 disableTab : function(id){
3665 var tab = this.items[id];
3666 if(tab && this.active != tab){
3672 * Enables a {@link Roo.TabPanelItem} that is disabled.
3673 * @param {String/Number} id The id or index of the TabPanelItem to enable.
3675 enableTab : function(id){
3676 var tab = this.items[id];
3681 * Activates a {@link Roo.TabPanelItem}. The currently active one will be deactivated.
3682 * @param {String/Number} id The id or index of the TabPanelItem to activate.
3683 * @return {Roo.TabPanelItem} The TabPanelItem.
3685 activate : function(id){
3686 var tab = this.items[id];
3690 if(tab == this.active || tab.disabled){
3694 this.fireEvent("beforetabchange", this, e, tab);
3695 if(e.cancel !== true && !tab.disabled){
3699 this.active = this.items[id];
3701 this.fireEvent("tabchange", this, this.active);
3707 * Gets the active {@link Roo.TabPanelItem}.
3708 * @return {Roo.TabPanelItem} The active TabPanelItem or null if none are active.
3710 getActiveTab : function(){
3715 * Updates the tab body element to fit the height of the container element
3716 * for overflow scrolling
3717 * @param {Number} targetHeight (optional) Override the starting height from the elements height
3719 syncHeight : function(targetHeight){
3720 var height = (targetHeight || this.el.getHeight())-this.el.getBorderWidth("tb")-this.el.getPadding("tb");
3721 var bm = this.bodyEl.getMargins();
3722 var newHeight = height-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
3723 this.bodyEl.setHeight(newHeight);
3727 onResize : function(){
3728 if(this.monitorResize){
3729 this.autoSizeTabs();
3734 * Disables tab resizing while tabs are being added (if {@link #resizeTabs} is false this does nothing)
3736 beginUpdate : function(){
3737 this.updating = true;
3741 * Stops an update and resizes the tabs (if {@link #resizeTabs} is false this does nothing)
3743 endUpdate : function(){
3744 this.updating = false;
3745 this.autoSizeTabs();
3749 * Manual call to resize the tabs (if {@link #resizeTabs} is false this does nothing)
3751 autoSizeTabs : function(){
3752 var count = this.items.length;
3753 var vcount = count - this.hiddenCount;
3754 if(!this.resizeTabs || count < 1 || vcount < 1 || this.updating) return;
3755 var w = Math.max(this.el.getWidth() - this.cpad, 10);
3756 var availWidth = Math.floor(w / vcount);
3757 var b = this.stripBody;
3758 if(b.getWidth() > w){
3759 var tabs = this.items;
3760 this.setTabWidth(Math.max(availWidth, this.minTabWidth)-2);
3761 if(availWidth < this.minTabWidth){
3762 /*if(!this.sleft){ // incomplete scrolling code
3763 this.createScrollButtons();
3766 this.stripClip.setWidth(w - (this.sleft.getWidth()+this.sright.getWidth()));*/
3769 if(this.currentTabWidth < this.preferredTabWidth){
3770 this.setTabWidth(Math.min(availWidth, this.preferredTabWidth)-2);
3776 * Returns the number of tabs in this TabPanel.
3779 getCount : function(){
3780 return this.items.length;
3784 * Resizes all the tabs to the passed width
3785 * @param {Number} The new width
3787 setTabWidth : function(width){
3788 this.currentTabWidth = width;
3789 for(var i = 0, len = this.items.length; i < len; i++) {
3790 if(!this.items[i].isHidden())this.items[i].setWidth(width);
3795 * Destroys this TabPanel
3796 * @param {Boolean} removeEl (optional) True to remove the element from the DOM as well (defaults to undefined)
3798 destroy : function(removeEl){
3799 Roo.EventManager.removeResizeListener(this.onResize, this);
3800 for(var i = 0, len = this.items.length; i < len; i++){
3801 this.items[i].purgeListeners();
3803 if(removeEl === true){
3811 * @class Roo.TabPanelItem
3812 * @extends Roo.util.Observable
3813 * Represents an individual item (tab plus body) in a TabPanel.
3814 * @param {Roo.TabPanel} tabPanel The {@link Roo.TabPanel} this TabPanelItem belongs to
3815 * @param {String} id The id of this TabPanelItem
3816 * @param {String} text The text for the tab of this TabPanelItem
3817 * @param {Boolean} closable True to allow this TabPanelItem to be closable (defaults to false)
3819 Roo.TabPanelItem = function(tabPanel, id, text, closable){
3821 * The {@link Roo.TabPanel} this TabPanelItem belongs to
3822 * @type Roo.TabPanel
3824 this.tabPanel = tabPanel;
3826 * The id for this TabPanelItem
3831 this.disabled = false;
3835 this.loaded = false;
3836 this.closable = closable;
3839 * The body element for this TabPanelItem.
3842 this.bodyEl = Roo.get(tabPanel.createItemBody(tabPanel.bodyEl.dom, id));
3843 this.bodyEl.setVisibilityMode(Roo.Element.VISIBILITY);
3844 this.bodyEl.setStyle("display", "block");
3845 this.bodyEl.setStyle("zoom", "1");
3848 var els = tabPanel.createStripElements(tabPanel.stripEl.dom, text, closable);
3850 this.el = Roo.get(els.el, true);
3851 this.inner = Roo.get(els.inner, true);
3852 this.textEl = Roo.get(this.el.dom.firstChild.firstChild.firstChild, true);
3853 this.pnode = Roo.get(els.el.parentNode, true);
3854 this.el.on("mousedown", this.onTabMouseDown, this);
3855 this.el.on("click", this.onTabClick, this);
3858 var c = Roo.get(els.close, true);
3859 c.dom.title = this.closeText;
3860 c.addClassOnOver("close-over");
3861 c.on("click", this.closeClick, this);
3867 * Fires when this tab becomes the active tab.
3868 * @param {Roo.TabPanel} tabPanel The parent TabPanel
3869 * @param {Roo.TabPanelItem} this
3873 * @event beforeclose
3874 * Fires before this tab is closed. To cancel the close, set cancel to true on e (e.cancel = true).
3875 * @param {Roo.TabPanelItem} this
3876 * @param {Object} e Set cancel to true on this object to cancel the close.
3878 "beforeclose": true,
3881 * Fires when this tab is closed.
3882 * @param {Roo.TabPanelItem} this
3887 * Fires when this tab is no longer the active tab.
3888 * @param {Roo.TabPanel} tabPanel The parent TabPanel
3889 * @param {Roo.TabPanelItem} this
3893 this.hidden = false;
3895 Roo.TabPanelItem.superclass.constructor.call(this);
3898 Roo.extend(Roo.TabPanelItem, Roo.util.Observable, {
3899 purgeListeners : function(){
3900 Roo.util.Observable.prototype.purgeListeners.call(this);
3901 this.el.removeAllListeners();
3904 * Shows this TabPanelItem -- this <b>does not</b> deactivate the currently active TabPanelItem.
3907 this.pnode.addClass("on");
3910 this.tabPanel.stripWrap.repaint();
3912 this.fireEvent("activate", this.tabPanel, this);
3916 * Returns true if this tab is the active tab.
3919 isActive : function(){
3920 return this.tabPanel.getActiveTab() == this;
3924 * Hides this TabPanelItem -- if you don't activate another TabPanelItem this could look odd.
3927 this.pnode.removeClass("on");
3929 this.fireEvent("deactivate", this.tabPanel, this);
3932 hideAction : function(){
3934 this.bodyEl.setStyle("position", "absolute");
3935 this.bodyEl.setLeft("-20000px");
3936 this.bodyEl.setTop("-20000px");
3939 showAction : function(){
3940 this.bodyEl.setStyle("position", "relative");
3941 this.bodyEl.setTop("");
3942 this.bodyEl.setLeft("");
3947 * Set the tooltip for the tab.
3948 * @param {String} tooltip The tab's tooltip
3950 setTooltip : function(text){
3951 if(Roo.QuickTips && Roo.QuickTips.isEnabled()){
3952 this.textEl.dom.qtip = text;
3953 this.textEl.dom.removeAttribute('title');
3955 this.textEl.dom.title = text;
3959 onTabClick : function(e){
3961 this.tabPanel.activate(this.id);
3964 onTabMouseDown : function(e){
3966 this.tabPanel.activate(this.id);
3969 getWidth : function(){
3970 return this.inner.getWidth();
3973 setWidth : function(width){
3974 var iwidth = width - this.pnode.getPadding("lr");
3975 this.inner.setWidth(iwidth);
3976 this.textEl.setWidth(iwidth-this.inner.getPadding("lr"));
3977 this.pnode.setWidth(width);
3981 * Show or hide the tab
3982 * @param {Boolean} hidden True to hide or false to show.
3984 setHidden : function(hidden){
3985 this.hidden = hidden;
3986 this.pnode.setStyle("display", hidden ? "none" : "");
3990 * Returns true if this tab is "hidden"
3993 isHidden : function(){
3998 * Returns the text for this tab
4001 getText : function(){
4005 autoSize : function(){
4006 //this.el.beginMeasure();
4007 this.textEl.setWidth(1);
4008 this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding("lr"));
4009 //this.el.endMeasure();
4013 * Sets the text for the tab (Note: this also sets the tooltip text)
4014 * @param {String} text The tab's text and tooltip
4016 setText : function(text){
4018 this.textEl.update(text);
4019 this.setTooltip(text);
4020 if(!this.tabPanel.resizeTabs){
4025 * Activates this TabPanelItem -- this <b>does</b> deactivate the currently active TabPanelItem.
4027 activate : function(){
4028 this.tabPanel.activate(this.id);
4032 * Disables this TabPanelItem -- this does nothing if this is the active TabPanelItem.
4034 disable : function(){
4035 if(this.tabPanel.active != this){
4036 this.disabled = true;
4037 this.pnode.addClass("disabled");
4042 * Enables this TabPanelItem if it was previously disabled.
4044 enable : function(){
4045 this.disabled = false;
4046 this.pnode.removeClass("disabled");
4050 * Sets the content for this TabPanelItem.
4051 * @param {String} content The content
4052 * @param {Boolean} loadScripts true to look for and load scripts
4054 setContent : function(content, loadScripts){
4055 this.bodyEl.update(content, loadScripts);
4059 * Gets the {@link Roo.UpdateManager} for the body of this TabPanelItem. Enables you to perform Ajax updates.
4060 * @return {Roo.UpdateManager} The UpdateManager
4062 getUpdateManager : function(){
4063 return this.bodyEl.getUpdateManager();
4067 * Set a URL to be used to load the content for this TabPanelItem.
4068 * @param {String/Function} url The URL to load the content from, or a function to call to get the URL
4069 * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
4070 * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this TabPanelItem is activated. (Defaults to false)
4071 * @return {Roo.UpdateManager} The UpdateManager
4073 setUrl : function(url, params, loadOnce){
4074 if(this.refreshDelegate){
4075 this.un('activate', this.refreshDelegate);
4077 this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
4078 this.on("activate", this.refreshDelegate);
4079 return this.bodyEl.getUpdateManager();
4083 _handleRefresh : function(url, params, loadOnce){
4084 if(!loadOnce || !this.loaded){
4085 var updater = this.bodyEl.getUpdateManager();
4086 updater.update(url, params, this._setLoaded.createDelegate(this));
4091 * Forces a content refresh from the URL specified in the {@link #setUrl} method.
4092 * Will fail silently if the setUrl method has not been called.
4093 * This does not activate the panel, just updates its content.
4095 refresh : function(){
4096 if(this.refreshDelegate){
4097 this.loaded = false;
4098 this.refreshDelegate();
4103 _setLoaded : function(){
4108 closeClick : function(e){
4111 this.fireEvent("beforeclose", this, o);
4112 if(o.cancel !== true){
4113 this.tabPanel.removeTab(this.id);
4117 * The text displayed in the tooltip for the close icon.
4120 closeText : "Close this tab"
4124 Roo.TabPanel.prototype.createStrip = function(container){
4125 var strip = document.createElement("div");
4126 strip.className = "x-tabs-wrap";
4127 container.appendChild(strip);
4131 Roo.TabPanel.prototype.createStripList = function(strip){
4132 // div wrapper for retard IE
4133 strip.innerHTML = '<div class="x-tabs-strip-wrap"><table class="x-tabs-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr></tr></tbody></table></div>';
4134 return strip.firstChild.firstChild.firstChild.firstChild;
4137 Roo.TabPanel.prototype.createBody = function(container){
4138 var body = document.createElement("div");
4139 Roo.id(body, "tab-body");
4140 Roo.fly(body).addClass("x-tabs-body");
4141 container.appendChild(body);
4145 Roo.TabPanel.prototype.createItemBody = function(bodyEl, id){
4146 var body = Roo.getDom(id);
4148 body = document.createElement("div");
4151 Roo.fly(body).addClass("x-tabs-item-body");
4152 bodyEl.insertBefore(body, bodyEl.firstChild);
4156 Roo.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
4157 var td = document.createElement("td");
4158 stripEl.appendChild(td);
4160 td.className = "x-tabs-closable";
4162 this.closeTpl = new Roo.Template(
4163 '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
4164 '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span>' +
4165 '<div unselectable="on" class="close-icon"> </div></em></span></a>'
4168 var el = this.closeTpl.overwrite(td, {"text": text});
4169 var close = el.getElementsByTagName("div")[0];
4170 var inner = el.getElementsByTagName("em")[0];
4171 return {"el": el, "close": close, "inner": inner};
4174 this.tabTpl = new Roo.Template(
4175 '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
4176 '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span></em></span></a>'
4179 var el = this.tabTpl.overwrite(td, {"text": text});
4180 var inner = el.getElementsByTagName("em")[0];
4181 return {"el": el, "inner": inner};
4185 * Ext JS Library 1.1.1
4186 * Copyright(c) 2006-2007, Ext JS, LLC.
4188 * Originally Released Under LGPL - original licence link has changed is not relivant.
4191 * <script type="text/javascript">
4196 * @extends Roo.util.Observable
4197 * Simple Button class
4198 * @cfg {String} text The button text
4199 * @cfg {String} icon The path to an image to display in the button (the image will be set as the background-image
4200 * CSS property of the button by default, so if you want a mixed icon/text button, set cls:"x-btn-text-icon")
4201 * @cfg {Function} handler A function called when the button is clicked (can be used instead of click event)
4202 * @cfg {Object} scope The scope of the handler
4203 * @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width)
4204 * @cfg {String/Object} tooltip The tooltip for the button - can be a string or QuickTips config object
4205 * @cfg {Boolean} hidden True to start hidden (defaults to false)
4206 * @cfg {Boolean} disabled True to start disabled (defaults to false)
4207 * @cfg {Boolean} pressed True to start pressed (only if enableToggle = true)
4208 * @cfg {String} toggleGroup The group this toggle button is a member of (only 1 per group can be pressed, only
4209 applies if enableToggle = true)
4210 * @cfg {String/HTMLElement/Element} renderTo The element to append the button to
4211 * @cfg {Boolean/Object} repeat True to repeat fire the click event while the mouse is down. This can also be
4212 an {@link Roo.util.ClickRepeater} config object (defaults to false).
4214 * Create a new button
4215 * @param {Object} config The config object
4217 Roo.Button = function(renderTo, config)
4221 renderTo = config.renderTo || false;
4224 Roo.apply(this, config);
4228 * Fires when this button is clicked
4229 * @param {Button} this
4230 * @param {EventObject} e The click event
4235 * Fires when the "pressed" state of this button changes (only if enableToggle = true)
4236 * @param {Button} this
4237 * @param {Boolean} pressed
4242 * Fires when the mouse hovers over the button
4243 * @param {Button} this
4244 * @param {Event} e The event object
4249 * Fires when the mouse exits the button
4250 * @param {Button} this
4251 * @param {Event} e The event object
4256 * Fires when the button is rendered
4257 * @param {Button} this
4262 this.menu = Roo.menu.MenuMgr.get(this.menu);
4265 this.render(renderTo);
4268 Roo.util.Observable.call(this);
4271 Roo.extend(Roo.Button, Roo.util.Observable, {
4277 * Read-only. True if this button is hidden
4282 * Read-only. True if this button is disabled
4287 * Read-only. True if this button is pressed (only if enableToggle = true)
4293 * @cfg {Number} tabIndex
4294 * The DOM tabIndex for this button (defaults to undefined)
4296 tabIndex : undefined,
4299 * @cfg {Boolean} enableToggle
4300 * True to enable pressed/not pressed toggling (defaults to false)
4302 enableToggle: false,
4305 * Standard menu attribute consisting of a reference to a menu object, a menu id or a menu config blob (defaults to undefined).
4309 * @cfg {String} menuAlign
4310 * The position to align the menu to (see {@link Roo.Element#alignTo} for more details, defaults to 'tl-bl?').
4312 menuAlign : "tl-bl?",
4315 * @cfg {String} iconCls
4316 * A css class which sets a background image to be used as the icon for this button (defaults to undefined).
4318 iconCls : undefined,
4320 * @cfg {String} type
4321 * The button's type, corresponding to the DOM input element type attribute. Either "submit," "reset" or "button" (default).
4326 menuClassTarget: 'tr',
4329 * @cfg {String} clickEvent
4330 * The type of event to map to the button's event handler (defaults to 'click')
4332 clickEvent : 'click',
4335 * @cfg {Boolean} handleMouseEvents
4336 * False to disable visual cues on mouseover, mouseout and mousedown (defaults to true)
4338 handleMouseEvents : true,
4341 * @cfg {String} tooltipType
4342 * The type of tooltip to use. Either "qtip" (default) for QuickTips or "title" for title attribute.
4344 tooltipType : 'qtip',
4348 * A CSS class to apply to the button's main element.
4352 * @cfg {Roo.Template} template (Optional)
4353 * An {@link Roo.Template} with which to create the Button's main element. This Template must
4354 * contain numeric substitution parameter 0 if it is to display the tRoo property. Changing the template could
4355 * require code modifications if required elements (e.g. a button) aren't present.
4359 render : function(renderTo){
4361 if(this.hideParent){
4362 this.parentEl = Roo.get(renderTo);
4366 if(!Roo.Button.buttonTemplate){
4367 // hideous table template
4368 Roo.Button.buttonTemplate = new Roo.Template(
4369 '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
4370 '<td class="x-btn-left"><i> </i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}">{0}</button></em></td><td class="x-btn-right"><i> </i></td>',
4371 "</tr></tbody></table>");
4373 this.template = Roo.Button.buttonTemplate;
4375 btn = this.template.append(renderTo, [this.text || ' ', this.type], true);
4376 var btnEl = btn.child("button:first");
4377 btnEl.on('focus', this.onFocus, this);
4378 btnEl.on('blur', this.onBlur, this);
4380 btn.addClass(this.cls);
4383 btnEl.setStyle('background-image', 'url(' +this.icon +')');
4386 btnEl.addClass(this.iconCls);
4388 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
4391 if(this.tabIndex !== undefined){
4392 btnEl.dom.tabIndex = this.tabIndex;
4395 if(typeof this.tooltip == 'object'){
4396 Roo.QuickTips.tips(Roo.apply({
4400 btnEl.dom[this.tooltipType] = this.tooltip;
4404 btn = Roo.DomHelper.append(Roo.get(renderTo).dom, this.dhconfig, true);
4408 this.el.dom.id = this.el.id = this.id;
4411 this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
4412 this.menu.on("show", this.onMenuShow, this);
4413 this.menu.on("hide", this.onMenuHide, this);
4415 btn.addClass("x-btn");
4416 if(Roo.isIE && !Roo.isIE7){
4417 this.autoWidth.defer(1, this);
4421 if(this.handleMouseEvents){
4422 btn.on("mouseover", this.onMouseOver, this);
4423 btn.on("mouseout", this.onMouseOut, this);
4424 btn.on("mousedown", this.onMouseDown, this);
4426 btn.on(this.clickEvent, this.onClick, this);
4427 //btn.on("mouseup", this.onMouseUp, this);
4434 Roo.ButtonToggleMgr.register(this);
4436 this.el.addClass("x-btn-pressed");
4439 var repeater = new Roo.util.ClickRepeater(btn,
4440 typeof this.repeat == "object" ? this.repeat : {}
4442 repeater.on("click", this.onClick, this);
4444 this.fireEvent('render', this);
4448 * Returns the button's underlying element
4449 * @return {Roo.Element} The element
4456 * Destroys this Button and removes any listeners.
4458 destroy : function(){
4459 Roo.ButtonToggleMgr.unregister(this);
4460 this.el.removeAllListeners();
4461 this.purgeListeners();
4466 autoWidth : function(){
4468 this.el.setWidth("auto");
4469 if(Roo.isIE7 && Roo.isStrict){
4470 var ib = this.el.child('button');
4471 if(ib && ib.getWidth() > 20){
4473 ib.setWidth(Roo.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
4478 this.el.beginMeasure();
4480 if(this.el.getWidth() < this.minWidth){
4481 this.el.setWidth(this.minWidth);
4484 this.el.endMeasure();
4491 * Assigns this button's click handler
4492 * @param {Function} handler The function to call when the button is clicked
4493 * @param {Object} scope (optional) Scope for the function passed in
4495 setHandler : function(handler, scope){
4496 this.handler = handler;
4501 * Sets this button's text
4502 * @param {String} text The button text
4504 setText : function(text){
4507 this.el.child("td.x-btn-center button.x-btn-text").update(text);
4513 * Gets the text for this button
4514 * @return {String} The button text
4516 getText : function(){
4524 this.hidden = false;
4526 this[this.hideParent? 'parentEl' : 'el'].setStyle("display", "");
4536 this[this.hideParent? 'parentEl' : 'el'].setStyle("display", "none");
4541 * Convenience function for boolean show/hide
4542 * @param {Boolean} visible True to show, false to hide
4544 setVisible: function(visible){
4553 * If a state it passed, it becomes the pressed state otherwise the current state is toggled.
4554 * @param {Boolean} state (optional) Force a particular state
4556 toggle : function(state){
4557 state = state === undefined ? !this.pressed : state;
4558 if(state != this.pressed){
4560 this.el.addClass("x-btn-pressed");
4561 this.pressed = true;
4562 this.fireEvent("toggle", this, true);
4564 this.el.removeClass("x-btn-pressed");
4565 this.pressed = false;
4566 this.fireEvent("toggle", this, false);
4568 if(this.toggleHandler){
4569 this.toggleHandler.call(this.scope || this, this, state);
4578 this.el.child('button:first').focus();
4582 * Disable this button
4584 disable : function(){
4586 this.el.addClass("x-btn-disabled");
4588 this.disabled = true;
4592 * Enable this button
4594 enable : function(){
4596 this.el.removeClass("x-btn-disabled");
4598 this.disabled = false;
4602 * Convenience function for boolean enable/disable
4603 * @param {Boolean} enabled True to enable, false to disable
4605 setDisabled : function(v){
4606 this[v !== true ? "enable" : "disable"]();
4610 onClick : function(e){
4618 if(this.enableToggle){
4621 if(this.menu && !this.menu.isVisible()){
4622 this.menu.show(this.el, this.menuAlign);
4624 this.fireEvent("click", this, e);
4626 this.el.removeClass("x-btn-over");
4627 this.handler.call(this.scope || this, this, e);
4632 onMouseOver : function(e){
4634 this.el.addClass("x-btn-over");
4635 this.fireEvent('mouseover', this, e);
4639 onMouseOut : function(e){
4640 if(!e.within(this.el, true)){
4641 this.el.removeClass("x-btn-over");
4642 this.fireEvent('mouseout', this, e);
4646 onFocus : function(e){
4648 this.el.addClass("x-btn-focus");
4652 onBlur : function(e){
4653 this.el.removeClass("x-btn-focus");
4656 onMouseDown : function(e){
4657 if(!this.disabled && e.button == 0){
4658 this.el.addClass("x-btn-click");
4659 Roo.get(document).on('mouseup', this.onMouseUp, this);
4663 onMouseUp : function(e){
4665 this.el.removeClass("x-btn-click");
4666 Roo.get(document).un('mouseup', this.onMouseUp, this);
4670 onMenuShow : function(e){
4671 this.el.addClass("x-btn-menu-active");
4674 onMenuHide : function(e){
4675 this.el.removeClass("x-btn-menu-active");
4679 // Private utility class used by Button
4680 Roo.ButtonToggleMgr = function(){
4683 function toggleGroup(btn, state){
4685 var g = groups[btn.toggleGroup];
4686 for(var i = 0, l = g.length; i < l; i++){
4695 register : function(btn){
4696 if(!btn.toggleGroup){
4699 var g = groups[btn.toggleGroup];
4701 g = groups[btn.toggleGroup] = [];
4704 btn.on("toggle", toggleGroup);
4707 unregister : function(btn){
4708 if(!btn.toggleGroup){
4711 var g = groups[btn.toggleGroup];
4714 btn.un("toggle", toggleGroup);
4720 * Ext JS Library 1.1.1
4721 * Copyright(c) 2006-2007, Ext JS, LLC.
4723 * Originally Released Under LGPL - original licence link has changed is not relivant.
4726 * <script type="text/javascript">
4730 * @class Roo.SplitButton
4731 * @extends Roo.Button
4732 * A split button that provides a built-in dropdown arrow that can fire an event separately from the default
4733 * click event of the button. Typically this would be used to display a dropdown menu that provides additional
4734 * options to the primary button action, but any custom handler can provide the arrowclick implementation.
4735 * @cfg {Function} arrowHandler A function called when the arrow button is clicked (can be used instead of click event)
4736 * @cfg {String} arrowTooltip The title attribute of the arrow
4738 * Create a new menu button
4739 * @param {String/HTMLElement/Element} renderTo The element to append the button to
4740 * @param {Object} config The config object
4742 Roo.SplitButton = function(renderTo, config){
4743 Roo.SplitButton.superclass.constructor.call(this, renderTo, config);
4746 * Fires when this button's arrow is clicked
4747 * @param {SplitButton} this
4748 * @param {EventObject} e The click event
4750 this.addEvents({"arrowclick":true});
4753 Roo.extend(Roo.SplitButton, Roo.Button, {
4754 render : function(renderTo){
4755 // this is one sweet looking template!
4756 var tpl = new Roo.Template(
4757 '<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>',
4758 '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>',
4759 '<tr><td class="x-btn-left"><i> </i></td><td class="x-btn-center"><button class="x-btn-text" type="{1}">{0}</button></td></tr>',
4760 "</tbody></table></td><td>",
4761 '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>',
4762 '<tr><td class="x-btn-center"><button class="x-btn-menu-arrow-el" type="button"> </button></td><td class="x-btn-right"><i> </i></td></tr>',
4763 "</tbody></table></td></tr></table>"
4765 var btn = tpl.append(renderTo, [this.text, this.type], true);
4766 var btnEl = btn.child("button");
4768 btn.addClass(this.cls);
4771 btnEl.setStyle('background-image', 'url(' +this.icon +')');
4774 btnEl.addClass(this.iconCls);
4776 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
4780 if(this.handleMouseEvents){
4781 btn.on("mouseover", this.onMouseOver, this);
4782 btn.on("mouseout", this.onMouseOut, this);
4783 btn.on("mousedown", this.onMouseDown, this);
4784 btn.on("mouseup", this.onMouseUp, this);
4786 btn.on(this.clickEvent, this.onClick, this);
4788 if(typeof this.tooltip == 'object'){
4789 Roo.QuickTips.tips(Roo.apply({
4793 btnEl.dom[this.tooltipType] = this.tooltip;
4796 if(this.arrowTooltip){
4797 btn.child("button:nth(2)").dom[this.tooltipType] = this.arrowTooltip;
4806 this.el.addClass("x-btn-pressed");
4808 if(Roo.isIE && !Roo.isIE7){
4809 this.autoWidth.defer(1, this);
4814 this.menu.on("show", this.onMenuShow, this);
4815 this.menu.on("hide", this.onMenuHide, this);
4817 this.fireEvent('render', this);
4821 autoWidth : function(){
4823 var tbl = this.el.child("table:first");
4824 var tbl2 = this.el.child("table:last");
4825 this.el.setWidth("auto");
4826 tbl.setWidth("auto");
4827 if(Roo.isIE7 && Roo.isStrict){
4828 var ib = this.el.child('button:first');
4829 if(ib && ib.getWidth() > 20){
4831 ib.setWidth(Roo.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
4836 this.el.beginMeasure();
4838 if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
4839 tbl.setWidth(this.minWidth-tbl2.getWidth());
4842 this.el.endMeasure();
4845 this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
4849 * Sets this button's click handler
4850 * @param {Function} handler The function to call when the button is clicked
4851 * @param {Object} scope (optional) Scope for the function passed above
4853 setHandler : function(handler, scope){
4854 this.handler = handler;
4859 * Sets this button's arrow click handler
4860 * @param {Function} handler The function to call when the arrow is clicked
4861 * @param {Object} scope (optional) Scope for the function passed above
4863 setArrowHandler : function(handler, scope){
4864 this.arrowHandler = handler;
4873 this.el.child("button:first").focus();
4878 onClick : function(e){
4881 if(e.getTarget(".x-btn-menu-arrow-wrap")){
4882 if(this.menu && !this.menu.isVisible()){
4883 this.menu.show(this.el, this.menuAlign);
4885 this.fireEvent("arrowclick", this, e);
4886 if(this.arrowHandler){
4887 this.arrowHandler.call(this.scope || this, this, e);
4890 this.fireEvent("click", this, e);
4892 this.handler.call(this.scope || this, this, e);
4898 onMouseDown : function(e){
4900 Roo.fly(e.getTarget("table")).addClass("x-btn-click");
4904 onMouseUp : function(e){
4905 Roo.fly(e.getTarget("table")).removeClass("x-btn-click");
4911 Roo.MenuButton = Roo.SplitButton;/*
4913 * Ext JS Library 1.1.1
4914 * Copyright(c) 2006-2007, Ext JS, LLC.
4916 * Originally Released Under LGPL - original licence link has changed is not relivant.
4919 * <script type="text/javascript">
4923 * @class Roo.Toolbar
4924 * Basic Toolbar class.
4926 * Creates a new Toolbar
4927 * @param {Object} config The config object
4929 Roo.Toolbar = function(container, buttons, config)
4931 /// old consturctor format still supported..
4932 if(container instanceof Array){ // omit the container for later rendering
4933 buttons = container;
4937 if (typeof(container) == 'object' && container.xtype) {
4939 container = config.container;
4940 buttons = config.buttons; // not really - use items!!
4943 if (config && config.items) {
4944 xitems = config.items;
4945 delete config.items;
4947 Roo.apply(this, config);
4948 this.buttons = buttons;
4951 this.render(container);
4953 Roo.each(xitems, function(b) {
4959 Roo.Toolbar.prototype = {
4961 * @cfg {Roo.data.Store} items
4962 * array of button configs or elements to add
4966 * @cfg {String/HTMLElement/Element} container
4967 * The id or element that will contain the toolbar
4970 render : function(ct){
4971 this.el = Roo.get(ct);
4973 this.el.addClass(this.cls);
4975 // using a table allows for vertical alignment
4976 // 100% width is needed by Safari...
4977 this.el.update('<div class="x-toolbar x-small-editor"><table cellspacing="0"><tr></tr></table></div>');
4978 this.tr = this.el.child("tr", true);
4980 this.items = new Roo.util.MixedCollection(false, function(o){
4981 return o.id || ("item" + (++autoId));
4984 this.add.apply(this, this.buttons);
4985 delete this.buttons;
4990 * Adds element(s) to the toolbar -- this function takes a variable number of
4991 * arguments of mixed type and adds them to the toolbar.
4992 * @param {Mixed} arg1 The following types of arguments are all valid:<br />
4994 * <li>{@link Roo.Toolbar.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
4995 * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
4996 * <li>Field: Any form field (equivalent to {@link #addField})</li>
4997 * <li>Item: Any subclass of {@link Roo.Toolbar.Item} (equivalent to {@link #addItem})</li>
4998 * <li>String: Any generic string (gets wrapped in a {@link Roo.Toolbar.TextItem}, equivalent to {@link #addText}).
4999 * Note that there are a few special strings that are treated differently as explained nRoo.</li>
5000 * <li>'separator' or '-': Creates a separator element (equivalent to {@link #addSeparator})</li>
5001 * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
5002 * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
5004 * @param {Mixed} arg2
5005 * @param {Mixed} etc.
5008 var a = arguments, l = a.length;
5009 for(var i = 0; i < l; i++){
5014 _add : function(el) {
5017 el = Roo.factory(el, typeof(Roo.Toolbar[el.xtype]) == 'undefined' ? Roo.form : Roo.Toolbar);
5020 if (el.applyTo){ // some kind of form field
5021 return this.addField(el);
5023 if (el.render){ // some kind of Toolbar.Item
5024 return this.addItem(el);
5026 if (typeof el == "string"){ // string
5027 if(el == "separator" || el == "-"){
5028 return this.addSeparator();
5031 return this.addSpacer();
5034 return this.addFill();
5036 return this.addText(el);
5039 if(el.tagName){ // element
5040 return this.addElement(el);
5042 if(typeof el == "object"){ // must be button config?
5043 return this.addButton(el);
5051 * Add an Xtype element
5052 * @param {Object} xtype Xtype Object
5053 * @return {Object} created Object
5055 addxtype : function(e){
5060 * Returns the Element for this toolbar.
5061 * @return {Roo.Element}
5069 * @return {Roo.Toolbar.Item} The separator item
5071 addSeparator : function(){
5072 return this.addItem(new Roo.Toolbar.Separator());
5076 * Adds a spacer element
5077 * @return {Roo.Toolbar.Spacer} The spacer item
5079 addSpacer : function(){
5080 return this.addItem(new Roo.Toolbar.Spacer());
5084 * Adds a fill element that forces subsequent additions to the right side of the toolbar
5085 * @return {Roo.Toolbar.Fill} The fill item
5087 addFill : function(){
5088 return this.addItem(new Roo.Toolbar.Fill());
5092 * Adds any standard HTML element to the toolbar
5093 * @param {String/HTMLElement/Element} el The element or id of the element to add
5094 * @return {Roo.Toolbar.Item} The element's item
5096 addElement : function(el){
5097 return this.addItem(new Roo.Toolbar.Item(el));
5100 * Collection of items on the toolbar.. (only Toolbar Items, so use fields to retrieve fields)
5101 * @type Roo.util.MixedCollection
5106 * Adds any Toolbar.Item or subclass
5107 * @param {Roo.Toolbar.Item} item
5108 * @return {Roo.Toolbar.Item} The item
5110 addItem : function(item){
5111 var td = this.nextBlock();
5113 this.items.add(item);
5118 * Adds a button (or buttons). See {@link Roo.Toolbar.Button} for more info on the config.
5119 * @param {Object/Array} config A button config or array of configs
5120 * @return {Roo.Toolbar.Button/Array}
5122 addButton : function(config){
5123 if(config instanceof Array){
5125 for(var i = 0, len = config.length; i < len; i++) {
5126 buttons.push(this.addButton(config[i]));
5131 if(!(config instanceof Roo.Toolbar.Button)){
5133 new Roo.Toolbar.SplitButton(config) :
5134 new Roo.Toolbar.Button(config);
5136 var td = this.nextBlock();
5143 * Adds text to the toolbar
5144 * @param {String} text The text to add
5145 * @return {Roo.Toolbar.Item} The element's item
5147 addText : function(text){
5148 return this.addItem(new Roo.Toolbar.TextItem(text));
5152 * Inserts any {@link Roo.Toolbar.Item}/{@link Roo.Toolbar.Button} at the specified index.
5153 * @param {Number} index The index where the item is to be inserted
5154 * @param {Object/Roo.Toolbar.Item/Roo.Toolbar.Button (may be Array)} item The button, or button config object to be inserted.
5155 * @return {Roo.Toolbar.Button/Item}
5157 insertButton : function(index, item){
5158 if(item instanceof Array){
5160 for(var i = 0, len = item.length; i < len; i++) {
5161 buttons.push(this.insertButton(index + i, item[i]));
5165 if (!(item instanceof Roo.Toolbar.Button)){
5166 item = new Roo.Toolbar.Button(item);
5168 var td = document.createElement("td");
5169 this.tr.insertBefore(td, this.tr.childNodes[index]);
5171 this.items.insert(index, item);
5176 * Adds a new element to the toolbar from the passed {@link Roo.DomHelper} config.
5177 * @param {Object} config
5178 * @return {Roo.Toolbar.Item} The element's item
5180 addDom : function(config, returnEl){
5181 var td = this.nextBlock();
5182 Roo.DomHelper.overwrite(td, config);
5183 var ti = new Roo.Toolbar.Item(td.firstChild);
5190 * Collection of fields on the toolbar.. usefull for quering (value is false if there are no fields)
5191 * @type Roo.util.MixedCollection
5196 * Adds a dynamically rendered Roo.form field (TextField, ComboBox, etc). Note: the field should not have
5197 * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
5198 * @param {Roo.form.Field} field
5199 * @return {Roo.ToolbarItem}
5203 addField : function(field) {
5206 this.fields = new Roo.util.MixedCollection(false, function(o){
5207 return o.id || ("item" + (++autoId));
5212 var td = this.nextBlock();
5214 var ti = new Roo.Toolbar.Item(td.firstChild);
5217 this.fields.add(field);
5228 this.el.child('div').setVisibilityMode(Roo.Element.DISPLAY);
5229 this.el.child('div').hide();
5237 this.el.child('div').show();
5241 nextBlock : function(){
5242 var td = document.createElement("td");
5243 this.tr.appendChild(td);
5248 destroy : function(){
5249 if(this.items){ // rendered?
5250 Roo.destroy.apply(Roo, this.items.items);
5252 if(this.fields){ // rendered?
5253 Roo.destroy.apply(Roo, this.fields.items);
5255 Roo.Element.uncache(this.el, this.tr);
5260 * @class Roo.Toolbar.Item
5261 * The base class that other classes should extend in order to get some basic common toolbar item functionality.
5263 * Creates a new Item
5264 * @param {HTMLElement} el
5266 Roo.Toolbar.Item = function(el){
5267 this.el = Roo.getDom(el);
5268 this.id = Roo.id(this.el);
5269 this.hidden = false;
5272 Roo.Toolbar.Item.prototype = {
5275 * Get this item's HTML Element
5276 * @return {HTMLElement}
5283 render : function(td){
5285 td.appendChild(this.el);
5289 * Removes and destroys this item.
5291 destroy : function(){
5292 this.td.parentNode.removeChild(this.td);
5299 this.hidden = false;
5300 this.td.style.display = "";
5308 this.td.style.display = "none";
5312 * Convenience function for boolean show/hide.
5313 * @param {Boolean} visible true to show/false to hide
5315 setVisible: function(visible){
5324 * Try to focus this item.
5327 Roo.fly(this.el).focus();
5331 * Disables this item.
5333 disable : function(){
5334 Roo.fly(this.td).addClass("x-item-disabled");
5335 this.disabled = true;
5336 this.el.disabled = true;
5340 * Enables this item.
5342 enable : function(){
5343 Roo.fly(this.td).removeClass("x-item-disabled");
5344 this.disabled = false;
5345 this.el.disabled = false;
5351 * @class Roo.Toolbar.Separator
5352 * @extends Roo.Toolbar.Item
5353 * A simple toolbar separator class
5355 * Creates a new Separator
5357 Roo.Toolbar.Separator = function(){
5358 var s = document.createElement("span");
5359 s.className = "ytb-sep";
5360 Roo.Toolbar.Separator.superclass.constructor.call(this, s);
5362 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
5364 disable:Roo.emptyFn,
5369 * @class Roo.Toolbar.Spacer
5370 * @extends Roo.Toolbar.Item
5371 * A simple element that adds extra horizontal space to a toolbar.
5373 * Creates a new Spacer
5375 Roo.Toolbar.Spacer = function(){
5376 var s = document.createElement("div");
5377 s.className = "ytb-spacer";
5378 Roo.Toolbar.Spacer.superclass.constructor.call(this, s);
5380 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
5382 disable:Roo.emptyFn,
5387 * @class Roo.Toolbar.Fill
5388 * @extends Roo.Toolbar.Spacer
5389 * A simple element that adds a greedy (100% width) horizontal space to a toolbar.
5391 * Creates a new Spacer
5393 Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
5395 render : function(td){
5396 td.style.width = '100%';
5397 Roo.Toolbar.Fill.superclass.render.call(this, td);
5402 * @class Roo.Toolbar.TextItem
5403 * @extends Roo.Toolbar.Item
5404 * A simple class that renders text directly into a toolbar.
5406 * Creates a new TextItem
5407 * @param {String} text
5409 Roo.Toolbar.TextItem = function(text){
5410 if (typeof(text) == 'object') {
5413 var s = document.createElement("span");
5414 s.className = "ytb-text";
5416 Roo.Toolbar.TextItem.superclass.constructor.call(this, s);
5418 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
5420 disable:Roo.emptyFn,
5425 * @class Roo.Toolbar.Button
5426 * @extends Roo.Button
5427 * A button that renders into a toolbar.
5429 * Creates a new Button
5430 * @param {Object} config A standard {@link Roo.Button} config object
5432 Roo.Toolbar.Button = function(config){
5433 Roo.Toolbar.Button.superclass.constructor.call(this, null, config);
5435 Roo.extend(Roo.Toolbar.Button, Roo.Button, {
5436 render : function(td){
5438 Roo.Toolbar.Button.superclass.render.call(this, td);
5442 * Removes and destroys this button
5444 destroy : function(){
5445 Roo.Toolbar.Button.superclass.destroy.call(this);
5446 this.td.parentNode.removeChild(this.td);
5453 this.hidden = false;
5454 this.td.style.display = "";
5462 this.td.style.display = "none";
5466 * Disables this item
5468 disable : function(){
5469 Roo.fly(this.td).addClass("x-item-disabled");
5470 this.disabled = true;
5476 enable : function(){
5477 Roo.fly(this.td).removeClass("x-item-disabled");
5478 this.disabled = false;
5482 Roo.ToolbarButton = Roo.Toolbar.Button;
5485 * @class Roo.Toolbar.SplitButton
5486 * @extends Roo.SplitButton
5487 * A menu button that renders into a toolbar.
5489 * Creates a new SplitButton
5490 * @param {Object} config A standard {@link Roo.SplitButton} config object
5492 Roo.Toolbar.SplitButton = function(config){
5493 Roo.Toolbar.SplitButton.superclass.constructor.call(this, null, config);
5495 Roo.extend(Roo.Toolbar.SplitButton, Roo.SplitButton, {
5496 render : function(td){
5498 Roo.Toolbar.SplitButton.superclass.render.call(this, td);
5502 * Removes and destroys this button
5504 destroy : function(){
5505 Roo.Toolbar.SplitButton.superclass.destroy.call(this);
5506 this.td.parentNode.removeChild(this.td);
5513 this.hidden = false;
5514 this.td.style.display = "";
5522 this.td.style.display = "none";
5527 Roo.Toolbar.MenuButton = Roo.Toolbar.SplitButton;/*
5529 * Ext JS Library 1.1.1
5530 * Copyright(c) 2006-2007, Ext JS, LLC.
5532 * Originally Released Under LGPL - original licence link has changed is not relivant.
5535 * <script type="text/javascript">
5539 * @class Roo.PagingToolbar
5540 * @extends Roo.Toolbar
5541 * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
5543 * Create a new PagingToolbar
5544 * @param {Object} config The config object
5546 Roo.PagingToolbar = function(el, ds, config)
5548 // old args format still supported... - xtype is prefered..
5549 if (typeof(el) == 'object' && el.xtype) {
5550 // created from xtype...
5553 el = config.container;
5557 Roo.PagingToolbar.superclass.constructor.call(this, el, null, config);
5560 this.renderButtons(this.el);
5564 Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
5566 * @cfg {Roo.data.Store} dataSource
5567 * The underlying data store providing the paged data
5570 * @cfg {String/HTMLElement/Element} container
5571 * container The id or element that will contain the toolbar
5574 * @cfg {Boolean} displayInfo
5575 * True to display the displayMsg (defaults to false)
5578 * @cfg {Number} pageSize
5579 * The number of records to display per page (defaults to 20)
5583 * @cfg {String} displayMsg
5584 * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
5586 displayMsg : 'Displaying {0} - {1} of {2}',
5588 * @cfg {String} emptyMsg
5589 * The message to display when no records are found (defaults to "No data to display")
5591 emptyMsg : 'No data to display',
5593 * Customizable piece of the default paging text (defaults to "Page")
5596 beforePageText : "Page",
5598 * Customizable piece of the default paging text (defaults to "of %0")
5601 afterPageText : "of {0}",
5603 * Customizable piece of the default paging text (defaults to "First Page")
5606 firstText : "First Page",
5608 * Customizable piece of the default paging text (defaults to "Previous Page")
5611 prevText : "Previous Page",
5613 * Customizable piece of the default paging text (defaults to "Next Page")
5616 nextText : "Next Page",
5618 * Customizable piece of the default paging text (defaults to "Last Page")
5621 lastText : "Last Page",
5623 * Customizable piece of the default paging text (defaults to "Refresh")
5626 refreshText : "Refresh",
5629 renderButtons : function(el){
5630 Roo.PagingToolbar.superclass.render.call(this, el);
5631 this.first = this.addButton({
5632 tooltip: this.firstText,
5633 cls: "x-btn-icon x-grid-page-first",
5635 handler: this.onClick.createDelegate(this, ["first"])
5637 this.prev = this.addButton({
5638 tooltip: this.prevText,
5639 cls: "x-btn-icon x-grid-page-prev",
5641 handler: this.onClick.createDelegate(this, ["prev"])
5643 this.addSeparator();
5644 this.add(this.beforePageText);
5645 this.field = Roo.get(this.addDom({
5650 cls: "x-grid-page-number"
5652 this.field.on("keydown", this.onPagingKeydown, this);
5653 this.field.on("focus", function(){this.dom.select();});
5654 this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
5655 this.field.setHeight(18);
5656 this.addSeparator();
5657 this.next = this.addButton({
5658 tooltip: this.nextText,
5659 cls: "x-btn-icon x-grid-page-next",
5661 handler: this.onClick.createDelegate(this, ["next"])
5663 this.last = this.addButton({
5664 tooltip: this.lastText,
5665 cls: "x-btn-icon x-grid-page-last",
5667 handler: this.onClick.createDelegate(this, ["last"])
5669 this.addSeparator();
5670 this.loading = this.addButton({
5671 tooltip: this.refreshText,
5672 cls: "x-btn-icon x-grid-loading",
5673 handler: this.onClick.createDelegate(this, ["refresh"])
5676 if(this.displayInfo){
5677 this.displayEl = Roo.fly(this.el.dom.firstChild).createChild({cls:'x-paging-info'});
5682 updateInfo : function(){
5684 var count = this.ds.getCount();
5685 var msg = count == 0 ?
5689 this.cursor+1, this.cursor+count, this.ds.getTotalCount()
5691 this.displayEl.update(msg);
5696 onLoad : function(ds, r, o){
5697 this.cursor = o.params ? o.params.start : 0;
5698 var d = this.getPageData(), ap = d.activePage, ps = d.pages;
5700 this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
5701 this.field.dom.value = ap;
5702 this.first.setDisabled(ap == 1);
5703 this.prev.setDisabled(ap == 1);
5704 this.next.setDisabled(ap == ps);
5705 this.last.setDisabled(ap == ps);
5706 this.loading.enable();
5711 getPageData : function(){
5712 var total = this.ds.getTotalCount();
5715 activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
5716 pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
5721 onLoadError : function(){
5722 this.loading.enable();
5726 onPagingKeydown : function(e){
5728 var d = this.getPageData();
5730 var v = this.field.dom.value, pageNum;
5731 if(!v || isNaN(pageNum = parseInt(v, 10))){
5732 this.field.dom.value = d.activePage;
5735 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
5736 this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
5739 else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
5741 var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
5742 this.field.dom.value = pageNum;
5743 this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
5746 else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
5748 var v = this.field.dom.value, pageNum;
5749 var increment = (e.shiftKey) ? 10 : 1;
5750 if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
5752 if(!v || isNaN(pageNum = parseInt(v, 10))) {
5753 this.field.dom.value = d.activePage;
5756 else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
5758 this.field.dom.value = parseInt(v, 10) + increment;
5759 pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
5760 this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
5767 beforeLoad : function(){
5769 this.loading.disable();
5774 onClick : function(which){
5778 ds.load({params:{start: 0, limit: this.pageSize}});
5781 ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
5784 ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
5787 var total = ds.getTotalCount();
5788 var extra = total % this.pageSize;
5789 var lastStart = extra ? (total - extra) : total-this.pageSize;
5790 ds.load({params:{start: lastStart, limit: this.pageSize}});
5793 ds.load({params:{start: this.cursor, limit: this.pageSize}});
5799 * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
5800 * @param {Roo.data.Store} store The data store to unbind
5802 unbind : function(ds){
5803 ds.un("beforeload", this.beforeLoad, this);
5804 ds.un("load", this.onLoad, this);
5805 ds.un("loadexception", this.onLoadError, this);
5806 ds.un("remove", this.updateInfo, this);
5807 ds.un("add", this.updateInfo, this);
5808 this.ds = undefined;
5812 * Binds the paging toolbar to the specified {@link Roo.data.Store}
5813 * @param {Roo.data.Store} store The data store to bind
5815 bind : function(ds){
5816 ds.on("beforeload", this.beforeLoad, this);
5817 ds.on("load", this.onLoad, this);
5818 ds.on("loadexception", this.onLoadError, this);
5819 ds.on("remove", this.updateInfo, this);
5820 ds.on("add", this.updateInfo, this);
5825 * Ext JS Library 1.1.1
5826 * Copyright(c) 2006-2007, Ext JS, LLC.
5828 * Originally Released Under LGPL - original licence link has changed is not relivant.
5831 * <script type="text/javascript">
5835 * @class Roo.Resizable
5836 * @extends Roo.util.Observable
5837 * <p>Applies drag handles to an element to make it resizable. The drag handles are inserted into the element
5838 * and positioned absolute. Some elements, such as a textarea or image, don't support this. To overcome that, you can wrap
5839 * the textarea in a div and set "resizeChild" to true (or to the id of the element), <b>or</b> set wrap:true in your config and
5840 * the element will be wrapped for you automatically.</p>
5841 * <p>Here is the list of valid resize handles:</p>
5844 ------ -------------------
5855 * <p>Here's an example showing the creation of a typical Resizable:</p>
5857 var resizer = new Roo.Resizable("element-id", {
5865 resizer.on("resize", myHandler);
5867 * <p>To hide a particular handle, set its display to none in CSS, or through script:<br>
5868 * resizer.east.setDisplayed(false);</p>
5869 * @cfg {Boolean/String/Element} resizeChild True to resize the first child, or id/element to resize (defaults to false)
5870 * @cfg {Array/String} adjustments String "auto" or an array [width, height] with values to be <b>added</b> to the
5871 * resize operation's new size (defaults to [0, 0])
5872 * @cfg {Number} minWidth The minimum width for the element (defaults to 5)
5873 * @cfg {Number} minHeight The minimum height for the element (defaults to 5)
5874 * @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
5875 * @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
5876 * @cfg {Boolean} enabled False to disable resizing (defaults to true)
5877 * @cfg {Boolean} wrap True to wrap an element with a div if needed (required for textareas and images, defaults to false)
5878 * @cfg {Number} width The width of the element in pixels (defaults to null)
5879 * @cfg {Number} height The height of the element in pixels (defaults to null)
5880 * @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
5881 * @cfg {Number} duration Animation duration if animate = true (defaults to .35)
5882 * @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
5883 * @cfg {String} handles String consisting of the resize handles to display (defaults to undefined)
5884 * @cfg {Boolean} multiDirectional <b>Deprecated</b>. The old style of adding multi-direction resize handles, deprecated
5885 * in favor of the handles config option (defaults to false)
5886 * @cfg {Boolean} disableTrackOver True to disable mouse tracking. This is only applied at config time. (defaults to false)
5887 * @cfg {String} easing Animation easing if animate = true (defaults to 'easingOutStrong')
5888 * @cfg {Number} widthIncrement The increment to snap the width resize in pixels (dynamic must be true, defaults to 0)
5889 * @cfg {Number} heightIncrement The increment to snap the height resize in pixels (dynamic must be true, defaults to 0)
5890 * @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
5891 * user mouses over the resizable borders. This is only applied at config time. (defaults to false)
5892 * @cfg {Boolean} preserveRatio True to preserve the original ratio between height and width during resize (defaults to false)
5893 * @cfg {Boolean} transparent True for transparent handles. This is only applied at config time. (defaults to false)
5894 * @cfg {Number} minX The minimum allowed page X for the element (only used for west resizing, defaults to 0)
5895 * @cfg {Number} minY The minimum allowed page Y for the element (only used for north resizing, defaults to 0)
5896 * @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
5898 * Create a new resizable component
5899 * @param {String/HTMLElement/Roo.Element} el The id or element to resize
5900 * @param {Object} config configuration options
5902 Roo.Resizable = function(el, config){
5903 this.el = Roo.get(el);
5905 if(config && config.wrap){
5906 config.resizeChild = this.el;
5907 this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap : {cls:"xresizable-wrap"});
5908 this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";
5909 this.el.setStyle("overflow", "hidden");
5910 this.el.setPositioning(config.resizeChild.getPositioning());
5911 config.resizeChild.clearPositioning();
5912 if(!config.width || !config.height){
5913 var csize = config.resizeChild.getSize();
5914 this.el.setSize(csize.width, csize.height);
5916 if(config.pinned && !config.adjustments){
5917 config.adjustments = "auto";
5921 this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"});
5922 this.proxy.unselectable();
5923 this.proxy.enableDisplayMode('block');
5925 Roo.apply(this, config);
5928 this.disableTrackOver = true;
5929 this.el.addClass("x-resizable-pinned");
5931 // if the element isn't positioned, make it relative
5932 var position = this.el.getStyle("position");
5933 if(position != "absolute" && position != "fixed"){
5934 this.el.setStyle("position", "relative");
5936 if(!this.handles){ // no handles passed, must be legacy style
5937 this.handles = 's,e,se';
5938 if(this.multiDirectional){
5939 this.handles += ',n,w';
5942 if(this.handles == "all"){
5943 this.handles = "n s e w ne nw se sw";
5945 var hs = this.handles.split(/\s*?[,;]\s*?| /);
5946 var ps = Roo.Resizable.positions;
5947 for(var i = 0, len = hs.length; i < len; i++){
5948 if(hs[i] && ps[hs[i]]){
5949 var pos = ps[hs[i]];
5950 this[pos] = new Roo.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
5954 this.corner = this.southeast;
5956 if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
5957 this.updateBox = true;
5960 this.activeHandle = null;
5962 if(this.resizeChild){
5963 if(typeof this.resizeChild == "boolean"){
5964 this.resizeChild = Roo.get(this.el.dom.firstChild, true);
5966 this.resizeChild = Roo.get(this.resizeChild, true);
5970 if(this.adjustments == "auto"){
5971 var rc = this.resizeChild;
5972 var hw = this.west, he = this.east, hn = this.north, hs = this.south;
5973 if(rc && (hw || hn)){
5974 rc.position("relative");
5975 rc.setLeft(hw ? hw.el.getWidth() : 0);
5976 rc.setTop(hn ? hn.el.getHeight() : 0);
5978 this.adjustments = [
5979 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
5980 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
5985 this.dd = this.dynamic ?
5986 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
5987 this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
5993 * @event beforeresize
5994 * Fired before resize is allowed. Set enabled to false to cancel resize.
5995 * @param {Roo.Resizable} this
5996 * @param {Roo.EventObject} e The mousedown event
5998 "beforeresize" : true,
6001 * Fired after a resize.
6002 * @param {Roo.Resizable} this
6003 * @param {Number} width The new width
6004 * @param {Number} height The new height
6005 * @param {Roo.EventObject} e The mouseup event
6010 if(this.width !== null && this.height !== null){
6011 this.resizeTo(this.width, this.height);
6013 this.updateChildSize();
6016 this.el.dom.style.zoom = 1;
6018 Roo.Resizable.superclass.constructor.call(this);
6021 Roo.extend(Roo.Resizable, Roo.util.Observable, {
6022 resizeChild : false,
6023 adjustments : [0, 0],
6033 multiDirectional : false,
6034 disableTrackOver : false,
6035 easing : 'easeOutStrong',
6037 heightIncrement : 0,
6041 preserveRatio : false,
6048 * @cfg {String/HTMLElement/Element} constrainTo Constrain the resize to a particular element
6050 constrainTo: undefined,
6052 * @cfg {Roo.lib.Region} resizeRegion Constrain the resize to a particular region
6054 resizeRegion: undefined,
6058 * Perform a manual resize
6059 * @param {Number} width
6060 * @param {Number} height
6062 resizeTo : function(width, height){
6063 this.el.setSize(width, height);
6064 this.updateChildSize();
6065 this.fireEvent("resize", this, width, height, null);
6069 startSizing : function(e, handle){
6070 this.fireEvent("beforeresize", this, e);
6071 if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
6074 this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: " "});
6075 this.overlay.unselectable();
6076 this.overlay.enableDisplayMode("block");
6077 this.overlay.on("mousemove", this.onMouseMove, this);
6078 this.overlay.on("mouseup", this.onMouseUp, this);
6080 this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));
6082 this.resizing = true;
6083 this.startBox = this.el.getBox();
6084 this.startPoint = e.getXY();
6085 this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
6086 (this.startBox.y + this.startBox.height) - this.startPoint[1]];
6088 this.overlay.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
6089 this.overlay.show();
6091 if(this.constrainTo) {
6092 var ct = Roo.get(this.constrainTo);
6093 this.resizeRegion = ct.getRegion().adjust(
6094 ct.getFrameWidth('t'),
6095 ct.getFrameWidth('l'),
6096 -ct.getFrameWidth('b'),
6097 -ct.getFrameWidth('r')
6101 this.proxy.setStyle('visibility', 'hidden'); // workaround display none
6103 this.proxy.setBox(this.startBox);
6105 this.proxy.setStyle('visibility', 'visible');
6111 onMouseDown : function(handle, e){
6114 this.activeHandle = handle;
6115 this.startSizing(e, handle);
6120 onMouseUp : function(e){
6121 var size = this.resizeElement();
6122 this.resizing = false;
6124 this.overlay.hide();
6126 this.fireEvent("resize", this, size.width, size.height, e);
6130 updateChildSize : function(){
6131 if(this.resizeChild){
6133 var child = this.resizeChild;
6134 var adj = this.adjustments;
6135 if(el.dom.offsetWidth){
6136 var b = el.getSize(true);
6137 child.setSize(b.width+adj[0], b.height+adj[1]);
6139 // Second call here for IE
6140 // The first call enables instant resizing and
6141 // the second call corrects scroll bars if they
6144 setTimeout(function(){
6145 if(el.dom.offsetWidth){
6146 var b = el.getSize(true);
6147 child.setSize(b.width+adj[0], b.height+adj[1]);
6155 snap : function(value, inc, min){
6156 if(!inc || !value) return value;
6157 var newValue = value;
6158 var m = value % inc;
6161 newValue = value + (inc-m);
6163 newValue = value - m;
6166 return Math.max(min, newValue);
6170 resizeElement : function(){
6171 var box = this.proxy.getBox();
6173 this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
6175 this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
6177 this.updateChildSize();
6185 constrain : function(v, diff, m, mx){
6188 }else if(v - diff > mx){
6195 onMouseMove : function(e){
6197 try{// try catch so if something goes wrong the user doesn't get hung
6199 if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
6203 //var curXY = this.startPoint;
6204 var curSize = this.curSize || this.startBox;
6205 var x = this.startBox.x, y = this.startBox.y;
6207 var w = curSize.width, h = curSize.height;
6209 var mw = this.minWidth, mh = this.minHeight;
6210 var mxw = this.maxWidth, mxh = this.maxHeight;
6211 var wi = this.widthIncrement;
6212 var hi = this.heightIncrement;
6214 var eventXY = e.getXY();
6215 var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
6216 var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
6218 var pos = this.activeHandle.position;
6223 w = Math.min(Math.max(mw, w), mxw);
6227 h = Math.min(Math.max(mh, h), mxh);
6232 w = Math.min(Math.max(mw, w), mxw);
6233 h = Math.min(Math.max(mh, h), mxh);
6236 diffY = this.constrain(h, diffY, mh, mxh);
6241 diffX = this.constrain(w, diffX, mw, mxw);
6247 w = Math.min(Math.max(mw, w), mxw);
6248 diffY = this.constrain(h, diffY, mh, mxh);
6253 diffX = this.constrain(w, diffX, mw, mxw);
6254 diffY = this.constrain(h, diffY, mh, mxh);
6261 diffX = this.constrain(w, diffX, mw, mxw);
6263 h = Math.min(Math.max(mh, h), mxh);
6269 var sw = this.snap(w, wi, mw);
6270 var sh = this.snap(h, hi, mh);
6271 if(sw != w || sh != h){
6294 if(this.preserveRatio){
6299 h = Math.min(Math.max(mh, h), mxh);
6304 w = Math.min(Math.max(mw, w), mxw);
6309 w = Math.min(Math.max(mw, w), mxw);
6315 w = Math.min(Math.max(mw, w), mxw);
6321 h = Math.min(Math.max(mh, h), mxh);
6329 h = Math.min(Math.max(mh, h), mxh);
6339 h = Math.min(Math.max(mh, h), mxh);
6347 this.proxy.setBounds(x, y, w, h);
6349 this.resizeElement();
6356 handleOver : function(){
6358 this.el.addClass("x-resizable-over");
6363 handleOut : function(){
6365 this.el.removeClass("x-resizable-over");
6370 * Returns the element this component is bound to.
6371 * @return {Roo.Element}
6378 * Returns the resizeChild element (or null).
6379 * @return {Roo.Element}
6381 getResizeChild : function(){
6382 return this.resizeChild;
6386 * Destroys this resizable. If the element was wrapped and
6387 * removeEl is not true then the element remains.
6388 * @param {Boolean} removeEl (optional) true to remove the element from the DOM
6390 destroy : function(removeEl){
6391 this.proxy.remove();
6393 this.overlay.removeAllListeners();
6394 this.overlay.remove();
6396 var ps = Roo.Resizable.positions;
6398 if(typeof ps[k] != "function" && this[ps[k]]){
6399 var h = this[ps[k]];
6400 h.el.removeAllListeners();
6412 // hash to map config positions to true positions
6413 Roo.Resizable.positions = {
6414 n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
6418 Roo.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
6420 // only initialize the template if resizable is used
6421 var tpl = Roo.DomHelper.createTemplate(
6422 {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}
6425 Roo.Resizable.Handle.prototype.tpl = tpl;
6427 this.position = pos;
6429 this.el = this.tpl.append(rz.el.dom, [this.position], true);
6430 this.el.unselectable();
6432 this.el.setOpacity(0);
6434 this.el.on("mousedown", this.onMouseDown, this);
6435 if(!disableTrackOver){
6436 this.el.on("mouseover", this.onMouseOver, this);
6437 this.el.on("mouseout", this.onMouseOut, this);
6442 Roo.Resizable.Handle.prototype = {
6443 afterResize : function(rz){
6447 onMouseDown : function(e){
6448 this.rz.onMouseDown(this, e);
6451 onMouseOver : function(e){
6452 this.rz.handleOver(this, e);
6455 onMouseOut : function(e){
6456 this.rz.handleOut(this, e);
6460 * Ext JS Library 1.1.1
6461 * Copyright(c) 2006-2007, Ext JS, LLC.
6463 * Originally Released Under LGPL - original licence link has changed is not relivant.
6466 * <script type="text/javascript">
6471 * @extends Roo.Component
6472 * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
6474 * Create a new Editor
6475 * @param {Roo.form.Field} field The Field object (or descendant)
6476 * @param {Object} config The config object
6478 Roo.Editor = function(field, config){
6479 Roo.Editor.superclass.constructor.call(this, config);
6483 * @event beforestartedit
6484 * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning
6485 * false from the handler of this event.
6486 * @param {Editor} this
6487 * @param {Roo.Element} boundEl The underlying element bound to this editor
6488 * @param {Mixed} value The field value being set
6490 "beforestartedit" : true,
6493 * Fires when this editor is displayed
6494 * @param {Roo.Element} boundEl The underlying element bound to this editor
6495 * @param {Mixed} value The starting field value
6499 * @event beforecomplete
6500 * Fires after a change has been made to the field, but before the change is reflected in the underlying
6501 * field. Saving the change to the field can be canceled by returning false from the handler of this event.
6502 * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
6503 * event will not fire since no edit actually occurred.
6504 * @param {Editor} this
6505 * @param {Mixed} value The current field value
6506 * @param {Mixed} startValue The original field value
6508 "beforecomplete" : true,
6511 * Fires after editing is complete and any changed value has been written to the underlying field.
6512 * @param {Editor} this
6513 * @param {Mixed} value The current field value
6514 * @param {Mixed} startValue The original field value
6519 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
6520 * {@link Roo.EventObject#getKey} to determine which key was pressed.
6521 * @param {Roo.form.Field} this
6522 * @param {Roo.EventObject} e The event object
6528 Roo.extend(Roo.Editor, Roo.Component, {
6530 * @cfg {Boolean/String} autosize
6531 * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
6532 * or "height" to adopt the height only (defaults to false)
6535 * @cfg {Boolean} revertInvalid
6536 * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
6537 * validation fails (defaults to true)
6540 * @cfg {Boolean} ignoreNoChange
6541 * True to skip the the edit completion process (no save, no events fired) if the user completes an edit and
6542 * the value has not changed (defaults to false). Applies only to string values - edits for other data types
6543 * will never be ignored.
6546 * @cfg {Boolean} hideEl
6547 * False to keep the bound element visible while the editor is displayed (defaults to true)
6550 * @cfg {Mixed} value
6551 * The data value of the underlying field (defaults to "")
6555 * @cfg {String} alignment
6556 * The position to align to (see {@link Roo.Element#alignTo} for more details, defaults to "c-c?").
6560 * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
6561 * for bottom-right shadow (defaults to "frame")
6565 * @cfg {Boolean} constrain True to constrain the editor to the viewport
6569 * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
6571 completeOnEnter : false,
6573 * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
6575 cancelOnEsc : false,
6577 * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
6582 onRender : function(ct, position){
6583 this.el = new Roo.Layer({
6584 shadow: this.shadow,
6590 constrain: this.constrain
6592 this.el.setStyle("overflow", Roo.isGecko ? "auto" : "hidden");
6593 if(this.field.msgTarget != 'title'){
6594 this.field.msgTarget = 'qtip';
6596 this.field.render(this.el);
6598 this.field.el.dom.setAttribute('autocomplete', 'off');
6600 this.field.on("specialkey", this.onSpecialKey, this);
6601 if(this.swallowKeys){
6602 this.field.el.swallowEvent(['keydown','keypress']);
6605 this.field.on("blur", this.onBlur, this);
6606 if(this.field.grow){
6607 this.field.on("autosize", this.el.sync, this.el, {delay:1});
6611 onSpecialKey : function(field, e){
6612 if(this.completeOnEnter && e.getKey() == e.ENTER){
6614 this.completeEdit();
6615 }else if(this.cancelOnEsc && e.getKey() == e.ESC){
6618 this.fireEvent('specialkey', field, e);
6623 * Starts the editing process and shows the editor.
6624 * @param {String/HTMLElement/Element} el The element to edit
6625 * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
6626 * to the innerHTML of el.
6628 startEdit : function(el, value){
6630 this.completeEdit();
6632 this.boundEl = Roo.get(el);
6633 var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
6635 this.render(this.parentEl || document.body);
6637 if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
6640 this.startValue = v;
6641 this.field.setValue(v);
6643 var sz = this.boundEl.getSize();
6644 switch(this.autoSize){
6646 this.setSize(sz.width, "");
6649 this.setSize("", sz.height);
6652 this.setSize(sz.width, sz.height);
6655 this.el.alignTo(this.boundEl, this.alignment);
6656 this.editing = true;
6658 Roo.QuickTips.disable();
6664 * Sets the height and width of this editor.
6665 * @param {Number} width The new width
6666 * @param {Number} height The new height
6668 setSize : function(w, h){
6669 this.field.setSize(w, h);
6676 * Realigns the editor to the bound field based on the current alignment config value.
6678 realign : function(){
6679 this.el.alignTo(this.boundEl, this.alignment);
6683 * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
6684 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
6686 completeEdit : function(remainVisible){
6690 var v = this.getValue();
6691 if(this.revertInvalid !== false && !this.field.isValid()){
6692 v = this.startValue;
6693 this.cancelEdit(true);
6695 if(String(v) === String(this.startValue) && this.ignoreNoChange){
6696 this.editing = false;
6700 if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
6701 this.editing = false;
6702 if(this.updateEl && this.boundEl){
6703 this.boundEl.update(v);
6705 if(remainVisible !== true){
6708 this.fireEvent("complete", this, v, this.startValue);
6713 onShow : function(){
6715 if(this.hideEl !== false){
6716 this.boundEl.hide();
6719 if(Roo.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
6720 this.fixIEFocus = true;
6721 this.deferredFocus.defer(50, this);
6725 this.fireEvent("startedit", this.boundEl, this.startValue);
6728 deferredFocus : function(){
6735 * Cancels the editing process and hides the editor without persisting any changes. The field value will be
6736 * reverted to the original starting value.
6737 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
6738 * cancel (defaults to false)
6740 cancelEdit : function(remainVisible){
6742 this.setValue(this.startValue);
6743 if(remainVisible !== true){
6750 onBlur : function(){
6751 if(this.allowBlur !== true && this.editing){
6752 this.completeEdit();
6757 onHide : function(){
6759 this.completeEdit();
6763 if(this.field.collapse){
6764 this.field.collapse();
6767 if(this.hideEl !== false){
6768 this.boundEl.show();
6771 Roo.QuickTips.enable();
6776 * Sets the data value of the editor
6777 * @param {Mixed} value Any valid value supported by the underlying field
6779 setValue : function(v){
6780 this.field.setValue(v);
6784 * Gets the data value of the editor
6785 * @return {Mixed} The data value
6787 getValue : function(){
6788 return this.field.getValue();
6792 * Ext JS Library 1.1.1
6793 * Copyright(c) 2006-2007, Ext JS, LLC.
6795 * Originally Released Under LGPL - original licence link has changed is not relivant.
6798 * <script type="text/javascript">
6802 * @class Roo.BasicDialog
6803 * @extends Roo.util.Observable
6804 * Lightweight Dialog Class. The code below shows the creation of a typical dialog using existing HTML markup:
6806 var dlg = new Roo.BasicDialog("my-dlg", {
6815 dlg.addKeyListener(27, dlg.hide, dlg); // ESC can also close the dialog
6816 dlg.addButton('OK', dlg.hide, dlg); // Could call a save function instead of hiding
6817 dlg.addButton('Cancel', dlg.hide, dlg);
6820 <b>A Dialog should always be a direct child of the body element.</b>
6821 * @cfg {Boolean/DomHelper} autoCreate True to auto create from scratch, or using a DomHelper Object (defaults to false)
6822 * @cfg {String} title Default text to display in the title bar (defaults to null)
6823 * @cfg {Number} width Width of the dialog in pixels (can also be set via CSS). Determined by browser if unspecified.
6824 * @cfg {Number} height Height of the dialog in pixels (can also be set via CSS). Determined by browser if unspecified.
6825 * @cfg {Number} x The default left page coordinate of the dialog (defaults to center screen)
6826 * @cfg {Number} y The default top page coordinate of the dialog (defaults to center screen)
6827 * @cfg {String/Element} animateTarget Id or element from which the dialog should animate while opening
6828 * (defaults to null with no animation)
6829 * @cfg {Boolean} resizable False to disable manual dialog resizing (defaults to true)
6830 * @cfg {String} resizeHandles Which resize handles to display - see the {@link Roo.Resizable} handles config
6831 * property for valid values (defaults to 'all')
6832 * @cfg {Number} minHeight The minimum allowable height for a resizable dialog (defaults to 80)
6833 * @cfg {Number} minWidth The minimum allowable width for a resizable dialog (defaults to 200)
6834 * @cfg {Boolean} modal True to show the dialog modally, preventing user interaction with the rest of the page (defaults to false)
6835 * @cfg {Boolean} autoScroll True to allow the dialog body contents to overflow and display scrollbars (defaults to false)
6836 * @cfg {Boolean} closable False to remove the built-in top-right corner close button (defaults to true)
6837 * @cfg {Boolean} collapsible False to remove the built-in top-right corner collapse button (defaults to true)
6838 * @cfg {Boolean} constraintoviewport True to keep the dialog constrained within the visible viewport boundaries (defaults to true)
6839 * @cfg {Boolean} syncHeightBeforeShow True to cause the dimensions to be recalculated before the dialog is shown (defaults to false)
6840 * @cfg {Boolean} draggable False to disable dragging of the dialog within the viewport (defaults to true)
6841 * @cfg {Boolean} autoTabs If true, all elements with class 'x-dlg-tab' will get automatically converted to tabs (defaults to false)
6842 * @cfg {String} tabTag The tag name of tab elements, used when autoTabs = true (defaults to 'div')
6843 * @cfg {Boolean} proxyDrag True to drag a lightweight proxy element rather than the dialog itself, used when
6844 * draggable = true (defaults to false)
6845 * @cfg {Boolean} fixedcenter True to ensure that anytime the dialog is shown or resized it gets centered (defaults to false)
6846 * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right
6847 * shadow (defaults to false)
6848 * @cfg {Number} shadowOffset The number of pixels to offset the shadow if displayed (defaults to 5)
6849 * @cfg {String} buttonAlign Valid values are "left," "center" and "right" (defaults to "right")
6850 * @cfg {Number} minButtonWidth Minimum width of all dialog buttons (defaults to 75)
6851 * @cfg {Array} buttons Array of buttons
6852 * @cfg {Boolean} shim True to create an iframe shim that prevents selects from showing through (defaults to false)
6854 * Create a new BasicDialog.
6855 * @param {String/HTMLElement/Roo.Element} el The container element or DOM node, or its id
6856 * @param {Object} config Configuration options
6858 Roo.BasicDialog = function(el, config){
6859 this.el = Roo.get(el);
6860 var dh = Roo.DomHelper;
6861 if(!this.el && config && config.autoCreate){
6862 if(typeof config.autoCreate == "object"){
6863 if(!config.autoCreate.id){
6864 config.autoCreate.id = el;
6866 this.el = dh.append(document.body,
6867 config.autoCreate, true);
6869 this.el = dh.append(document.body,
6870 {tag: "div", id: el, style:'visibility:hidden;'}, true);
6874 el.setDisplayed(true);
6875 el.hide = this.hideAction;
6877 el.addClass("x-dlg");
6879 Roo.apply(this, config);
6881 this.proxy = el.createProxy("x-dlg-proxy");
6882 this.proxy.hide = this.hideAction;
6883 this.proxy.setOpacity(.5);
6887 el.setWidth(config.width);
6890 el.setHeight(config.height);
6892 this.size = el.getSize();
6893 if(typeof config.x != "undefined" && typeof config.y != "undefined"){
6894 this.xy = [config.x,config.y];
6896 this.xy = el.getCenterXY(true);
6898 /** The header element @type Roo.Element */
6899 this.header = el.child("> .x-dlg-hd");
6900 /** The body element @type Roo.Element */
6901 this.body = el.child("> .x-dlg-bd");
6902 /** The footer element @type Roo.Element */
6903 this.footer = el.child("> .x-dlg-ft");
6906 this.header = el.createChild({tag: "div", cls:"x-dlg-hd", html: " "}, this.body ? this.body.dom : null);
6909 this.body = el.createChild({tag: "div", cls:"x-dlg-bd"});
6912 this.header.unselectable();
6914 this.header.update(this.title);
6916 // this element allows the dialog to be focused for keyboard event
6917 this.focusEl = el.createChild({tag: "a", href:"#", cls:"x-dlg-focus", tabIndex:"-1"});
6918 this.focusEl.swallowEvent("click", true);
6920 this.header.wrap({cls:"x-dlg-hd-right"}).wrap({cls:"x-dlg-hd-left"}, true);
6922 // wrap the body and footer for special rendering
6923 this.bwrap = this.body.wrap({tag: "div", cls:"x-dlg-dlg-body"});
6925 this.bwrap.dom.appendChild(this.footer.dom);
6928 this.bg = this.el.createChild({
6929 tag: "div", cls:"x-dlg-bg",
6930 html: '<div class="x-dlg-bg-left"><div class="x-dlg-bg-right"><div class="x-dlg-bg-center"> </div></div></div>'
6932 this.centerBg = this.bg.child("div.x-dlg-bg-center");
6935 if(this.autoScroll !== false && !this.autoTabs){
6936 this.body.setStyle("overflow", "auto");
6939 this.toolbox = this.el.createChild({cls: "x-dlg-toolbox"});
6941 if(this.closable !== false){
6942 this.el.addClass("x-dlg-closable");
6943 this.close = this.toolbox.createChild({cls:"x-dlg-close"});
6944 this.close.on("click", this.closeClick, this);
6945 this.close.addClassOnOver("x-dlg-close-over");
6947 if(this.collapsible !== false){
6948 this.collapseBtn = this.toolbox.createChild({cls:"x-dlg-collapse"});
6949 this.collapseBtn.on("click", this.collapseClick, this);
6950 this.collapseBtn.addClassOnOver("x-dlg-collapse-over");
6951 this.header.on("dblclick", this.collapseClick, this);
6953 if(this.resizable !== false){
6954 this.el.addClass("x-dlg-resizable");
6955 this.resizer = new Roo.Resizable(el, {
6956 minWidth: this.minWidth || 80,
6957 minHeight:this.minHeight || 80,
6958 handles: this.resizeHandles || "all",
6961 this.resizer.on("beforeresize", this.beforeResize, this);
6962 this.resizer.on("resize", this.onResize, this);
6964 if(this.draggable !== false){
6965 el.addClass("x-dlg-draggable");
6966 if (!this.proxyDrag) {
6967 var dd = new Roo.dd.DD(el.dom.id, "WindowDrag");
6970 var dd = new Roo.dd.DDProxy(el.dom.id, "WindowDrag", {dragElId: this.proxy.id});
6972 dd.setHandleElId(this.header.id);
6973 dd.endDrag = this.endMove.createDelegate(this);
6974 dd.startDrag = this.startMove.createDelegate(this);
6975 dd.onDrag = this.onDrag.createDelegate(this);
6980 this.mask = dh.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
6981 this.mask.enableDisplayMode("block");
6983 this.el.addClass("x-dlg-modal");
6986 this.shadow = new Roo.Shadow({
6987 mode : typeof this.shadow == "string" ? this.shadow : "sides",
6988 offset : this.shadowOffset
6991 this.shadowOffset = 0;
6993 if(Roo.useShims && this.shim !== false){
6994 this.shim = this.el.createShim();
6995 this.shim.hide = this.hideAction;
7004 var bts= this.buttons;
7006 Roo.each(bts, function(b) {
7015 * Fires when a key is pressed
7016 * @param {Roo.BasicDialog} this
7017 * @param {Roo.EventObject} e
7022 * Fires when this dialog is moved by the user.
7023 * @param {Roo.BasicDialog} this
7024 * @param {Number} x The new page X
7025 * @param {Number} y The new page Y
7030 * Fires when this dialog is resized by the user.
7031 * @param {Roo.BasicDialog} this
7032 * @param {Number} width The new width
7033 * @param {Number} height The new height
7038 * Fires before this dialog is hidden.
7039 * @param {Roo.BasicDialog} this
7041 "beforehide" : true,
7044 * Fires when this dialog is hidden.
7045 * @param {Roo.BasicDialog} this
7050 * Fires before this dialog is shown.
7051 * @param {Roo.BasicDialog} this
7053 "beforeshow" : true,
7056 * Fires when this dialog is shown.
7057 * @param {Roo.BasicDialog} this
7061 el.on("keydown", this.onKeyDown, this);
7062 el.on("mousedown", this.toFront, this);
7063 Roo.EventManager.onWindowResize(this.adjustViewport, this, true);
7065 Roo.DialogManager.register(this);
7066 Roo.BasicDialog.superclass.constructor.call(this);
7069 Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
7070 shadowOffset: Roo.isIE ? 6 : 5,
7074 defaultButton: null,
7075 buttonAlign: "right",
7080 * Sets the dialog title text
7081 * @param {String} text The title text to display
7082 * @return {Roo.BasicDialog} this
7084 setTitle : function(text){
7085 this.header.update(text);
7090 closeClick : function(){
7095 collapseClick : function(){
7096 this[this.collapsed ? "expand" : "collapse"]();
7100 * Collapses the dialog to its minimized state (only the title bar is visible).
7101 * Equivalent to the user clicking the collapse dialog button.
7103 collapse : function(){
7104 if(!this.collapsed){
7105 this.collapsed = true;
7106 this.el.addClass("x-dlg-collapsed");
7107 this.restoreHeight = this.el.getHeight();
7108 this.resizeTo(this.el.getWidth(), this.header.getHeight());
7113 * Expands a collapsed dialog back to its normal state. Equivalent to the user
7114 * clicking the expand dialog button.
7116 expand : function(){
7118 this.collapsed = false;
7119 this.el.removeClass("x-dlg-collapsed");
7120 this.resizeTo(this.el.getWidth(), this.restoreHeight);
7125 * Reinitializes the tabs component, clearing out old tabs and finding new ones.
7126 * @return {Roo.TabPanel} The tabs component
7128 initTabs : function(){
7129 var tabs = this.getTabs();
7130 while(tabs.getTab(0)){
7133 this.el.select(this.tabTag+'.x-dlg-tab').each(function(el){
7135 tabs.addTab(Roo.id(dom), dom.title);
7143 beforeResize : function(){
7144 this.resizer.minHeight = Math.max(this.minHeight, this.getHeaderFooterHeight(true)+40);
7148 onResize : function(){
7150 this.syncBodyHeight();
7151 this.adjustAssets();
7153 this.fireEvent("resize", this, this.size.width, this.size.height);
7157 onKeyDown : function(e){
7158 if(this.isVisible()){
7159 this.fireEvent("keydown", this, e);
7164 * Resizes the dialog.
7165 * @param {Number} width
7166 * @param {Number} height
7167 * @return {Roo.BasicDialog} this
7169 resizeTo : function(width, height){
7170 this.el.setSize(width, height);
7171 this.size = {width: width, height: height};
7172 this.syncBodyHeight();
7173 if(this.fixedcenter){
7176 if(this.isVisible()){
7178 this.adjustAssets();
7180 this.fireEvent("resize", this, width, height);
7186 * Resizes the dialog to fit the specified content size.
7187 * @param {Number} width
7188 * @param {Number} height
7189 * @return {Roo.BasicDialog} this
7191 setContentSize : function(w, h){
7192 h += this.getHeaderFooterHeight() + this.body.getMargins("tb");
7193 w += this.body.getMargins("lr") + this.bwrap.getMargins("lr") + this.centerBg.getPadding("lr");
7194 //if(!this.el.isBorderBox()){
7195 h += this.body.getPadding("tb") + this.bwrap.getBorderWidth("tb") + this.body.getBorderWidth("tb") + this.el.getBorderWidth("tb");
7196 w += this.body.getPadding("lr") + this.bwrap.getBorderWidth("lr") + this.body.getBorderWidth("lr") + this.bwrap.getPadding("lr") + this.el.getBorderWidth("lr");
7199 h += this.tabs.stripWrap.getHeight() + this.tabs.bodyEl.getMargins("tb") + this.tabs.bodyEl.getPadding("tb");
7200 w += this.tabs.bodyEl.getMargins("lr") + this.tabs.bodyEl.getPadding("lr");
7202 this.resizeTo(w, h);
7207 * Adds a key listener for when this dialog is displayed. This allows you to hook in a function that will be
7208 * executed in response to a particular key being pressed while the dialog is active.
7209 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the following options:
7210 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
7211 * @param {Function} fn The function to call
7212 * @param {Object} scope (optional) The scope of the function
7213 * @return {Roo.BasicDialog} this
7215 addKeyListener : function(key, fn, scope){
7216 var keyCode, shift, ctrl, alt;
7217 if(typeof key == "object" && !(key instanceof Array)){
7218 keyCode = key["key"];
7219 shift = key["shift"];
7225 var handler = function(dlg, e){
7226 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
7228 if(keyCode instanceof Array){
7229 for(var i = 0, len = keyCode.length; i < len; i++){
7230 if(keyCode[i] == k){
7231 fn.call(scope || window, dlg, k, e);
7237 fn.call(scope || window, dlg, k, e);
7242 this.on("keydown", handler);
7247 * Returns the TabPanel component (creates it if it doesn't exist).
7248 * Note: If you wish to simply check for the existence of tabs without creating them,
7249 * check for a null 'tabs' property.
7250 * @return {Roo.TabPanel} The tabs component
7252 getTabs : function(){
7254 this.el.addClass("x-dlg-auto-tabs");
7255 this.body.addClass(this.tabPosition == "bottom" ? "x-tabs-bottom" : "x-tabs-top");
7256 this.tabs = new Roo.TabPanel(this.body.dom, this.tabPosition == "bottom");
7262 * Adds a button to the footer section of the dialog.
7263 * @param {String/Object} config A string becomes the button text, an object can either be a Button config
7264 * object or a valid Roo.DomHelper element config
7265 * @param {Function} handler The function called when the button is clicked
7266 * @param {Object} scope (optional) The scope of the handler function (accepts position as a property)
7267 * @return {Roo.Button} The new button
7269 addButton : function(config, handler, scope){
7270 var dh = Roo.DomHelper;
7272 this.footer = dh.append(this.bwrap, {tag: "div", cls:"x-dlg-ft"}, true);
7274 if(!this.btnContainer){
7275 var tb = this.footer.createChild({
7277 cls:"x-dlg-btns x-dlg-btns-"+this.buttonAlign,
7278 html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
7280 this.btnContainer = tb.firstChild.firstChild.firstChild;
7285 minWidth: this.minButtonWidth,
7288 if(typeof config == "string"){
7289 bconfig.text = config;
7292 bconfig.dhconfig = config;
7294 Roo.apply(bconfig, config);
7298 if ((typeof(bconfig.position) != 'undefined') && bconfig.position < this.btnContainer.childNodes.length-1) {
7299 bconfig.position = Math.max(0, bconfig.position);
7300 fc = this.btnContainer.childNodes[bconfig.position];
7303 var btn = new Roo.Button(
7305 this.btnContainer.insertBefore(document.createElement("td"),fc)
7306 : this.btnContainer.appendChild(document.createElement("td")),
7307 //Roo.get(this.btnContainer).createChild( { tag: 'td'}, fc ),
7310 this.syncBodyHeight();
7313 * Array of all the buttons that have been added to this dialog via addButton
7318 this.buttons.push(btn);
7323 * Sets the default button to be focused when the dialog is displayed.
7324 * @param {Roo.BasicDialog.Button} btn The button object returned by {@link #addButton}
7325 * @return {Roo.BasicDialog} this
7327 setDefaultButton : function(btn){
7328 this.defaultButton = btn;
7333 getHeaderFooterHeight : function(safe){
7336 height += this.header.getHeight();
7339 var fm = this.footer.getMargins();
7340 height += (this.footer.getHeight()+fm.top+fm.bottom);
7342 height += this.bwrap.getPadding("tb")+this.bwrap.getBorderWidth("tb");
7343 height += this.centerBg.getPadding("tb");
7348 syncBodyHeight : function(){
7349 var bd = this.body, cb = this.centerBg, bw = this.bwrap;
7350 var height = this.size.height - this.getHeaderFooterHeight(false);
7351 bd.setHeight(height-bd.getMargins("tb"));
7352 var hh = this.header.getHeight();
7353 var h = this.size.height-hh;
7355 bw.setLeftTop(cb.getPadding("l"), hh+cb.getPadding("t"));
7356 bw.setHeight(h-cb.getPadding("tb"));
7357 bw.setWidth(this.el.getWidth(true)-cb.getPadding("lr"));
7358 bd.setWidth(bw.getWidth(true));
7360 this.tabs.syncHeight();
7362 this.tabs.el.repaint();
7368 * Restores the previous state of the dialog if Roo.state is configured.
7369 * @return {Roo.BasicDialog} this
7371 restoreState : function(){
7372 var box = Roo.state.Manager.get(this.stateId || (this.el.id + "-state"));
7373 if(box && box.width){
7374 this.xy = [box.x, box.y];
7375 this.resizeTo(box.width, box.height);
7381 beforeShow : function(){
7383 if(this.fixedcenter){
7384 this.xy = this.el.getCenterXY(true);
7387 Roo.get(document.body).addClass("x-body-masked");
7388 this.mask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
7395 animShow : function(){
7396 var b = Roo.get(this.animateTarget, true).getBox();
7397 this.proxy.setSize(b.width, b.height);
7398 this.proxy.setLocation(b.x, b.y);
7400 this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height,
7401 true, .35, this.showEl.createDelegate(this));
7406 * @param {String/HTMLElement/Roo.Element} animateTarget (optional) Reset the animation target
7407 * @return {Roo.BasicDialog} this
7409 show : function(animateTarget){
7410 if (this.fireEvent("beforeshow", this) === false){
7413 if(this.syncHeightBeforeShow){
7414 this.syncBodyHeight();
7415 }else if(this.firstShow){
7416 this.firstShow = false;
7417 this.syncBodyHeight(); // sync the height on the first show instead of in the constructor
7419 this.animateTarget = animateTarget || this.animateTarget;
7420 if(!this.el.isVisible()){
7422 if(this.animateTarget){
7432 showEl : function(){
7434 this.el.setXY(this.xy);
7436 this.adjustAssets(true);
7439 // IE peekaboo bug - fix found by Dave Fenwick
7443 this.fireEvent("show", this);
7447 * Focuses the dialog. If a defaultButton is set, it will receive focus, otherwise the
7448 * dialog itself will receive focus.
7451 if(this.defaultButton){
7452 this.defaultButton.focus();
7454 this.focusEl.focus();
7459 constrainXY : function(){
7460 if(this.constraintoviewport !== false){
7463 var s = this.container.getSize();
7464 this.viewSize = [s.width, s.height];
7466 this.viewSize = [Roo.lib.Dom.getViewWidth(),Roo.lib.Dom.getViewHeight()];
7469 var s = Roo.get(this.container||document).getScroll();
7471 var x = this.xy[0], y = this.xy[1];
7472 var w = this.size.width, h = this.size.height;
7473 var vw = this.viewSize[0], vh = this.viewSize[1];
7474 // only move it if it needs it
7476 // first validate right/bottom
7477 if(x + w > vw+s.left){
7481 if(y + h > vh+s.top){
7485 // then make sure top/left isn't negative
7497 if(this.isVisible()){
7498 this.el.setLocation(x, y);
7499 this.adjustAssets();
7506 onDrag : function(){
7507 if(!this.proxyDrag){
7508 this.xy = this.el.getXY();
7509 this.adjustAssets();
7514 adjustAssets : function(doShow){
7515 var x = this.xy[0], y = this.xy[1];
7516 var w = this.size.width, h = this.size.height;
7517 if(doShow === true){
7519 this.shadow.show(this.el);
7525 if(this.shadow && this.shadow.isVisible()){
7526 this.shadow.show(this.el);
7528 if(this.shim && this.shim.isVisible()){
7529 this.shim.setBounds(x, y, w, h);
7534 adjustViewport : function(w, h){
7536 w = Roo.lib.Dom.getViewWidth();
7537 h = Roo.lib.Dom.getViewHeight();
7540 this.viewSize = [w, h];
7541 if(this.modal && this.mask.isVisible()){
7542 this.mask.setSize(w, h); // first make sure the mask isn't causing overflow
7543 this.mask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
7545 if(this.isVisible()){
7551 * Destroys this dialog and all its supporting elements (including any tabs, shim,
7552 * shadow, proxy, mask, etc.) Also removes all event listeners.
7553 * @param {Boolean} removeEl (optional) true to remove the element from the DOM
7555 destroy : function(removeEl){
7556 if(this.isVisible()){
7557 this.animateTarget = null;
7560 Roo.EventManager.removeResizeListener(this.adjustViewport, this);
7562 this.tabs.destroy(removeEl);
7575 for(var i = 0, len = this.buttons.length; i < len; i++){
7576 this.buttons[i].destroy();
7579 this.el.removeAllListeners();
7580 if(removeEl === true){
7584 Roo.DialogManager.unregister(this);
7588 startMove : function(){
7592 if(this.constraintoviewport !== false){
7593 this.dd.constrainTo(document.body, {right: this.shadowOffset, bottom: this.shadowOffset});
7598 endMove : function(){
7599 if(!this.proxyDrag){
7600 Roo.dd.DD.prototype.endDrag.apply(this.dd, arguments);
7602 Roo.dd.DDProxy.prototype.endDrag.apply(this.dd, arguments);
7606 this.adjustAssets();
7608 this.fireEvent("move", this, this.xy[0], this.xy[1]);
7612 * Brings this dialog to the front of any other visible dialogs
7613 * @return {Roo.BasicDialog} this
7615 toFront : function(){
7616 Roo.DialogManager.bringToFront(this);
7621 * Sends this dialog to the back (under) of any other visible dialogs
7622 * @return {Roo.BasicDialog} this
7624 toBack : function(){
7625 Roo.DialogManager.sendToBack(this);
7630 * Centers this dialog in the viewport
7631 * @return {Roo.BasicDialog} this
7633 center : function(){
7634 var xy = this.el.getCenterXY(true);
7635 this.moveTo(xy[0], xy[1]);
7640 * Moves the dialog's top-left corner to the specified point
7643 * @return {Roo.BasicDialog} this
7645 moveTo : function(x, y){
7647 if(this.isVisible()){
7648 this.el.setXY(this.xy);
7649 this.adjustAssets();
7655 * Aligns the dialog to the specified element
7656 * @param {String/HTMLElement/Roo.Element} element The element to align to.
7657 * @param {String} position The position to align to (see {@link Roo.Element#alignTo} for more details).
7658 * @param {Array} offsets (optional) Offset the positioning by [x, y]
7659 * @return {Roo.BasicDialog} this
7661 alignTo : function(element, position, offsets){
7662 this.xy = this.el.getAlignToXY(element, position, offsets);
7663 if(this.isVisible()){
7664 this.el.setXY(this.xy);
7665 this.adjustAssets();
7671 * Anchors an element to another element and realigns it when the window is resized.
7672 * @param {String/HTMLElement/Roo.Element} element The element to align to.
7673 * @param {String} position The position to align to (see {@link Roo.Element#alignTo} for more details)
7674 * @param {Array} offsets (optional) Offset the positioning by [x, y]
7675 * @param {Boolean/Number} monitorScroll (optional) true to monitor body scroll and reposition. If this parameter
7676 * is a number, it is used as the buffer delay (defaults to 50ms).
7677 * @return {Roo.BasicDialog} this
7679 anchorTo : function(el, alignment, offsets, monitorScroll){
7680 var action = function(){
7681 this.alignTo(el, alignment, offsets);
7683 Roo.EventManager.onWindowResize(action, this);
7684 var tm = typeof monitorScroll;
7685 if(tm != 'undefined'){
7686 Roo.EventManager.on(window, 'scroll', action, this,
7687 {buffer: tm == 'number' ? monitorScroll : 50});
7694 * Returns true if the dialog is visible
7697 isVisible : function(){
7698 return this.el.isVisible();
7702 animHide : function(callback){
7703 var b = Roo.get(this.animateTarget).getBox();
7705 this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height);
7707 this.proxy.setBounds(b.x, b.y, b.width, b.height, true, .35,
7708 this.hideEl.createDelegate(this, [callback]));
7713 * @param {Function} callback (optional) Function to call when the dialog is hidden
7714 * @return {Roo.BasicDialog} this
7716 hide : function(callback){
7717 if (this.fireEvent("beforehide", this) === false){
7726 if(this.animateTarget){
7727 this.animHide(callback);
7730 this.hideEl(callback);
7736 hideEl : function(callback){
7740 Roo.get(document.body).removeClass("x-body-masked");
7742 this.fireEvent("hide", this);
7743 if(typeof callback == "function"){
7749 hideAction : function(){
7750 this.setLeft("-10000px");
7751 this.setTop("-10000px");
7752 this.setStyle("visibility", "hidden");
7756 refreshSize : function(){
7757 this.size = this.el.getSize();
7758 this.xy = this.el.getXY();
7759 Roo.state.Manager.set(this.stateId || this.el.id + "-state", this.el.getBox());
7763 // z-index is managed by the DialogManager and may be overwritten at any time
7764 setZIndex : function(index){
7766 this.mask.setStyle("z-index", index);
7769 this.shim.setStyle("z-index", ++index);
7772 this.shadow.setZIndex(++index);
7774 this.el.setStyle("z-index", ++index);
7776 this.proxy.setStyle("z-index", ++index);
7779 this.resizer.proxy.setStyle("z-index", ++index);
7782 this.lastZIndex = index;
7786 * Returns the element for this dialog
7787 * @return {Roo.Element} The underlying dialog Element
7795 * @class Roo.DialogManager
7796 * Provides global access to BasicDialogs that have been created and
7797 * support for z-indexing (layering) multiple open dialogs.
7799 Roo.DialogManager = function(){
7801 var accessList = [];
7805 var sortDialogs = function(d1, d2){
7806 return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
7810 var orderDialogs = function(){
7811 accessList.sort(sortDialogs);
7812 var seed = Roo.DialogManager.zseed;
7813 for(var i = 0, len = accessList.length; i < len; i++){
7814 var dlg = accessList[i];
7816 dlg.setZIndex(seed + (i*10));
7823 * The starting z-index for BasicDialogs (defaults to 9000)
7824 * @type Number The z-index value
7829 register : function(dlg){
7831 accessList.push(dlg);
7835 unregister : function(dlg){
7836 delete list[dlg.id];
7839 if(!accessList.indexOf){
7840 for( i = 0, len = accessList.length; i < len; i++){
7841 if(accessList[i] == dlg){
7842 accessList.splice(i, 1);
7847 i = accessList.indexOf(dlg);
7849 accessList.splice(i, 1);
7855 * Gets a registered dialog by id
7856 * @param {String/Object} id The id of the dialog or a dialog
7857 * @return {Roo.BasicDialog} this
7860 return typeof id == "object" ? id : list[id];
7864 * Brings the specified dialog to the front
7865 * @param {String/Object} dlg The id of the dialog or a dialog
7866 * @return {Roo.BasicDialog} this
7868 bringToFront : function(dlg){
7869 dlg = this.get(dlg);
7872 dlg._lastAccess = new Date().getTime();
7879 * Sends the specified dialog to the back
7880 * @param {String/Object} dlg The id of the dialog or a dialog
7881 * @return {Roo.BasicDialog} this
7883 sendToBack : function(dlg){
7884 dlg = this.get(dlg);
7885 dlg._lastAccess = -(new Date().getTime());
7893 hideAll : function(){
7894 for(var id in list){
7895 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
7904 * @class Roo.LayoutDialog
7905 * @extends Roo.BasicDialog
7906 * Dialog which provides adjustments for working with a layout in a Dialog.
7907 * Add your necessary layout config options to the dialog's config.<br>
7908 * Example usage (including a nested layout):
7911 dialog = new Roo.LayoutDialog("download-dlg", {
7920 // layout config merges with the dialog config
7923 alwaysShowTabs: true
7926 dialog.addKeyListener(27, dialog.hide, dialog);
7927 dialog.setDefaultButton(dialog.addButton("Close", dialog.hide, dialog));
7928 dialog.addButton("Build It!", this.getDownload, this);
7930 // we can even add nested layouts
7931 var innerLayout = new Roo.BorderLayout("dl-inner", {
7941 innerLayout.beginUpdate();
7942 innerLayout.add("east", new Roo.ContentPanel("dl-details"));
7943 innerLayout.add("center", new Roo.ContentPanel("selection-panel"));
7944 innerLayout.endUpdate(true);
7946 var layout = dialog.getLayout();
7947 layout.beginUpdate();
7948 layout.add("center", new Roo.ContentPanel("standard-panel",
7949 {title: "Download the Source", fitToFrame:true}));
7950 layout.add("center", new Roo.NestedLayoutPanel(innerLayout,
7951 {title: "Build your own roo.js"}));
7952 layout.getRegion("center").showPanel(sp);
7957 * @param {String/HTMLElement/Roo.Element} el The id of or container element, or config
7958 * @param {Object} config configuration options
7960 Roo.LayoutDialog = function(el, cfg){
7963 if (typeof(cfg) == 'undefined') {
7964 config = Roo.apply({}, el);
7965 el = Roo.get( document.documentElement || document.body).createChild();
7966 //config.autoCreate = true;
7970 config.autoTabs = false;
7971 Roo.LayoutDialog.superclass.constructor.call(this, el, config);
7972 this.body.setStyle({overflow:"hidden", position:"relative"});
7973 this.layout = new Roo.BorderLayout(this.body.dom, config);
7974 this.layout.monitorWindowResize = false;
7975 this.el.addClass("x-dlg-auto-layout");
7976 // fix case when center region overwrites center function
7977 this.center = Roo.BasicDialog.prototype.center;
7978 this.on("show", this.layout.layout, this.layout, true);
7980 var xitems = config.items;
7981 delete config.items;
7982 Roo.each(xitems, this.addxtype, this);
7987 Roo.extend(Roo.LayoutDialog, Roo.BasicDialog, {
7989 * Ends update of the layout <strike>and resets display to none</strike>. Use standard beginUpdate/endUpdate on the layout.
7992 endUpdate : function(){
7993 this.layout.endUpdate();
7997 * Begins an update of the layout <strike>and sets display to block and visibility to hidden</strike>. Use standard beginUpdate/endUpdate on the layout.
8000 beginUpdate : function(){
8001 this.layout.beginUpdate();
8005 * Get the BorderLayout for this dialog
8006 * @return {Roo.BorderLayout}
8008 getLayout : function(){
8012 showEl : function(){
8013 Roo.LayoutDialog.superclass.showEl.apply(this, arguments);
8015 this.layout.layout();
8020 // Use the syncHeightBeforeShow config option to control this automatically
8021 syncBodyHeight : function(){
8022 Roo.LayoutDialog.superclass.syncBodyHeight.call(this);
8023 if(this.layout){this.layout.layout();}
8027 * Add an xtype element (actually adds to the layout.)
8028 * @return {Object} xdata xtype object data.
8031 addxtype : function(c) {
8032 return this.layout.addxtype(c);
8036 * Ext JS Library 1.1.1
8037 * Copyright(c) 2006-2007, Ext JS, LLC.
8039 * Originally Released Under LGPL - original licence link has changed is not relivant.
8042 * <script type="text/javascript">
8046 * @class Roo.MessageBox
8047 * Utility class for generating different styles of message boxes. The alias Roo.Msg can also be used.
8051 Roo.Msg.alert('Status', 'Changes saved successfully.');
8053 // Prompt for user data:
8054 Roo.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
8056 // process text value...
8060 // Show a dialog using config options:
8062 title:'Save Changes?',
8063 msg: 'Your are closing a tab that has unsaved changes. Would you like to save your changes?',
8064 buttons: Roo.Msg.YESNOCANCEL,
8071 Roo.MessageBox = function(){
8072 var dlg, opt, mask, waitTimer;
8073 var bodyEl, msgEl, textboxEl, textareaEl, progressEl, pp;
8074 var buttons, activeTextEl, bwidth;
8077 var handleButton = function(button){
8079 Roo.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value], 1);
8083 var handleHide = function(){
8085 dlg.el.removeClass(opt.cls);
8088 Roo.TaskMgr.stop(waitTimer);
8094 var updateButtons = function(b){
8097 buttons["ok"].hide();
8098 buttons["cancel"].hide();
8099 buttons["yes"].hide();
8100 buttons["no"].hide();
8101 dlg.footer.dom.style.display = 'none';
8104 dlg.footer.dom.style.display = '';
8105 for(var k in buttons){
8106 if(typeof buttons[k] != "function"){
8109 buttons[k].setText(typeof b[k] == "string" ? b[k] : Roo.MessageBox.buttonText[k]);
8110 width += buttons[k].el.getWidth()+15;
8120 var handleEsc = function(d, k, e){
8121 if(opt && opt.closable !== false){
8131 * Returns a reference to the underlying {@link Roo.BasicDialog} element
8132 * @return {Roo.BasicDialog} The BasicDialog element
8134 getDialog : function(){
8136 dlg = new Roo.BasicDialog("x-msg-box", {
8141 constraintoviewport:false,
8143 collapsible : false,
8146 width:400, height:100,
8147 buttonAlign:"center",
8148 closeClick : function(){
8149 if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
8152 handleButton("cancel");
8156 dlg.on("hide", handleHide);
8158 dlg.addKeyListener(27, handleEsc);
8160 var bt = this.buttonText;
8161 buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
8162 buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
8163 buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
8164 buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
8165 bodyEl = dlg.body.createChild({
8167 html:'<span class="roo-mb-text"></span><br /><input type="text" class="roo-mb-input" /><textarea class="roo-mb-textarea"></textarea><div class="roo-mb-progress-wrap"><div class="roo-mb-progress"><div class="roo-mb-progress-bar"> </div></div></div>'
8169 msgEl = bodyEl.dom.firstChild;
8170 textboxEl = Roo.get(bodyEl.dom.childNodes[2]);
8171 textboxEl.enableDisplayMode();
8172 textboxEl.addKeyListener([10,13], function(){
8173 if(dlg.isVisible() && opt && opt.buttons){
8176 }else if(opt.buttons.yes){
8177 handleButton("yes");
8181 textareaEl = Roo.get(bodyEl.dom.childNodes[3]);
8182 textareaEl.enableDisplayMode();
8183 progressEl = Roo.get(bodyEl.dom.childNodes[4]);
8184 progressEl.enableDisplayMode();
8185 var pf = progressEl.dom.firstChild;
8187 pp = Roo.get(pf.firstChild);
8188 pp.setHeight(pf.offsetHeight);
8196 * Updates the message box body text
8197 * @param {String} text (optional) Replaces the message box element's innerHTML with the specified string (defaults to
8198 * the XHTML-compliant non-breaking space character '&#160;')
8199 * @return {Roo.MessageBox} This message box
8201 updateText : function(text){
8202 if(!dlg.isVisible() && !opt.width){
8203 dlg.resizeTo(this.maxWidth, 100); // resize first so content is never clipped from previous shows
8205 msgEl.innerHTML = text || ' ';
8206 var w = Math.max(Math.min(opt.width || msgEl.offsetWidth, this.maxWidth),
8207 Math.max(opt.minWidth || this.minWidth, bwidth));
8209 activeTextEl.setWidth(w);
8211 if(dlg.isVisible()){
8212 dlg.fixedcenter = false;
8214 dlg.setContentSize(w, bodyEl.getHeight());
8215 if(dlg.isVisible()){
8216 dlg.fixedcenter = true;
8222 * Updates a progress-style message box's text and progress bar. Only relevant on message boxes
8223 * initiated via {@link Roo.MessageBox#progress} or by calling {@link Roo.MessageBox#show} with progress: true.
8224 * @param {Number} value Any number between 0 and 1 (e.g., .5)
8225 * @param {String} text (optional) If defined, the message box's body text is replaced with the specified string (defaults to undefined)
8226 * @return {Roo.MessageBox} This message box
8228 updateProgress : function(value, text){
8230 this.updateText(text);
8232 if (pp) { // weird bug on my firefox - for some reason this is not defined
8233 pp.setWidth(Math.floor(value*progressEl.dom.firstChild.offsetWidth));
8239 * Returns true if the message box is currently displayed
8240 * @return {Boolean} True if the message box is visible, else false
8242 isVisible : function(){
8243 return dlg && dlg.isVisible();
8247 * Hides the message box if it is displayed
8250 if(this.isVisible()){
8256 * Displays a new message box, or reinitializes an existing message box, based on the config options
8257 * passed in. All functions (e.g. prompt, alert, etc) on MessageBox call this function internally.
8258 * The following config object properties are supported:
8260 Property Type Description
8261 ---------- --------------- ------------------------------------------------------------------------------------
8262 animEl String/Element An id or Element from which the message box should animate as it opens and
8263 closes (defaults to undefined)
8264 buttons Object/Boolean A button config object (e.g., Roo.MessageBox.OKCANCEL or {ok:'Foo',
8265 cancel:'Bar'}), or false to not show any buttons (defaults to false)
8266 closable Boolean False to hide the top-right close button (defaults to true). Note that
8267 progress and wait dialogs will ignore this property and always hide the
8268 close button as they can only be closed programmatically.
8269 cls String A custom CSS class to apply to the message box element
8270 defaultTextHeight Number The default height in pixels of the message box's multiline textarea if
8271 displayed (defaults to 75)
8272 fn Function A callback function to execute after closing the dialog. The arguments to the
8273 function will be btn (the name of the button that was clicked, if applicable,
8274 e.g. "ok"), and text (the value of the active text field, if applicable).
8275 Progress and wait dialogs will ignore this option since they do not respond to
8276 user actions and can only be closed programmatically, so any required function
8277 should be called by the same code after it closes the dialog.
8278 icon String A CSS class that provides a background image to be used as an icon for
8279 the dialog (e.g., Roo.MessageBox.WARNING or 'custom-class', defaults to '')
8280 maxWidth Number The maximum width in pixels of the message box (defaults to 600)
8281 minWidth Number The minimum width in pixels of the message box (defaults to 100)
8282 modal Boolean False to allow user interaction with the page while the message box is
8283 displayed (defaults to true)
8284 msg String A string that will replace the existing message box body text (defaults
8285 to the XHTML-compliant non-breaking space character ' ')
8286 multiline Boolean True to prompt the user to enter multi-line text (defaults to false)
8287 progress Boolean True to display a progress bar (defaults to false)
8288 progressText String The text to display inside the progress bar if progress = true (defaults to '')
8289 prompt Boolean True to prompt the user to enter single-line text (defaults to false)
8290 proxyDrag Boolean True to display a lightweight proxy while dragging (defaults to false)
8291 title String The title text
8292 value String The string value to set into the active textbox element if displayed
8293 wait Boolean True to display a progress bar (defaults to false)
8294 width Number The width of the dialog in pixels
8301 msg: 'Please enter your address:',
8303 buttons: Roo.MessageBox.OKCANCEL,
8306 animEl: 'addAddressBtn'
8309 * @param {Object} config Configuration options
8310 * @return {Roo.MessageBox} This message box
8312 show : function(options){
8313 if(this.isVisible()){
8316 var d = this.getDialog();
8318 d.setTitle(opt.title || " ");
8319 d.close.setDisplayed(opt.closable !== false);
8320 activeTextEl = textboxEl;
8321 opt.prompt = opt.prompt || (opt.multiline ? true : false);
8326 textareaEl.setHeight(typeof opt.multiline == "number" ?
8327 opt.multiline : this.defaultTextHeight);
8328 activeTextEl = textareaEl;
8337 progressEl.setDisplayed(opt.progress === true);
8338 this.updateProgress(0);
8339 activeTextEl.dom.value = opt.value || "";
8341 dlg.setDefaultButton(activeTextEl);
8343 var bs = opt.buttons;
8347 }else if(bs && bs.yes){
8348 db = buttons["yes"];
8350 dlg.setDefaultButton(db);
8352 bwidth = updateButtons(opt.buttons);
8353 this.updateText(opt.msg);
8355 d.el.addClass(opt.cls);
8357 d.proxyDrag = opt.proxyDrag === true;
8358 d.modal = opt.modal !== false;
8359 d.mask = opt.modal !== false ? mask : false;
8361 // force it to the end of the z-index stack so it gets a cursor in FF
8362 document.body.appendChild(dlg.el.dom);
8363 d.animateTarget = null;
8364 d.show(options.animEl);
8370 * Displays a message box with a progress bar. This message box has no buttons and is not closeable by
8371 * the user. You are responsible for updating the progress bar as needed via {@link Roo.MessageBox#updateProgress}
8372 * and closing the message box when the process is complete.
8373 * @param {String} title The title bar text
8374 * @param {String} msg The message box body text
8375 * @return {Roo.MessageBox} This message box
8377 progress : function(title, msg){
8384 minWidth: this.minProgressWidth,
8391 * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript Window.alert).
8392 * If a callback function is passed it will be called after the user clicks the button, and the
8393 * id of the button that was clicked will be passed as the only parameter to the callback
8394 * (could also be the top-right close button).
8395 * @param {String} title The title bar text
8396 * @param {String} msg The message box body text
8397 * @param {Function} fn (optional) The callback function invoked after the message box is closed
8398 * @param {Object} scope (optional) The scope of the callback function
8399 * @return {Roo.MessageBox} This message box
8401 alert : function(title, msg, fn, scope){
8414 * Displays a message box with an infinitely auto-updating progress bar. This can be used to block user
8415 * interaction while waiting for a long-running process to complete that does not have defined intervals.
8416 * You are responsible for closing the message box when the process is complete.
8417 * @param {String} msg The message box body text
8418 * @param {String} title (optional) The title bar text
8419 * @return {Roo.MessageBox} This message box
8421 wait : function(msg, title){
8432 waitTimer = Roo.TaskMgr.start({
8434 Roo.MessageBox.updateProgress(((((i+20)%20)+1)*5)*.01);
8442 * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's Window.confirm).
8443 * If a callback function is passed it will be called after the user clicks either button, and the id of the
8444 * button that was clicked will be passed as the only parameter to the callback (could also be the top-right close button).
8445 * @param {String} title The title bar text
8446 * @param {String} msg The message box body text
8447 * @param {Function} fn (optional) The callback function invoked after the message box is closed
8448 * @param {Object} scope (optional) The scope of the callback function
8449 * @return {Roo.MessageBox} This message box
8451 confirm : function(title, msg, fn, scope){
8455 buttons: this.YESNO,
8464 * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to
8465 * JavaScript's Window.prompt). The prompt can be a single-line or multi-line textbox. If a callback function
8466 * is passed it will be called after the user clicks either button, and the id of the button that was clicked
8467 * (could also be the top-right close button) and the text that was entered will be passed as the two
8468 * parameters to the callback.
8469 * @param {String} title The title bar text
8470 * @param {String} msg The message box body text
8471 * @param {Function} fn (optional) The callback function invoked after the message box is closed
8472 * @param {Object} scope (optional) The scope of the callback function
8473 * @param {Boolean/Number} multiline (optional) True to create a multiline textbox using the defaultTextHeight
8474 * property, or the height in pixels to create the textbox (defaults to false / single-line)
8475 * @return {Roo.MessageBox} This message box
8477 prompt : function(title, msg, fn, scope, multiline){
8481 buttons: this.OKCANCEL,
8486 multiline: multiline,
8493 * Button config that displays a single OK button
8498 * Button config that displays Yes and No buttons
8501 YESNO : {yes:true, no:true},
8503 * Button config that displays OK and Cancel buttons
8506 OKCANCEL : {ok:true, cancel:true},
8508 * Button config that displays Yes, No and Cancel buttons
8511 YESNOCANCEL : {yes:true, no:true, cancel:true},
8514 * The default height in pixels of the message box's multiline textarea if displayed (defaults to 75)
8517 defaultTextHeight : 75,
8519 * The maximum width in pixels of the message box (defaults to 600)
8524 * The minimum width in pixels of the message box (defaults to 100)
8529 * The minimum width in pixels of the message box if it is a progress-style dialog. This is useful
8530 * for setting a different minimum width than text-only dialogs may need (defaults to 250)
8533 minProgressWidth : 250,
8535 * An object containing the default button text strings that can be overriden for localized language support.
8536 * Supported properties are: ok, cancel, yes and no.
8537 * Customize the default text like so: Roo.MessageBox.buttonText.yes = "S?";
8550 * Shorthand for {@link Roo.MessageBox}
8552 Roo.Msg = Roo.MessageBox;/*
8554 * Ext JS Library 1.1.1
8555 * Copyright(c) 2006-2007, Ext JS, LLC.
8557 * Originally Released Under LGPL - original licence link has changed is not relivant.
8560 * <script type="text/javascript">
8563 * @class Roo.QuickTips
8564 * Provides attractive and customizable tooltips for any element.
8567 Roo.QuickTips = function(){
8568 var el, tipBody, tipBodyText, tipTitle, tm, cfg, close, tagEls = {}, esc, removeCls = null, bdLeft, bdRight;
8570 var visible = false, disabled = true, inited = false;
8571 var showProc = 1, hideProc = 1, dismissProc = 1, locks = [];
8573 var onOver = function(e){
8577 var t = e.getTarget();
8578 if(!t || t.nodeType !== 1 || t == document || t == document.body){
8581 if(ce && t == ce.el){
8582 clearTimeout(hideProc);
8585 if(t && tagEls[t.id]){
8586 tagEls[t.id].el = t;
8587 showProc = show.defer(tm.showDelay, tm, [tagEls[t.id]]);
8590 var ttp, et = Roo.fly(t);
8591 var ns = cfg.namespace;
8592 if(tm.interceptTitles && t.title){
8595 t.removeAttribute("title");
8598 ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);
8601 showProc = show.defer(tm.showDelay, tm, [{
8604 width: et.getAttributeNS(ns, cfg.width),
8605 autoHide: et.getAttributeNS(ns, cfg.hide) != "user",
8606 title: et.getAttributeNS(ns, cfg.title),
8607 cls: et.getAttributeNS(ns, cfg.cls)
8612 var onOut = function(e){
8613 clearTimeout(showProc);
8614 var t = e.getTarget();
8615 if(t && ce && ce.el == t && (tm.autoHide && ce.autoHide !== false)){
8616 hideProc = setTimeout(hide, tm.hideDelay);
8620 var onMove = function(e){
8626 if(tm.trackMouse && ce){
8631 var onDown = function(e){
8632 clearTimeout(showProc);
8633 clearTimeout(hideProc);
8638 tm.enable.defer(100, tm);
8643 var getPad = function(){
8644 return 2;//bdLeft.getPadding('l')+bdRight.getPadding('r');
8647 var show = function(o){
8651 clearTimeout(dismissProc);
8653 if(removeCls){ // in case manually hidden
8654 el.removeClass(removeCls);
8658 el.addClass(ce.cls);
8662 tipTitle.update(ce.title);
8665 tipTitle.update('');
8668 el.dom.style.width = tm.maxWidth+'px';
8669 //tipBody.dom.style.width = '';
8670 tipBodyText.update(o.text);
8671 var p = getPad(), w = ce.width;
8673 var td = tipBodyText.dom;
8674 var aw = Math.max(td.offsetWidth, td.clientWidth, td.scrollWidth);
8675 if(aw > tm.maxWidth){
8677 }else if(aw < tm.minWidth){
8683 //tipBody.setWidth(w);
8684 el.setWidth(parseInt(w, 10) + p);
8685 if(ce.autoHide === false){
8686 close.setDisplayed(true);
8691 close.setDisplayed(false);
8697 el.avoidY = xy[1]-18;
8702 el.setStyle("visibility", "visible");
8703 el.fadeIn({callback: afterShow});
8709 var afterShow = function(){
8713 if(tm.autoDismiss && ce.autoHide !== false){
8714 dismissProc = setTimeout(hide, tm.autoDismissDelay);
8719 var hide = function(noanim){
8720 clearTimeout(dismissProc);
8721 clearTimeout(hideProc);
8725 if(noanim !== true && tm.animate){
8726 el.fadeOut({callback: afterHide});
8733 var afterHide = function(){
8736 el.removeClass(removeCls);
8743 * @cfg {Number} minWidth
8744 * The minimum width of the quick tip (defaults to 40)
8748 * @cfg {Number} maxWidth
8749 * The maximum width of the quick tip (defaults to 300)
8753 * @cfg {Boolean} interceptTitles
8754 * True to automatically use the element's DOM title value if available (defaults to false)
8756 interceptTitles : false,
8758 * @cfg {Boolean} trackMouse
8759 * True to have the quick tip follow the mouse as it moves over the target element (defaults to false)
8763 * @cfg {Boolean} hideOnClick
8764 * True to hide the quick tip if the user clicks anywhere in the document (defaults to true)
8768 * @cfg {Number} showDelay
8769 * Delay in milliseconds before the quick tip displays after the mouse enters the target element (defaults to 500)
8773 * @cfg {Number} hideDelay
8774 * Delay in milliseconds before the quick tip hides when autoHide = true (defaults to 200)
8778 * @cfg {Boolean} autoHide
8779 * True to automatically hide the quick tip after the mouse exits the target element (defaults to true).
8780 * Used in conjunction with hideDelay.
8785 * True to automatically hide the quick tip after a set period of time, regardless of the user's actions
8786 * (defaults to true). Used in conjunction with autoDismissDelay.
8791 * Delay in milliseconds before the quick tip hides when autoDismiss = true (defaults to 5000)
8793 autoDismissDelay : 5000,
8795 * @cfg {Boolean} animate
8796 * True to turn on fade animation. Defaults to false (ClearType/scrollbar flicker issues in IE7).
8801 * @cfg {String} title
8802 * Title text to display (defaults to ''). This can be any valid HTML markup.
8806 * @cfg {String} text
8807 * Body text to display (defaults to ''). This can be any valid HTML markup.
8812 * A CSS class to apply to the base quick tip element (defaults to '').
8816 * @cfg {Number} width
8817 * Width in pixels of the quick tip (defaults to auto). Width will be ignored if it exceeds the bounds of
8818 * minWidth or maxWidth.
8823 * Initialize and enable QuickTips for first use. This should be called once before the first attempt to access
8824 * or display QuickTips in a page.
8830 if(!Roo.isReady){ // allow calling of init() before onReady
8831 Roo.onReady(Roo.QuickTips.init, Roo.QuickTips);
8834 el = new Roo.Layer({cls:"x-tip", shadow:"drop", shim: true, constrain:true, shadowOffset:4});
8835 el.fxDefaults = {stopFx: true};
8836 // maximum custom styling
8837 //el.update('<div class="x-tip-top-left"><div class="x-tip-top-right"><div class="x-tip-top"></div></div></div><div class="x-tip-bd-left"><div class="x-tip-bd-right"><div class="x-tip-bd"><div class="x-tip-close"></div><h3></h3><div class="x-tip-bd-inner"></div><div class="x-clear"></div></div></div></div><div class="x-tip-ft-left"><div class="x-tip-ft-right"><div class="x-tip-ft"></div></div></div>');
8838 el.update('<div class="x-tip-bd"><div class="x-tip-close"></div><h3></h3><div class="x-tip-bd-inner"></div><div class="x-clear"></div></div>');
8839 tipTitle = el.child('h3');
8840 tipTitle.enableDisplayMode("block");
8841 tipBody = el.child('div.x-tip-bd');
8842 tipBodyText = el.child('div.x-tip-bd-inner');
8843 //bdLeft = el.child('div.x-tip-bd-left');
8844 //bdRight = el.child('div.x-tip-bd-right');
8845 close = el.child('div.x-tip-close');
8846 close.enableDisplayMode("block");
8847 close.on("click", hide);
8848 var d = Roo.get(document);
8849 d.on("mousedown", onDown);
8850 d.on("mouseover", onOver);
8851 d.on("mouseout", onOut);
8852 d.on("mousemove", onMove);
8853 esc = d.addKeyListener(27, hide);
8856 dd = el.initDD("default", null, {
8857 onDrag : function(){
8861 dd.setHandleElId(tipTitle.id);
8870 * Configures a new quick tip instance and assigns it to a target element. The following config options
8873 Property Type Description
8874 ---------- --------------------- ------------------------------------------------------------------------
8875 target Element/String/Array An Element, id or array of ids that this quick tip should be tied to
8877 * @param {Object} config The config object
8879 register : function(config){
8880 var cs = config instanceof Array ? config : arguments;
8881 for(var i = 0, len = cs.length; i < len; i++) {
8883 var target = c.target;
8885 if(target instanceof Array){
8886 for(var j = 0, jlen = target.length; j < jlen; j++){
8887 tagEls[target[j]] = c;
8890 tagEls[typeof target == 'string' ? target : Roo.id(target)] = c;
8897 * Removes this quick tip from its element and destroys it.
8898 * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
8900 unregister : function(el){
8901 delete tagEls[Roo.id(el)];
8905 * Enable this quick tip.
8907 enable : function(){
8908 if(inited && disabled){
8910 if(locks.length < 1){
8917 * Disable this quick tip.
8919 disable : function(){
8921 clearTimeout(showProc);
8922 clearTimeout(hideProc);
8923 clearTimeout(dismissProc);
8931 * Returns true if the quick tip is enabled, else false.
8933 isEnabled : function(){
8951 Roo.QuickTips.tips = Roo.QuickTips.register;