((this.secure == true) ? "; secure" : "");
}
});/*
- * Original code for Roojs - LGPL
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
* <script type="text/javascript">
*/
+
/**
- * @class Roo.XComponent
- * A delayed Element creator...
- * Or a way to group chunks of interface together.
- *
- * Mypart.xyx = new Roo.XComponent({
+ * @class Roo.ComponentMgr
+ * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
+ * @singleton
+ */
+Roo.ComponentMgr = function(){
+ var all = new Roo.util.MixedCollection();
- parent : 'Mypart.xyz', // empty == document.element.!!
- order : '001',
- name : 'xxxx'
- region : 'xxxx'
- disabled : function() {}
-
- tree : function() { // return an tree of xtype declared components
- var MODULE = this;
- return
- {
- xtype : 'NestedLayoutPanel',
- // technicall
+ return {
+ /**
+ * Registers a component.
+ * @param {Roo.Component} c The component
+ */
+ register : function(c){
+ all.add(c);
+ },
+
+ /**
+ * Unregisters a component.
+ * @param {Roo.Component} c The component
+ */
+ unregister : function(c){
+ all.remove(c);
+ },
+
+ /**
+ * Returns a component by id
+ * @param {String} id The component id
+ */
+ get : function(id){
+ return all.get(id);
+ },
+
+ /**
+ * Registers a function that will be called when a specified component is added to ComponentMgr
+ * @param {String} id The component id
+ * @param {Funtction} fn The callback function
+ * @param {Object} scope The scope of the callback
+ */
+ onAvailable : function(id, fn, scope){
+ all.on("add", function(index, o){
+ if(o.id == id){
+ fn.call(scope || o, o);
+ all.un("add", fn, scope);
+ }
+ });
}
- ]
- *})
+ };
+}();/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
*
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
*
- * It can be used to build a big heiracy, with parent etc.
- * or you can just use this to render a single compoent to a dom element
- * MYPART.render(Roo.Element | String(id) | dom_element )
- *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Roo.Component
* @extends Roo.util.Observable
+ * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
+ * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
+ * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
+ * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
+ * All visual components (widgets) that require rendering into a layout should subclass Component.
* @constructor
- * @param cfg {Object} configuration of component
- *
+ * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
+ * 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
+ * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
*/
-Roo.XComponent = function(cfg) {
- Roo.apply(this, cfg);
- this.addEvents({
+Roo.Component = function(config){
+ config = config || {};
+ if(config.tagName || config.dom || typeof config == "string"){ // element object
+ config = {el: config, id: config.id || config};
+ }
+ this.initialConfig = config;
+
+ Roo.apply(this, config);
+ this.addEvents({
/**
- * @event built
- * Fires when this the componnt is built
- * @param {Roo.XComponent} c the component
+ * @event disable
+ * Fires after the component is disabled.
+ * @param {Roo.Component} this
*/
- 'built' : true
-
+ disable : true,
+ /**
+ * @event enable
+ * Fires after the component is enabled.
+ * @param {Roo.Component} this
+ */
+ enable : true,
+ /**
+ * @event beforeshow
+ * Fires before the component is shown. Return false to stop the show.
+ * @param {Roo.Component} this
+ */
+ beforeshow : true,
+ /**
+ * @event show
+ * Fires after the component is shown.
+ * @param {Roo.Component} this
+ */
+ show : true,
+ /**
+ * @event beforehide
+ * Fires before the component is hidden. Return false to stop the hide.
+ * @param {Roo.Component} this
+ */
+ beforehide : true,
+ /**
+ * @event hide
+ * Fires after the component is hidden.
+ * @param {Roo.Component} this
+ */
+ hide : true,
+ /**
+ * @event beforerender
+ * Fires before the component is rendered. Return false to stop the render.
+ * @param {Roo.Component} this
+ */
+ beforerender : true,
+ /**
+ * @event render
+ * Fires after the component is rendered.
+ * @param {Roo.Component} this
+ */
+ render : true,
+ /**
+ * @event beforedestroy
+ * Fires before the component is destroyed. Return false to stop the destroy.
+ * @param {Roo.Component} this
+ */
+ beforedestroy : true,
+ /**
+ * @event destroy
+ * Fires after the component is destroyed.
+ * @param {Roo.Component} this
+ */
+ destroy : true
});
- this.region = this.region || 'center'; // default..
- Roo.XComponent.register(this);
- this.modules = false;
- this.el = false; // where the layout goes..
-
-
-}
-Roo.extend(Roo.XComponent, Roo.util.Observable, {
- /**
- * @property el
- * The created element (with Roo.factory())
- * @type {Roo.Layout}
- */
- el : false,
-
+ if(!this.id){
+ this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
+ }
+ Roo.ComponentMgr.register(this);
+ Roo.Component.superclass.constructor.call(this);
+ this.initComponent();
+ if(this.renderTo){ // not supported by all components yet. use at your own risk!
+ this.render(this.renderTo);
+ delete this.renderTo;
+ }
+};
+
+/** @private */
+Roo.Component.AUTO_ID = 1000;
+
+Roo.extend(Roo.Component, Roo.util.Observable, {
/**
- * @property el
- * for BC - use el in new code
- * @type {Roo.Layout}
+ * @scope Roo.Component.prototype
+ * @type {Boolean}
+ * true if this component is hidden. Read-only.
*/
- panel : false,
-
+ hidden : false,
/**
- * @property layout
- * for BC - use el in new code
- * @type {Roo.Layout}
- */
- layout : false,
-
- /**
- * @cfg {Function|boolean} disabled
- * If this module is disabled by some rule, return true from the funtion
+ * @type {Boolean}
+ * true if this component is disabled. Read-only.
*/
disabled : false,
-
/**
- * @cfg {String} parent
- * Name of parent element which it get xtype added to..
+ * @type {Boolean}
+ * true if this component has been rendered. Read-only.
*/
- parent: false,
+ rendered : false,
- /**
- * @cfg {String} order
- * Used to set the order in which elements are created (usefull for multiple tabs)
+ /** @cfg {String} disableClass
+ * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
*/
-
- order : false,
- /**
- * @cfg {String} name
- * String to display while loading.
+ disabledClass : "x-item-disabled",
+ /** @cfg {Boolean} allowDomMove
+ * Whether the component can move the Dom node when rendering (defaults to true).
+ */
+ allowDomMove : true,
+ /** @cfg {String} hideMode
+ * How this component should hidden. Supported values are
+ * "visibility" (css visibility), "offsets" (negative offset position) and
+ * "display" (css display) - defaults to "display".
*/
- name : false,
+ hideMode: 'display',
+
+ /** @private */
+ ctype : "Roo.Component",
+
/**
- * @cfg {String} region
- * Region to render component to (defaults to center)
- */
- region : 'center',
-
- /**
- * @cfg {Array} items
- * A single item array - the first element is the root of the tree..
- * It's done this way to stay compatible with the Xtype system...
+ * @cfg {String} actionMode
+ * which property holds the element that used for hide() / show() / disable() / enable()
+ * default is 'el'
*/
- items : false,
-
+ actionMode : "el",
+
+ /** @private */
+ getActionEl : function(){
+ return this[this.actionMode];
+ },
+
+ initComponent : Roo.emptyFn,
/**
- * @property _tree
- * The method that retuns the tree of parts that make up this compoennt
- * @type {function}
- */
- _tree : false,
-
- /**
- * render
- * render element to dom or tree
- * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
+ * If this is a lazy rendering component, render it to its container element.
+ * @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.
*/
-
- render : function(el)
- {
-
- el = el || false;
- var hp = this.parent ? 1 : 0;
-
- if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
- // if parent is a '#.....' string, then let's use that..
- var ename = this.parent.substr(1)
- this.parent = (this.parent == '#bootstrap') ? { el : true} : false; // flags it as a top module...
- el = Roo.get(ename);
- if (!el && !this.parent) {
- Roo.log("Warning - element can not be found :#" + ename );
- return;
+ render : function(container, position){
+ if(!this.rendered && this.fireEvent("beforerender", this) !== false){
+ if(!container && this.el){
+ this.el = Roo.get(this.el);
+ container = this.el.dom.parentNode;
+ this.allowDomMove = false;
+ }
+ this.container = Roo.get(container);
+ this.rendered = true;
+ if(position !== undefined){
+ if(typeof position == 'number'){
+ position = this.container.dom.childNodes[position];
+ }else{
+ position = Roo.getDom(position);
+ }
+ }
+ this.onRender(this.container, position || null);
+ if(this.cls){
+ this.el.addClass(this.cls);
+ delete this.cls;
+ }
+ if(this.style){
+ this.el.applyStyles(this.style);
+ delete this.style;
+ }
+ this.fireEvent("render", this);
+ this.afterRender(this.container);
+ if(this.hidden){
+ this.hide();
+ }
+ if(this.disabled){
+ this.disable();
}
}
-
-
- if (!this.parent) {
-
- el = el ? Roo.get(el) : false;
-
- // it's a top level one..
- this.parent = {
- el : new Roo.BorderLayout(el || document.body, {
-
- center: {
- titlebar: false,
- autoScroll:false,
- closeOnTab: true,
- tabPosition: 'top',
- //resizeTabs: true,
- alwaysShowTabs: el && hp? false : true,
- hideTabs: el || !hp ? true : false,
- minTabWidth: 140
- }
- })
+ return this;
+ },
+
+ /** @private */
+ // default function is not really useful
+ onRender : function(ct, position){
+ if(this.el){
+ this.el = Roo.get(this.el);
+ if(this.allowDomMove !== false){
+ ct.dom.insertBefore(this.el.dom, position);
}
}
-
- if (!this.parent.el) {
- // probably an old style ctor, which has been disabled.
- return;
-
- }
- // The 'tree' method is '_tree now'
-
- var tree = this._tree ? this._tree() : this.tree();
- tree.region = tree.region || this.region;
- this.el = this.parent.el.addxtype(tree);
- this.fireEvent('built', this);
-
- this.panel = this.el;
- this.layout = this.panel.layout;
- this.parentLayout = this.parent.layout || false;
-
- }
-
-});
+ },
+
+ /** @private */
+ getAutoCreate : function(){
+ var cfg = typeof this.autoCreate == "object" ?
+ this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
+ if(this.id && !cfg.id){
+ cfg.id = this.id;
+ }
+ return cfg;
+ },
+
+ /** @private */
+ afterRender : Roo.emptyFn,
-Roo.apply(Roo.XComponent, {
/**
- * @property hideProgress
- * true to disable the building progress bar.. usefull on single page renders.
- * @type Boolean
+ * Destroys this component by purging any event listeners, removing the component's element from the DOM,
+ * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
*/
- hideProgress : false,
+ destroy : function(){
+ if(this.fireEvent("beforedestroy", this) !== false){
+ this.purgeListeners();
+ this.beforeDestroy();
+ if(this.rendered){
+ this.el.removeAllListeners();
+ this.el.remove();
+ if(this.actionMode == "container"){
+ this.container.remove();
+ }
+ }
+ this.onDestroy();
+ Roo.ComponentMgr.unregister(this);
+ this.fireEvent("destroy", this);
+ }
+ },
+
+ /** @private */
+ beforeDestroy : function(){
+
+ },
+
+ /** @private */
+ onDestroy : function(){
+
+ },
+
/**
- * @property buildCompleted
- * True when the builder has completed building the interface.
- * @type Boolean
+ * Returns the underlying {@link Roo.Element}.
+ * @return {Roo.Element} The element
*/
- buildCompleted : false,
-
+ getEl : function(){
+ return this.el;
+ },
+
/**
- * @property topModule
- * the upper most module - uses document.element as it's constructor.
- * @type Object
+ * Returns the id of this component.
+ * @return {String}
*/
-
- topModule : false,
-
+ getId : function(){
+ return this.id;
+ },
+
/**
- * @property modules
- * array of modules to be created by registration system.
- * @type {Array} of Roo.XComponent
+ * Try to focus this component.
+ * @param {Boolean} selectText True to also select the text in this component (if applicable)
+ * @return {Roo.Component} this
*/
-
- modules : [],
+ focus : function(selectText){
+ if(this.rendered){
+ this.el.focus();
+ if(selectText === true){
+ this.el.dom.select();
+ }
+ }
+ return this;
+ },
+
+ /** @private */
+ blur : function(){
+ if(this.rendered){
+ this.el.blur();
+ }
+ return this;
+ },
+
/**
- * @property elmodules
- * array of modules to be created by which use #ID
- * @type {Array} of Roo.XComponent
+ * Disable this component.
+ * @return {Roo.Component} this
*/
-
- elmodules : [],
+ disable : function(){
+ if(this.rendered){
+ this.onDisable();
+ }
+ this.disabled = true;
+ this.fireEvent("disable", this);
+ return this;
+ },
+
+ // private
+ onDisable : function(){
+ this.getActionEl().addClass(this.disabledClass);
+ this.el.dom.disabled = true;
+ },
-
/**
- * Register components to be built later.
- *
- * This solves the following issues
- * - Building is not done on page load, but after an authentication process has occured.
- * - Interface elements are registered on page load
- * - Parent Interface elements may not be loaded before child, so this handles that..
- *
- *
- * example:
- *
- * MyApp.register({
- order : '000001',
- module : 'Pman.Tab.projectMgr',
- region : 'center',
- parent : 'Pman.layout',
- disabled : false, // or use a function..
- })
-
- * * @param {Object} details about module
+ * Enable this component.
+ * @return {Roo.Component} this
*/
- register : function(obj) {
-
- Roo.XComponent.event.fireEvent('register', obj);
- switch(typeof(obj.disabled) ) {
-
- case 'undefined':
- break;
-
- case 'function':
- if ( obj.disabled() ) {
- return;
- }
- break;
-
- default:
- if (obj.disabled) {
- return;
- }
- break;
+ enable : function(){
+ if(this.rendered){
+ this.onEnable();
}
-
- this.modules.push(obj);
-
+ this.disabled = false;
+ this.fireEvent("enable", this);
+ return this;
+ },
+
+ // private
+ onEnable : function(){
+ this.getActionEl().removeClass(this.disabledClass);
+ this.el.dom.disabled = false;
},
+
/**
- * convert a string to an object..
- * eg. 'AAA.BBB' -> finds AAA.BBB
+ * Convenience function for setting disabled/enabled by boolean.
+ * @param {Boolean} disabled
+ */
+ setDisabled : function(disabled){
+ this[disabled ? "disable" : "enable"]();
+ },
+ /**
+ * Show this component.
+ * @return {Roo.Component} this
*/
-
- toObject : function(str)
- {
- if (!str || typeof(str) == 'object') {
- return str;
- }
- if (str.substring(0,1) == '#') {
- return str;
+ show: function(){
+ if(this.fireEvent("beforeshow", this) !== false){
+ this.hidden = false;
+ if(this.rendered){
+ this.onShow();
+ }
+ this.fireEvent("show", this);
}
+ return this;
+ },
- var ar = str.split('.');
- var rt, o;
- rt = ar.shift();
- /** eval:var:o */
- try {
- eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
- } catch (e) {
- throw "Module not found : " + str;
- }
-
- if (o === false) {
- throw "Module not found : " + str;
+ // private
+ onShow : function(){
+ var ae = this.getActionEl();
+ if(this.hideMode == 'visibility'){
+ ae.dom.style.visibility = "visible";
+ }else if(this.hideMode == 'offsets'){
+ ae.removeClass('x-hidden');
+ }else{
+ ae.dom.style.display = "";
}
- Roo.each(ar, function(e) {
- if (typeof(o[e]) == 'undefined') {
- throw "Module not found : " + str;
- }
- o = o[e];
- });
-
- return o;
-
},
-
-
+
/**
- * move modules into their correct place in the tree..
- *
+ * Hide this component.
+ * @return {Roo.Component} this
*/
- preBuild : function ()
- {
- var _t = this;
- Roo.each(this.modules , function (obj)
- {
- Roo.XComponent.event.fireEvent('beforebuild', obj);
-
- var opar = obj.parent;
- try {
- obj.parent = this.toObject(opar);
- } catch(e) {
- Roo.log("parent:toObject failed: " + e.toString());
- return;
- }
-
- if (!obj.parent) {
- Roo.debug && Roo.log("GOT top level module");
- Roo.debug && Roo.log(obj);
- obj.modules = new Roo.util.MixedCollection(false,
- function(o) { return o.order + '' }
- );
- this.topModule = obj;
- return;
- }
- // parent is a string (usually a dom element name..)
- if (typeof(obj.parent) == 'string') {
- this.elmodules.push(obj);
- return;
- }
- if (obj.parent.constructor != Roo.XComponent) {
- Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
- }
- if (!obj.parent.modules) {
- obj.parent.modules = new Roo.util.MixedCollection(false,
- function(o) { return o.order + '' }
- );
- }
- if (obj.parent.disabled) {
- obj.disabled = true;
+ hide: function(){
+ if(this.fireEvent("beforehide", this) !== false){
+ this.hidden = true;
+ if(this.rendered){
+ this.onHide();
}
- obj.parent.modules.add(obj);
- }, this);
+ this.fireEvent("hide", this);
+ }
+ return this;
},
-
- /**
- * make a list of modules to build.
- * @return {Array} list of modules.
- */
-
- buildOrder : function()
- {
- var _this = this;
- var cmp = function(a,b) {
- return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
- };
- if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
- throw "No top level modules to build";
+
+ // private
+ onHide : function(){
+ var ae = this.getActionEl();
+ if(this.hideMode == 'visibility'){
+ ae.dom.style.visibility = "hidden";
+ }else if(this.hideMode == 'offsets'){
+ ae.addClass('x-hidden');
+ }else{
+ ae.dom.style.display = "none";
}
-
- // make a flat list in order of modules to build.
- var mods = this.topModule ? [ this.topModule ] : [];
-
-
- // elmodules (is a list of DOM based modules )
- Roo.each(this.elmodules, function(e) {
- mods.push(e);
- if (!this.topModule &&
- typeof(e.parent) == 'string' &&
- e.parent.substring(0,1) == '#' &&
- Roo.get(e.parent.substr(1))
- ) {
-
- _this.topModule = e;
- }
-
- });
+ },
-
- // add modules to their parents..
- var addMod = function(m) {
- Roo.debug && Roo.log("build Order: add: " + m.name);
-
- mods.push(m);
- if (m.modules && !m.disabled) {
- Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
- m.modules.keySort('ASC', cmp );
- Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
-
- m.modules.each(addMod);
- } else {
- Roo.debug && Roo.log("build Order: no child modules");
- }
- // not sure if this is used any more..
- if (m.finalize) {
- m.finalize.name = m.name + " (clean up) ";
- mods.push(m.finalize);
- }
-
+ /**
+ * Convenience function to hide or show this component by boolean.
+ * @param {Boolean} visible True to show, false to hide
+ * @return {Roo.Component} this
+ */
+ setVisible: function(visible){
+ if(visible) {
+ this.show();
+ }else{
+ this.hide();
}
- if (this.topModule && this.topModule.modules) {
- this.topModule.modules.keySort('ASC', cmp );
- this.topModule.modules.each(addMod);
- }
- return mods;
+ return this;
},
-
- /**
- * Build the registered modules.
- * @param {Object} parent element.
- * @param {Function} optional method to call after module has been added.
- *
- */
-
- build : function()
- {
-
- this.preBuild();
- var mods = this.buildOrder();
-
- //this.allmods = mods;
- //Roo.debug && Roo.log(mods);
- //return;
- if (!mods.length) { // should not happen
- throw "NO modules!!!";
- }
-
-
- var msg = "Building Interface...";
- // flash it up as modal - so we store the mask!?
- if (!this.hideProgress) {
- Roo.MessageBox.show({ title: 'loading' });
- Roo.MessageBox.show({
- title: "Please wait...",
- msg: msg,
- width:450,
- progress:true,
- closable:false,
- modal: false
-
- });
- }
- var total = mods.length;
-
- var _this = this;
- var progressRun = function() {
- if (!mods.length) {
- Roo.debug && Roo.log('hide?');
- if (!this.hideProgress) {
- Roo.MessageBox.hide();
- }
- Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
-
- // THE END...
- return false;
- }
-
- var m = mods.shift();
-
-
- Roo.debug && Roo.log(m);
- // not sure if this is supported any more.. - modules that are are just function
- if (typeof(m) == 'function') {
- m.call(this);
- return progressRun.defer(10, _this);
- }
-
-
- msg = "Building Interface " + (total - mods.length) +
- " of " + total +
- (m.name ? (' - ' + m.name) : '');
- Roo.debug && Roo.log(msg);
- if (!this.hideProgress) {
- Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
- }
-
-
- // is the module disabled?
- var disabled = (typeof(m.disabled) == 'function') ?
- m.disabled.call(m.module.disabled) : m.disabled;
-
-
- if (disabled) {
- return progressRun(); // we do not update the display!
- }
-
- // now build
-
-
-
- m.render();
- // it's 10 on top level, and 1 on others??? why...
- return progressRun.defer(10, _this);
-
- }
- progressRun.defer(1, _this);
-
-
-
- },
-
-
- /**
- * Event Object.
- *
- *
- */
- event: false,
- /**
- * wrapper for event.on - aliased later..
- * Typically use to register a event handler for register:
- *
- * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
- *
- */
- on : false
-
-
-
-});
-Roo.XComponent.event = new Roo.util.Observable({
- events : {
- /**
- * @event register
- * Fires when an Component is registered,
- * set the disable property on the Component to stop registration.
- * @param {Roo.XComponent} c the component being registerd.
- *
- */
- 'register' : true,
- /**
- * @event beforebuild
- * Fires before each Component is built
- * can be used to apply permissions.
- * @param {Roo.XComponent} c the component being registerd.
- *
- */
- 'beforebuild' : true,
- /**
- * @event buildcomplete
- * Fires on the top level element when all elements have been built
- * @param {Roo.XComponent} the top level component.
- */
- 'buildcomplete' : true
-
- }
-});
+ /**
+ * Returns true if this component is visible.
+ */
+ isVisible : function(){
+ return this.getActionEl().isVisible();
+ },
-Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
- /*
+ cloneConfig : function(overrides){
+ overrides = overrides || {};
+ var id = overrides.id || Roo.id();
+ var cfg = Roo.applyIf(overrides, this.initialConfig);
+ cfg.id = id; // prevent dup id
+ return new this.constructor(cfg);
+ }
+});/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
* <script type="text/javascript">
*/
-
-
-/*
- * These classes are derivatives of the similarly named classes in the YUI Library.
- * The original license:
- * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
- * Code licensed under the BSD License:
- * http://developer.yahoo.net/yui/license.txt
- */
-
-(function() {
-
-var Event=Roo.EventManager;
-var Dom=Roo.lib.Dom;
-
/**
- * @class Roo.dd.DragDrop
- * @extends Roo.util.Observable
- * Defines the interface and base operation of items that that can be
- * dragged or can be drop targets. It was designed to be extended, overriding
- * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
- * Up to three html elements can be associated with a DragDrop instance:
- * <ul>
- * <li>linked element: the element that is passed into the constructor.
- * This is the element which defines the boundaries for interaction with
- * other DragDrop objects.</li>
- * <li>handle element(s): The drag operation only occurs if the element that
- * was clicked matches a handle element. By default this is the linked
- * element, but there are times that you will want only a portion of the
- * linked element to initiate the drag operation, and the setHandleElId()
- * method provides a way to define this.</li>
- * <li>drag element: this represents the element that would be moved along
- * with the cursor during a drag operation. By default, this is the linked
- * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
- * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
- * </li>
- * </ul>
- * This class should not be instantiated until the onload event to ensure that
- * the associated elements are available.
- * The following would define a DragDrop obj that would interact with any
- * other DragDrop obj in the "group1" group:
- * <pre>
- * dd = new Roo.dd.DragDrop("div1", "group1");
- * </pre>
- * Since none of the event handlers have been implemented, nothing would
- * actually happen if you were to run the code above. Normally you would
- * override this class or one of the default implementations, but you can
- * also override the methods you want on an instance of the class...
- * <pre>
- * dd.onDragDrop = function(e, id) {
- * alert("dd was dropped on " + id);
- * }
- * </pre>
+ * @class Roo.BoxComponent
+ * @extends Roo.Component
+ * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
+ * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
+ * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
+ * layout containers.
* @constructor
- * @param {String} id of the element that is linked to this instance
- * @param {String} sGroup the group of related DragDrop objects
- * @param {object} config an object containing configurable attributes
- * Valid properties for DragDrop:
- * padding, isTarget, maintainOffset, primaryButtonOnly
+ * @param {Roo.Element/String/Object} config The configuration options.
*/
-Roo.dd.DragDrop = function(id, sGroup, config) {
- if (id) {
- this.init(id, sGroup, config);
- }
-
+Roo.BoxComponent = function(config){
+ Roo.Component.call(this, config);
+ this.addEvents({
+ /**
+ * @event resize
+ * Fires after the component is resized.
+ * @param {Roo.Component} this
+ * @param {Number} adjWidth The box-adjusted width that was set
+ * @param {Number} adjHeight The box-adjusted height that was set
+ * @param {Number} rawWidth The width that was originally specified
+ * @param {Number} rawHeight The height that was originally specified
+ */
+ resize : true,
+ /**
+ * @event move
+ * Fires after the component is moved.
+ * @param {Roo.Component} this
+ * @param {Number} x The new x position
+ * @param {Number} y The new y position
+ */
+ move : true
+ });
};
-Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
-
- /**
- * The id of the element associated with this object. This is what we
- * refer to as the "linked element" because the size and position of
- * this element is used to determine when the drag and drop objects have
- * interacted.
- * @property id
- * @type String
+Roo.extend(Roo.BoxComponent, Roo.Component, {
+ // private, set in afterRender to signify that the component has been rendered
+ boxReady : false,
+ // private, used to defer height settings to subclasses
+ deferHeight: false,
+ /** @cfg {Number} width
+ * width (optional) size of component
*/
- id: null,
-
- /**
- * Configuration attributes passed into the constructor
- * @property config
- * @type object
+ /** @cfg {Number} height
+ * height (optional) size of component
*/
- config: null,
-
+
/**
- * The id of the element that will be dragged. By default this is same
- * as the linked element , but could be changed to another element. Ex:
- * Roo.dd.DDProxy
- * @property dragElId
- * @type String
- * @private
+ * Sets the width and height of the component. This method fires the resize event. This method can accept
+ * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
+ * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
+ * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
+ * @return {Roo.BoxComponent} this
*/
- dragElId: null,
+ setSize : function(w, h){
+ // support for standard size objects
+ if(typeof w == 'object'){
+ h = w.height;
+ w = w.width;
+ }
+ // not rendered
+ if(!this.boxReady){
+ this.width = w;
+ this.height = h;
+ return this;
+ }
- /**
- * the id of the element that initiates the drag operation. By default
- * this is the linked element, but could be changed to be a child of this
- * element. This lets us do things like only starting the drag when the
- * header element within the linked html element is clicked.
- * @property handleElId
- * @type String
- * @private
- */
- handleElId: null,
+ // prevent recalcs when not needed
+ if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
+ return this;
+ }
+ this.lastSize = {width: w, height: h};
- /**
- * An associative array of HTML tags that will be ignored if clicked.
- * @property invalidHandleTypes
- * @type {string: string}
- */
- invalidHandleTypes: null,
+ var adj = this.adjustSize(w, h);
+ var aw = adj.width, ah = adj.height;
+ if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
+ var rz = this.getResizeEl();
+ if(!this.deferHeight && aw !== undefined && ah !== undefined){
+ rz.setSize(aw, ah);
+ }else if(!this.deferHeight && ah !== undefined){
+ rz.setHeight(ah);
+ }else if(aw !== undefined){
+ rz.setWidth(aw);
+ }
+ this.onResize(aw, ah, w, h);
+ this.fireEvent('resize', this, aw, ah, w, h);
+ }
+ return this;
+ },
/**
- * An associative array of ids for elements that will be ignored if clicked
- * @property invalidHandleIds
- * @type {string: string}
+ * Gets the current size of the component's underlying element.
+ * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
*/
- invalidHandleIds: null,
+ getSize : function(){
+ return this.el.getSize();
+ },
/**
- * An indexted array of css class names for elements that will be ignored
- * if clicked.
- * @property invalidHandleClasses
- * @type string[]
+ * Gets the current XY position of the component's underlying element.
+ * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
+ * @return {Array} The XY position of the element (e.g., [100, 200])
*/
- invalidHandleClasses: null,
+ getPosition : function(local){
+ if(local === true){
+ return [this.el.getLeft(true), this.el.getTop(true)];
+ }
+ return this.xy || this.el.getXY();
+ },
/**
- * The linked element's absolute X position at the time the drag was
- * started
- * @property startPageX
- * @type int
- * @private
+ * Gets the current box measurements of the component's underlying element.
+ * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
+ * @returns {Object} box An object in the format {x, y, width, height}
*/
- startPageX: 0,
+ getBox : function(local){
+ var s = this.el.getSize();
+ if(local){
+ s.x = this.el.getLeft(true);
+ s.y = this.el.getTop(true);
+ }else{
+ var xy = this.xy || this.el.getXY();
+ s.x = xy[0];
+ s.y = xy[1];
+ }
+ return s;
+ },
/**
- * The linked element's absolute X position at the time the drag was
- * started
- * @property startPageY
- * @type int
- * @private
+ * Sets the current box measurements of the component's underlying element.
+ * @param {Object} box An object in the format {x, y, width, height}
+ * @returns {Roo.BoxComponent} this
*/
- startPageY: 0,
+ updateBox : function(box){
+ this.setSize(box.width, box.height);
+ this.setPagePosition(box.x, box.y);
+ return this;
+ },
- /**
- * The group defines a logical collection of DragDrop objects that are
- * related. Instances only get events when interacting with other
- * DragDrop object in the same group. This lets us define multiple
- * groups using a single DragDrop subclass if we want.
- * @property groups
- * @type {string: string}
- */
- groups: null,
+ // protected
+ getResizeEl : function(){
+ return this.resizeEl || this.el;
+ },
- /**
- * Individual drag/drop instances can be locked. This will prevent
- * onmousedown start drag.
- * @property locked
- * @type boolean
- * @private
- */
- locked: false,
+ // protected
+ getPositionEl : function(){
+ return this.positionEl || this.el;
+ },
/**
- * Lock this instance
- * @method lock
+ * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
+ * This method fires the move event.
+ * @param {Number} left The new left
+ * @param {Number} top The new top
+ * @returns {Roo.BoxComponent} this
*/
- lock: function() { this.locked = true; },
+ setPosition : function(x, y){
+ this.x = x;
+ this.y = y;
+ if(!this.boxReady){
+ return this;
+ }
+ var adj = this.adjustPosition(x, y);
+ var ax = adj.x, ay = adj.y;
- /**
- * Unlock this instace
- * @method unlock
- */
- unlock: function() { this.locked = false; },
+ var el = this.getPositionEl();
+ if(ax !== undefined || ay !== undefined){
+ if(ax !== undefined && ay !== undefined){
+ el.setLeftTop(ax, ay);
+ }else if(ax !== undefined){
+ el.setLeft(ax);
+ }else if(ay !== undefined){
+ el.setTop(ay);
+ }
+ this.onPosition(ax, ay);
+ this.fireEvent('move', this, ax, ay);
+ }
+ return this;
+ },
/**
- * By default, all insances can be a drop target. This can be disabled by
- * setting isTarget to false.
- * @method isTarget
- * @type boolean
+ * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
+ * This method fires the move event.
+ * @param {Number} x The new x position
+ * @param {Number} y The new y position
+ * @returns {Roo.BoxComponent} this
*/
- isTarget: true,
+ setPagePosition : function(x, y){
+ this.pageX = x;
+ this.pageY = y;
+ if(!this.boxReady){
+ return;
+ }
+ if(x === undefined || y === undefined){ // cannot translate undefined points
+ return;
+ }
+ var p = this.el.translatePoints(x, y);
+ this.setPosition(p.left, p.top);
+ return this;
+ },
- /**
- * The padding configured for this drag and drop object for calculating
- * the drop zone intersection with this object.
- * @method padding
- * @type int[]
- */
- padding: null,
+ // private
+ onRender : function(ct, position){
+ Roo.BoxComponent.superclass.onRender.call(this, ct, position);
+ if(this.resizeEl){
+ this.resizeEl = Roo.get(this.resizeEl);
+ }
+ if(this.positionEl){
+ this.positionEl = Roo.get(this.positionEl);
+ }
+ },
- /**
- * Cached reference to the linked element
- * @property _domRef
- * @private
- */
- _domRef: null,
+ // private
+ afterRender : function(){
+ Roo.BoxComponent.superclass.afterRender.call(this);
+ this.boxReady = true;
+ this.setSize(this.width, this.height);
+ if(this.x || this.y){
+ this.setPosition(this.x, this.y);
+ }
+ if(this.pageX || this.pageY){
+ this.setPagePosition(this.pageX, this.pageY);
+ }
+ },
/**
- * Internal typeof flag
- * @property __ygDragDrop
- * @private
+ * Force the component's size to recalculate based on the underlying element's current height and width.
+ * @returns {Roo.BoxComponent} this
*/
- __ygDragDrop: true,
+ syncSize : function(){
+ delete this.lastSize;
+ this.setSize(this.el.getWidth(), this.el.getHeight());
+ return this;
+ },
/**
- * Set to true when horizontal contraints are applied
- * @property constrainX
- * @type boolean
- * @private
+ * Called after the component is resized, this method is empty by default but can be implemented by any
+ * subclass that needs to perform custom logic after a resize occurs.
+ * @param {Number} adjWidth The box-adjusted width that was set
+ * @param {Number} adjHeight The box-adjusted height that was set
+ * @param {Number} rawWidth The width that was originally specified
+ * @param {Number} rawHeight The height that was originally specified
*/
- constrainX: false,
+ onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
- /**
- * Set to true when vertical contraints are applied
- * @property constrainY
- * @type boolean
- * @private
- */
- constrainY: false,
+ },
/**
- * The left constraint
- * @property minX
- * @type int
- * @private
+ * Called after the component is moved, this method is empty by default but can be implemented by any
+ * subclass that needs to perform custom logic after a move occurs.
+ * @param {Number} x The new x position
+ * @param {Number} y The new y position
*/
- minX: 0,
+ onPosition : function(x, y){
- /**
- * The right constraint
- * @property maxX
- * @type int
- * @private
- */
- maxX: 0,
+ },
- /**
- * The up constraint
- * @property minY
- * @type int
- * @type int
- * @private
- */
- minY: 0,
+ // private
+ adjustSize : function(w, h){
+ if(this.autoWidth){
+ w = 'auto';
+ }
+ if(this.autoHeight){
+ h = 'auto';
+ }
+ return {width : w, height: h};
+ },
- /**
- * The down constraint
- * @property maxY
- * @type int
- * @private
- */
- maxY: 0,
+ // private
+ adjustPosition : function(x, y){
+ return {x : x, y: y};
+ }
+});/*
+ * Original code for Roojs - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Roo.XComponent
+ * A delayed Element creator...
+ * Or a way to group chunks of interface together.
+ *
+ * Mypart.xyx = new Roo.XComponent({
+ parent : 'Mypart.xyz', // empty == document.element.!!
+ order : '001',
+ name : 'xxxx'
+ region : 'xxxx'
+ disabled : function() {}
+
+ tree : function() { // return an tree of xtype declared components
+ var MODULE = this;
+ return
+ {
+ xtype : 'NestedLayoutPanel',
+ // technicall
+ }
+ ]
+ *})
+ *
+ *
+ * It can be used to build a big heiracy, with parent etc.
+ * or you can just use this to render a single compoent to a dom element
+ * MYPART.render(Roo.Element | String(id) | dom_element )
+ *
+ * @extends Roo.util.Observable
+ * @constructor
+ * @param cfg {Object} configuration of component
+ *
+ */
+Roo.XComponent = function(cfg) {
+ Roo.apply(this, cfg);
+ this.addEvents({
+ /**
+ * @event built
+ * Fires when this the componnt is built
+ * @param {Roo.XComponent} c the component
+ */
+ 'built' : true
+
+ });
+ this.region = this.region || 'center'; // default..
+ Roo.XComponent.register(this);
+ this.modules = false;
+ this.el = false; // where the layout goes..
+
+
+}
+Roo.extend(Roo.XComponent, Roo.util.Observable, {
/**
- * Maintain offsets when we resetconstraints. Set to true when you want
- * the position of the element relative to its parent to stay the same
- * when the page changes
- *
- * @property maintainOffset
- * @type boolean
+ * @property el
+ * The created element (with Roo.factory())
+ * @type {Roo.Layout}
*/
- maintainOffset: false,
-
+ el : false,
+
/**
- * Array of pixel locations the element will snap to if we specified a
- * horizontal graduation/interval. This array is generated automatically
- * when you define a tick interval.
- * @property xTicks
- * @type int[]
+ * @property el
+ * for BC - use el in new code
+ * @type {Roo.Layout}
*/
- xTicks: null,
-
+ panel : false,
+
/**
- * Array of pixel locations the element will snap to if we specified a
- * vertical graduation/interval. This array is generated automatically
- * when you define a tick interval.
- * @property yTicks
- * @type int[]
+ * @property layout
+ * for BC - use el in new code
+ * @type {Roo.Layout}
*/
- yTicks: null,
-
- /**
- * By default the drag and drop instance will only respond to the primary
- * button click (left button for a right-handed mouse). Set to true to
- * allow drag and drop to start with any mouse click that is propogated
- * by the browser
- * @property primaryButtonOnly
- * @type boolean
+ layout : false,
+
+ /**
+ * @cfg {Function|boolean} disabled
+ * If this module is disabled by some rule, return true from the funtion
*/
- primaryButtonOnly: true,
-
+ disabled : false,
+
/**
- * The availabe property is false until the linked dom element is accessible.
- * @property available
- * @type boolean
+ * @cfg {String} parent
+ * Name of parent element which it get xtype added to..
*/
- available: false,
-
+ parent: false,
+
/**
- * By default, drags can only be initiated if the mousedown occurs in the
- * region the linked element is. This is done in part to work around a
- * bug in some browsers that mis-report the mousedown if the previous
- * mouseup happened outside of the window. This property is set to true
- * if outer handles are defined.
- *
- * @property hasOuterHandles
- * @type boolean
- * @default false
+ * @cfg {String} order
+ * Used to set the order in which elements are created (usefull for multiple tabs)
*/
- hasOuterHandles: false,
-
+
+ order : false,
/**
- * Code that executes immediately before the startDrag event
- * @method b4StartDrag
- * @private
+ * @cfg {String} name
+ * String to display while loading.
*/
- b4StartDrag: function(x, y) { },
-
+ name : false,
/**
- * Abstract method called after a drag/drop object is clicked
- * and the drag or mousedown time thresholds have beeen met.
- * @method startDrag
- * @param {int} X click location
- * @param {int} Y click location
+ * @cfg {String} region
+ * Region to render component to (defaults to center)
*/
- startDrag: function(x, y) { /* override this */ },
-
+ region : 'center',
+
/**
- * Code that executes immediately before the onDrag event
- * @method b4Drag
- * @private
+ * @cfg {Array} items
+ * A single item array - the first element is the root of the tree..
+ * It's done this way to stay compatible with the Xtype system...
*/
- b4Drag: function(e) { },
-
+ items : false,
+
/**
- * Abstract method called during the onMouseMove event while dragging an
- * object.
- * @method onDrag
- * @param {Event} e the mousemove event
+ * @property _tree
+ * The method that retuns the tree of parts that make up this compoennt
+ * @type {function}
*/
- onDrag: function(e) { /* override this */ },
-
- /**
- * Abstract method called when this element fist begins hovering over
- * another DragDrop obj
- * @method onDragEnter
- * @param {Event} e the mousemove event
- * @param {String|DragDrop[]} id In POINT mode, the element
- * id this is hovering over. In INTERSECT mode, an array of one or more
- * dragdrop items being hovered over.
+ _tree : false,
+
+ /**
+ * render
+ * render element to dom or tree
+ * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
*/
- onDragEnter: function(e, id) { /* override this */ },
-
- /**
- * Code that executes immediately before the onDragOver event
- * @method b4DragOver
- * @private
- */
- b4DragOver: function(e) { },
-
- /**
- * Abstract method called when this element is hovering over another
- * DragDrop obj
- * @method onDragOver
- * @param {Event} e the mousemove event
- * @param {String|DragDrop[]} id In POINT mode, the element
- * id this is hovering over. In INTERSECT mode, an array of dd items
- * being hovered over.
- */
- onDragOver: function(e, id) { /* override this */ },
-
- /**
- * Code that executes immediately before the onDragOut event
- * @method b4DragOut
- * @private
- */
- b4DragOut: function(e) { },
-
- /**
- * Abstract method called when we are no longer hovering over an element
- * @method onDragOut
- * @param {Event} e the mousemove event
- * @param {String|DragDrop[]} id In POINT mode, the element
- * id this was hovering over. In INTERSECT mode, an array of dd items
- * that the mouse is no longer over.
- */
- onDragOut: function(e, id) { /* override this */ },
+
+ render : function(el)
+ {
+
+ el = el || false;
+ var hp = this.parent ? 1 : 0;
+
+ if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
+ // if parent is a '#.....' string, then let's use that..
+ var ename = this.parent.substr(1)
+ this.parent = (this.parent == '#bootstrap') ? { el : true} : false; // flags it as a top module...
+ el = Roo.get(ename);
+ if (!el && !this.parent) {
+ Roo.log("Warning - element can not be found :#" + ename );
+ return;
+ }
+ }
+
+
+ if (!this.parent) {
+
+ el = el ? Roo.get(el) : false;
+
+ // it's a top level one..
+ this.parent = {
+ el : new Roo.BorderLayout(el || document.body, {
+
+ center: {
+ titlebar: false,
+ autoScroll:false,
+ closeOnTab: true,
+ tabPosition: 'top',
+ //resizeTabs: true,
+ alwaysShowTabs: el && hp? false : true,
+ hideTabs: el || !hp ? true : false,
+ minTabWidth: 140
+ }
+ })
+ }
+ }
+
+ if (!this.parent.el) {
+ // probably an old style ctor, which has been disabled.
+ return;
+
+ }
+ // The 'tree' method is '_tree now'
+
+ var tree = this._tree ? this._tree() : this.tree();
+ tree.region = tree.region || this.region;
+ this.el = this.parent.el.addxtype(tree);
+ this.fireEvent('built', this);
+
+ this.panel = this.el;
+ this.layout = this.panel.layout;
+ this.parentLayout = this.parent.layout || false;
+
+ }
+
+});
+Roo.apply(Roo.XComponent, {
/**
- * Code that executes immediately before the onDragDrop event
- * @method b4DragDrop
- * @private
+ * @property hideProgress
+ * true to disable the building progress bar.. usefull on single page renders.
+ * @type Boolean
*/
- b4DragDrop: function(e) { },
-
+ hideProgress : false,
/**
- * Abstract method called when this item is dropped on another DragDrop
- * obj
- * @method onDragDrop
- * @param {Event} e the mouseup event
- * @param {String|DragDrop[]} id In POINT mode, the element
- * id this was dropped on. In INTERSECT mode, an array of dd items this
- * was dropped on.
+ * @property buildCompleted
+ * True when the builder has completed building the interface.
+ * @type Boolean
*/
- onDragDrop: function(e, id) { /* override this */ },
-
+ buildCompleted : false,
+
/**
- * Abstract method called when this item is dropped on an area with no
- * drop target
- * @method onInvalidDrop
- * @param {Event} e the mouseup event
+ * @property topModule
+ * the upper most module - uses document.element as it's constructor.
+ * @type Object
*/
- onInvalidDrop: function(e) { /* override this */ },
-
+
+ topModule : false,
+
/**
- * Code that executes immediately before the endDrag event
- * @method b4EndDrag
- * @private
+ * @property modules
+ * array of modules to be created by registration system.
+ * @type {Array} of Roo.XComponent
*/
- b4EndDrag: function(e) { },
-
+
+ modules : [],
/**
- * Fired when we are done dragging the object
- * @method endDrag
- * @param {Event} e the mouseup event
+ * @property elmodules
+ * array of modules to be created by which use #ID
+ * @type {Array} of Roo.XComponent
*/
- endDrag: function(e) { /* override this */ },
+
+ elmodules : [],
+
/**
- * Code executed immediately before the onMouseDown event
- * @method b4MouseDown
- * @param {Event} e the mousedown event
- * @private
+ * Register components to be built later.
+ *
+ * This solves the following issues
+ * - Building is not done on page load, but after an authentication process has occured.
+ * - Interface elements are registered on page load
+ * - Parent Interface elements may not be loaded before child, so this handles that..
+ *
+ *
+ * example:
+ *
+ * MyApp.register({
+ order : '000001',
+ module : 'Pman.Tab.projectMgr',
+ region : 'center',
+ parent : 'Pman.layout',
+ disabled : false, // or use a function..
+ })
+
+ * * @param {Object} details about module
*/
- b4MouseDown: function(e) { },
-
+ register : function(obj) {
+
+ Roo.XComponent.event.fireEvent('register', obj);
+ switch(typeof(obj.disabled) ) {
+
+ case 'undefined':
+ break;
+
+ case 'function':
+ if ( obj.disabled() ) {
+ return;
+ }
+ break;
+
+ default:
+ if (obj.disabled) {
+ return;
+ }
+ break;
+ }
+
+ this.modules.push(obj);
+
+ },
/**
- * Event handler that fires when a drag/drop obj gets a mousedown
- * @method onMouseDown
- * @param {Event} e the mousedown event
- */
- onMouseDown: function(e) { /* override this */ },
+ * convert a string to an object..
+ * eg. 'AAA.BBB' -> finds AAA.BBB
- /**
- * Event handler that fires when a drag/drop obj gets a mouseup
- * @method onMouseUp
- * @param {Event} e the mouseup event
*/
- onMouseUp: function(e) { /* override this */ },
+
+ toObject : function(str)
+ {
+ if (!str || typeof(str) == 'object') {
+ return str;
+ }
+ if (str.substring(0,1) == '#') {
+ return str;
+ }
- /**
- * Override the onAvailable method to do what is needed after the initial
- * position was determined.
- * @method onAvailable
- */
- onAvailable: function () {
+ var ar = str.split('.');
+ var rt, o;
+ rt = ar.shift();
+ /** eval:var:o */
+ try {
+ eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
+ } catch (e) {
+ throw "Module not found : " + str;
+ }
+
+ if (o === false) {
+ throw "Module not found : " + str;
+ }
+ Roo.each(ar, function(e) {
+ if (typeof(o[e]) == 'undefined') {
+ throw "Module not found : " + str;
+ }
+ o = o[e];
+ });
+
+ return o;
+
},
-
- /*
- * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
- * @type Object
+
+
+ /**
+ * move modules into their correct place in the tree..
+ *
*/
- defaultPadding : {left:0, right:0, top:0, bottom:0},
-
- /*
+ preBuild : function ()
+ {
+ var _t = this;
+ Roo.each(this.modules , function (obj)
+ {
+ Roo.XComponent.event.fireEvent('beforebuild', obj);
+
+ var opar = obj.parent;
+ try {
+ obj.parent = this.toObject(opar);
+ } catch(e) {
+ Roo.log("parent:toObject failed: " + e.toString());
+ return;
+ }
+
+ if (!obj.parent) {
+ Roo.debug && Roo.log("GOT top level module");
+ Roo.debug && Roo.log(obj);
+ obj.modules = new Roo.util.MixedCollection(false,
+ function(o) { return o.order + '' }
+ );
+ this.topModule = obj;
+ return;
+ }
+ // parent is a string (usually a dom element name..)
+ if (typeof(obj.parent) == 'string') {
+ this.elmodules.push(obj);
+ return;
+ }
+ if (obj.parent.constructor != Roo.XComponent) {
+ Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
+ }
+ if (!obj.parent.modules) {
+ obj.parent.modules = new Roo.util.MixedCollection(false,
+ function(o) { return o.order + '' }
+ );
+ }
+ if (obj.parent.disabled) {
+ obj.disabled = true;
+ }
+ obj.parent.modules.add(obj);
+ }, this);
+ },
+
+ /**
+ * make a list of modules to build.
+ * @return {Array} list of modules.
+ */
+
+ buildOrder : function()
+ {
+ var _this = this;
+ var cmp = function(a,b) {
+ return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
+ };
+ if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
+ throw "No top level modules to build";
+ }
+
+ // make a flat list in order of modules to build.
+ var mods = this.topModule ? [ this.topModule ] : [];
+
+
+ // elmodules (is a list of DOM based modules )
+ Roo.each(this.elmodules, function(e) {
+ mods.push(e);
+ if (!this.topModule &&
+ typeof(e.parent) == 'string' &&
+ e.parent.substring(0,1) == '#' &&
+ Roo.get(e.parent.substr(1))
+ ) {
+
+ _this.topModule = e;
+ }
+
+ });
+
+
+ // add modules to their parents..
+ var addMod = function(m) {
+ Roo.debug && Roo.log("build Order: add: " + m.name);
+
+ mods.push(m);
+ if (m.modules && !m.disabled) {
+ Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
+ m.modules.keySort('ASC', cmp );
+ Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
+
+ m.modules.each(addMod);
+ } else {
+ Roo.debug && Roo.log("build Order: no child modules");
+ }
+ // not sure if this is used any more..
+ if (m.finalize) {
+ m.finalize.name = m.name + " (clean up) ";
+ mods.push(m.finalize);
+ }
+
+ }
+ if (this.topModule && this.topModule.modules) {
+ this.topModule.modules.keySort('ASC', cmp );
+ this.topModule.modules.each(addMod);
+ }
+ return mods;
+ },
+
+ /**
+ * Build the registered modules.
+ * @param {Object} parent element.
+ * @param {Function} optional method to call after module has been added.
+ *
+ */
+
+ build : function()
+ {
+
+ this.preBuild();
+ var mods = this.buildOrder();
+
+ //this.allmods = mods;
+ //Roo.debug && Roo.log(mods);
+ //return;
+ if (!mods.length) { // should not happen
+ throw "NO modules!!!";
+ }
+
+
+ var msg = "Building Interface...";
+ // flash it up as modal - so we store the mask!?
+ if (!this.hideProgress) {
+ Roo.MessageBox.show({ title: 'loading' });
+ Roo.MessageBox.show({
+ title: "Please wait...",
+ msg: msg,
+ width:450,
+ progress:true,
+ closable:false,
+ modal: false
+
+ });
+ }
+ var total = mods.length;
+
+ var _this = this;
+ var progressRun = function() {
+ if (!mods.length) {
+ Roo.debug && Roo.log('hide?');
+ if (!this.hideProgress) {
+ Roo.MessageBox.hide();
+ }
+ Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
+
+ // THE END...
+ return false;
+ }
+
+ var m = mods.shift();
+
+
+ Roo.debug && Roo.log(m);
+ // not sure if this is supported any more.. - modules that are are just function
+ if (typeof(m) == 'function') {
+ m.call(this);
+ return progressRun.defer(10, _this);
+ }
+
+
+ msg = "Building Interface " + (total - mods.length) +
+ " of " + total +
+ (m.name ? (' - ' + m.name) : '');
+ Roo.debug && Roo.log(msg);
+ if (!this.hideProgress) {
+ Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
+ }
+
+
+ // is the module disabled?
+ var disabled = (typeof(m.disabled) == 'function') ?
+ m.disabled.call(m.module.disabled) : m.disabled;
+
+
+ if (disabled) {
+ return progressRun(); // we do not update the display!
+ }
+
+ // now build
+
+
+
+ m.render();
+ // it's 10 on top level, and 1 on others??? why...
+ return progressRun.defer(10, _this);
+
+ }
+ progressRun.defer(1, _this);
+
+
+
+ },
+
+
+ /**
+ * Event Object.
+ *
+ *
+ */
+ event: false,
+ /**
+ * wrapper for event.on - aliased later..
+ * Typically use to register a event handler for register:
+ *
+ * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
+ *
+ */
+ on : false
+
+
+
+});
+
+Roo.XComponent.event = new Roo.util.Observable({
+ events : {
+ /**
+ * @event register
+ * Fires when an Component is registered,
+ * set the disable property on the Component to stop registration.
+ * @param {Roo.XComponent} c the component being registerd.
+ *
+ */
+ 'register' : true,
+ /**
+ * @event beforebuild
+ * Fires before each Component is built
+ * can be used to apply permissions.
+ * @param {Roo.XComponent} c the component being registerd.
+ *
+ */
+ 'beforebuild' : true,
+ /**
+ * @event buildcomplete
+ * Fires on the top level element when all elements have been built
+ * @param {Roo.XComponent} the top level component.
+ */
+ 'buildcomplete' : true
+
+ }
+});
+
+Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
+ /*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+
+
+/*
+ * These classes are derivatives of the similarly named classes in the YUI Library.
+ * The original license:
+ * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+(function() {
+
+var Event=Roo.EventManager;
+var Dom=Roo.lib.Dom;
+
+/**
+ * @class Roo.dd.DragDrop
+ * @extends Roo.util.Observable
+ * Defines the interface and base operation of items that that can be
+ * dragged or can be drop targets. It was designed to be extended, overriding
+ * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
+ * Up to three html elements can be associated with a DragDrop instance:
+ * <ul>
+ * <li>linked element: the element that is passed into the constructor.
+ * This is the element which defines the boundaries for interaction with
+ * other DragDrop objects.</li>
+ * <li>handle element(s): The drag operation only occurs if the element that
+ * was clicked matches a handle element. By default this is the linked
+ * element, but there are times that you will want only a portion of the
+ * linked element to initiate the drag operation, and the setHandleElId()
+ * method provides a way to define this.</li>
+ * <li>drag element: this represents the element that would be moved along
+ * with the cursor during a drag operation. By default, this is the linked
+ * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
+ * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
+ * </li>
+ * </ul>
+ * This class should not be instantiated until the onload event to ensure that
+ * the associated elements are available.
+ * The following would define a DragDrop obj that would interact with any
+ * other DragDrop obj in the "group1" group:
+ * <pre>
+ * dd = new Roo.dd.DragDrop("div1", "group1");
+ * </pre>
+ * Since none of the event handlers have been implemented, nothing would
+ * actually happen if you were to run the code above. Normally you would
+ * override this class or one of the default implementations, but you can
+ * also override the methods you want on an instance of the class...
+ * <pre>
+ * dd.onDragDrop = function(e, id) {
+ * alert("dd was dropped on " + id);
+ * }
+ * </pre>
+ * @constructor
+ * @param {String} id of the element that is linked to this instance
+ * @param {String} sGroup the group of related DragDrop objects
+ * @param {object} config an object containing configurable attributes
+ * Valid properties for DragDrop:
+ * padding, isTarget, maintainOffset, primaryButtonOnly
+ */
+Roo.dd.DragDrop = function(id, sGroup, config) {
+ if (id) {
+ this.init(id, sGroup, config);
+ }
+
+};
+
+Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
+
+ /**
+ * The id of the element associated with this object. This is what we
+ * refer to as the "linked element" because the size and position of
+ * this element is used to determine when the drag and drop objects have
+ * interacted.
+ * @property id
+ * @type String
+ */
+ id: null,
+
+ /**
+ * Configuration attributes passed into the constructor
+ * @property config
+ * @type object
+ */
+ config: null,
+
+ /**
+ * The id of the element that will be dragged. By default this is same
+ * as the linked element , but could be changed to another element. Ex:
+ * Roo.dd.DDProxy
+ * @property dragElId
+ * @type String
+ * @private
+ */
+ dragElId: null,
+
+ /**
+ * the id of the element that initiates the drag operation. By default
+ * this is the linked element, but could be changed to be a child of this
+ * element. This lets us do things like only starting the drag when the
+ * header element within the linked html element is clicked.
+ * @property handleElId
+ * @type String
+ * @private
+ */
+ handleElId: null,
+
+ /**
+ * An associative array of HTML tags that will be ignored if clicked.
+ * @property invalidHandleTypes
+ * @type {string: string}
+ */
+ invalidHandleTypes: null,
+
+ /**
+ * An associative array of ids for elements that will be ignored if clicked
+ * @property invalidHandleIds
+ * @type {string: string}
+ */
+ invalidHandleIds: null,
+
+ /**
+ * An indexted array of css class names for elements that will be ignored
+ * if clicked.
+ * @property invalidHandleClasses
+ * @type string[]
+ */
+ invalidHandleClasses: null,
+
+ /**
+ * The linked element's absolute X position at the time the drag was
+ * started
+ * @property startPageX
+ * @type int
+ * @private
+ */
+ startPageX: 0,
+
+ /**
+ * The linked element's absolute X position at the time the drag was
+ * started
+ * @property startPageY
+ * @type int
+ * @private
+ */
+ startPageY: 0,
+
+ /**
+ * The group defines a logical collection of DragDrop objects that are
+ * related. Instances only get events when interacting with other
+ * DragDrop object in the same group. This lets us define multiple
+ * groups using a single DragDrop subclass if we want.
+ * @property groups
+ * @type {string: string}
+ */
+ groups: null,
+
+ /**
+ * Individual drag/drop instances can be locked. This will prevent
+ * onmousedown start drag.
+ * @property locked
+ * @type boolean
+ * @private
+ */
+ locked: false,
+
+ /**
+ * Lock this instance
+ * @method lock
+ */
+ lock: function() { this.locked = true; },
+
+ /**
+ * Unlock this instace
+ * @method unlock
+ */
+ unlock: function() { this.locked = false; },
+
+ /**
+ * By default, all insances can be a drop target. This can be disabled by
+ * setting isTarget to false.
+ * @method isTarget
+ * @type boolean
+ */
+ isTarget: true,
+
+ /**
+ * The padding configured for this drag and drop object for calculating
+ * the drop zone intersection with this object.
+ * @method padding
+ * @type int[]
+ */
+ padding: null,
+
+ /**
+ * Cached reference to the linked element
+ * @property _domRef
+ * @private
+ */
+ _domRef: null,
+
+ /**
+ * Internal typeof flag
+ * @property __ygDragDrop
+ * @private
+ */
+ __ygDragDrop: true,
+
+ /**
+ * Set to true when horizontal contraints are applied
+ * @property constrainX
+ * @type boolean
+ * @private
+ */
+ constrainX: false,
+
+ /**
+ * Set to true when vertical contraints are applied
+ * @property constrainY
+ * @type boolean
+ * @private
+ */
+ constrainY: false,
+
+ /**
+ * The left constraint
+ * @property minX
+ * @type int
+ * @private
+ */
+ minX: 0,
+
+ /**
+ * The right constraint
+ * @property maxX
+ * @type int
+ * @private
+ */
+ maxX: 0,
+
+ /**
+ * The up constraint
+ * @property minY
+ * @type int
+ * @type int
+ * @private
+ */
+ minY: 0,
+
+ /**
+ * The down constraint
+ * @property maxY
+ * @type int
+ * @private
+ */
+ maxY: 0,
+
+ /**
+ * Maintain offsets when we resetconstraints. Set to true when you want
+ * the position of the element relative to its parent to stay the same
+ * when the page changes
+ *
+ * @property maintainOffset
+ * @type boolean
+ */
+ maintainOffset: false,
+
+ /**
+ * Array of pixel locations the element will snap to if we specified a
+ * horizontal graduation/interval. This array is generated automatically
+ * when you define a tick interval.
+ * @property xTicks
+ * @type int[]
+ */
+ xTicks: null,
+
+ /**
+ * Array of pixel locations the element will snap to if we specified a
+ * vertical graduation/interval. This array is generated automatically
+ * when you define a tick interval.
+ * @property yTicks
+ * @type int[]
+ */
+ yTicks: null,
+
+ /**
+ * By default the drag and drop instance will only respond to the primary
+ * button click (left button for a right-handed mouse). Set to true to
+ * allow drag and drop to start with any mouse click that is propogated
+ * by the browser
+ * @property primaryButtonOnly
+ * @type boolean
+ */
+ primaryButtonOnly: true,
+
+ /**
+ * The availabe property is false until the linked dom element is accessible.
+ * @property available
+ * @type boolean
+ */
+ available: false,
+
+ /**
+ * By default, drags can only be initiated if the mousedown occurs in the
+ * region the linked element is. This is done in part to work around a
+ * bug in some browsers that mis-report the mousedown if the previous
+ * mouseup happened outside of the window. This property is set to true
+ * if outer handles are defined.
+ *
+ * @property hasOuterHandles
+ * @type boolean
+ * @default false
+ */
+ hasOuterHandles: false,
+
+ /**
+ * Code that executes immediately before the startDrag event
+ * @method b4StartDrag
+ * @private
+ */
+ b4StartDrag: function(x, y) { },
+
+ /**
+ * Abstract method called after a drag/drop object is clicked
+ * and the drag or mousedown time thresholds have beeen met.
+ * @method startDrag
+ * @param {int} X click location
+ * @param {int} Y click location
+ */
+ startDrag: function(x, y) { /* override this */ },
+
+ /**
+ * Code that executes immediately before the onDrag event
+ * @method b4Drag
+ * @private
+ */
+ b4Drag: function(e) { },
+
+ /**
+ * Abstract method called during the onMouseMove event while dragging an
+ * object.
+ * @method onDrag
+ * @param {Event} e the mousemove event
+ */
+ onDrag: function(e) { /* override this */ },
+
+ /**
+ * Abstract method called when this element fist begins hovering over
+ * another DragDrop obj
+ * @method onDragEnter
+ * @param {Event} e the mousemove event
+ * @param {String|DragDrop[]} id In POINT mode, the element
+ * id this is hovering over. In INTERSECT mode, an array of one or more
+ * dragdrop items being hovered over.
+ */
+ onDragEnter: function(e, id) { /* override this */ },
+
+ /**
+ * Code that executes immediately before the onDragOver event
+ * @method b4DragOver
+ * @private
+ */
+ b4DragOver: function(e) { },
+
+ /**
+ * Abstract method called when this element is hovering over another
+ * DragDrop obj
+ * @method onDragOver
+ * @param {Event} e the mousemove event
+ * @param {String|DragDrop[]} id In POINT mode, the element
+ * id this is hovering over. In INTERSECT mode, an array of dd items
+ * being hovered over.
+ */
+ onDragOver: function(e, id) { /* override this */ },
+
+ /**
+ * Code that executes immediately before the onDragOut event
+ * @method b4DragOut
+ * @private
+ */
+ b4DragOut: function(e) { },
+
+ /**
+ * Abstract method called when we are no longer hovering over an element
+ * @method onDragOut
+ * @param {Event} e the mousemove event
+ * @param {String|DragDrop[]} id In POINT mode, the element
+ * id this was hovering over. In INTERSECT mode, an array of dd items
+ * that the mouse is no longer over.
+ */
+ onDragOut: function(e, id) { /* override this */ },
+
+ /**
+ * Code that executes immediately before the onDragDrop event
+ * @method b4DragDrop
+ * @private
+ */
+ b4DragDrop: function(e) { },
+
+ /**
+ * Abstract method called when this item is dropped on another DragDrop
+ * obj
+ * @method onDragDrop
+ * @param {Event} e the mouseup event
+ * @param {String|DragDrop[]} id In POINT mode, the element
+ * id this was dropped on. In INTERSECT mode, an array of dd items this
+ * was dropped on.
+ */
+ onDragDrop: function(e, id) { /* override this */ },
+
+ /**
+ * Abstract method called when this item is dropped on an area with no
+ * drop target
+ * @method onInvalidDrop
+ * @param {Event} e the mouseup event
+ */
+ onInvalidDrop: function(e) { /* override this */ },
+
+ /**
+ * Code that executes immediately before the endDrag event
+ * @method b4EndDrag
+ * @private
+ */
+ b4EndDrag: function(e) { },
+
+ /**
+ * Fired when we are done dragging the object
+ * @method endDrag
+ * @param {Event} e the mouseup event
+ */
+ endDrag: function(e) { /* override this */ },
+
+ /**
+ * Code executed immediately before the onMouseDown event
+ * @method b4MouseDown
+ * @param {Event} e the mousedown event
+ * @private
+ */
+ b4MouseDown: function(e) { },
+
+ /**
+ * Event handler that fires when a drag/drop obj gets a mousedown
+ * @method onMouseDown
+ * @param {Event} e the mousedown event
+ */
+ onMouseDown: function(e) { /* override this */ },
+
+ /**
+ * Event handler that fires when a drag/drop obj gets a mouseup
+ * @method onMouseUp
+ * @param {Event} e the mouseup event
+ */
+ onMouseUp: function(e) { /* override this */ },
+
+ /**
+ * Override the onAvailable method to do what is needed after the initial
+ * position was determined.
+ * @method onAvailable
+ */
+ onAvailable: function () {
+ },
+
+ /*
+ * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
+ * @type Object
+ */
+ defaultPadding : {left:0, right:0, top:0, bottom:0},
+
+ /*
* Initializes the drag drop object's constraints to restrict movement to a certain element.
*
* Usage:
"insert" : true,
/**
* @event beforeappend
- * Fires before a new child is appended to a node in this tree, return false to cancel the append.
- * @param {Tree} tree The owner tree
- * @param {Node} parent The parent node
- * @param {Node} node The child node to be appended
- */
- "beforeappend" : true,
- /**
- * @event beforeremove
- * Fires before a child is removed from a node in this tree, return false to cancel the remove.
- * @param {Tree} tree The owner tree
- * @param {Node} parent The parent node
- * @param {Node} node The child node to be removed
- */
- "beforeremove" : true,
- /**
- * @event beforemove
- * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
- * @param {Tree} tree The owner tree
- * @param {Node} node The node being moved
- * @param {Node} oldParent The parent of the node
- * @param {Node} newParent The new parent the node is moving to
- * @param {Number} index The index it is being moved to
- */
- "beforemove" : true,
- /**
- * @event beforeinsert
- * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
- * @param {Tree} tree The owner tree
- * @param {Node} parent The parent node
- * @param {Node} node The child node to be inserted
- * @param {Node} refNode The child node the node is being inserted before
- */
- "beforeinsert" : true
- });
-
- Roo.data.Tree.superclass.constructor.call(this);
-};
-
-Roo.extend(Roo.data.Tree, Roo.util.Observable, {
- pathSeparator: "/",
-
- proxyNodeEvent : function(){
- return this.fireEvent.apply(this, arguments);
- },
-
- /**
- * Returns the root node for this tree.
- * @return {Node}
- */
- getRootNode : function(){
- return this.root;
- },
-
- /**
- * Sets the root node for this tree.
- * @param {Node} node
- * @return {Node}
- */
- setRootNode : function(node){
- this.root = node;
- node.ownerTree = this;
- node.isRoot = true;
- this.registerNode(node);
- return node;
- },
-
- /**
- * Gets a node in this tree by its id.
- * @param {String} id
- * @return {Node}
- */
- getNodeById : function(id){
- return this.nodeHash[id];
- },
-
- registerNode : function(node){
- this.nodeHash[node.id] = node;
- },
-
- unregisterNode : function(node){
- delete this.nodeHash[node.id];
- },
-
- toString : function(){
- return "[Tree"+(this.id?" "+this.id:"")+"]";
- }
-});
-
-/**
- * @class Roo.data.Node
- * @extends Roo.util.Observable
- * @cfg {Boolean} leaf true if this node is a leaf and does not have children
- * @cfg {String} id The id for this node. If one is not specified, one is generated.
- * @constructor
- * @param {Object} attributes The attributes/config for the node
- */
-Roo.data.Node = function(attributes){
- /**
- * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
- * @type {Object}
- */
- this.attributes = attributes || {};
- this.leaf = this.attributes.leaf;
- /**
- * The node id. @type String
- */
- this.id = this.attributes.id;
- if(!this.id){
- this.id = Roo.id(null, "ynode-");
- this.attributes.id = this.id;
- }
-
-
- /**
- * All child nodes of this node. @type Array
- */
- this.childNodes = [];
- if(!this.childNodes.indexOf){ // indexOf is a must
- this.childNodes.indexOf = function(o){
- for(var i = 0, len = this.length; i < len; i++){
- if(this[i] == o) {
- return i;
- }
- }
- return -1;
- };
- }
- /**
- * The parent node for this node. @type Node
- */
- this.parentNode = null;
- /**
- * The first direct child node of this node, or null if this node has no child nodes. @type Node
- */
- this.firstChild = null;
- /**
- * The last direct child node of this node, or null if this node has no child nodes. @type Node
- */
- this.lastChild = null;
- /**
- * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
- */
- this.previousSibling = null;
- /**
- * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
- */
- this.nextSibling = null;
-
- this.addEvents({
- /**
- * @event append
- * Fires when a new child node is appended
- * @param {Tree} tree The owner tree
- * @param {Node} this This node
- * @param {Node} node The newly appended node
- * @param {Number} index The index of the newly appended node
- */
- "append" : true,
- /**
- * @event remove
- * Fires when a child node is removed
- * @param {Tree} tree The owner tree
- * @param {Node} this This node
- * @param {Node} node The removed node
- */
- "remove" : true,
- /**
- * @event move
- * Fires when this node is moved to a new location in the tree
- * @param {Tree} tree The owner tree
- * @param {Node} this This node
- * @param {Node} oldParent The old parent of this node
- * @param {Node} newParent The new parent of this node
- * @param {Number} index The index it was moved to
- */
- "move" : true,
- /**
- * @event insert
- * Fires when a new child node is inserted.
- * @param {Tree} tree The owner tree
- * @param {Node} this This node
- * @param {Node} node The child node inserted
- * @param {Node} refNode The child node the node was inserted before
- */
- "insert" : true,
- /**
- * @event beforeappend
- * Fires before a new child is appended, return false to cancel the append.
+ * Fires before a new child is appended to a node in this tree, return false to cancel the append.
* @param {Tree} tree The owner tree
- * @param {Node} this This node
+ * @param {Node} parent The parent node
* @param {Node} node The child node to be appended
*/
"beforeappend" : true,
/**
* @event beforeremove
- * Fires before a child is removed, return false to cancel the remove.
+ * Fires before a child is removed from a node in this tree, return false to cancel the remove.
* @param {Tree} tree The owner tree
- * @param {Node} this This node
+ * @param {Node} parent The parent node
* @param {Node} node The child node to be removed
*/
"beforeremove" : true,
/**
* @event beforemove
- * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
+ * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
* @param {Tree} tree The owner tree
- * @param {Node} this This node
- * @param {Node} oldParent The parent of this node
- * @param {Node} newParent The new parent this node is moving to
+ * @param {Node} node The node being moved
+ * @param {Node} oldParent The parent of the node
+ * @param {Node} newParent The new parent the node is moving to
* @param {Number} index The index it is being moved to
*/
"beforemove" : true,
/**
* @event beforeinsert
- * Fires before a new child is inserted, return false to cancel the insert.
+ * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
* @param {Tree} tree The owner tree
- * @param {Node} this This node
+ * @param {Node} parent The parent node
* @param {Node} node The child node to be inserted
* @param {Node} refNode The child node the node is being inserted before
*/
"beforeinsert" : true
});
- this.listeners = this.attributes.listeners;
- Roo.data.Node.superclass.constructor.call(this);
-};
-
-Roo.extend(Roo.data.Node, Roo.util.Observable, {
- fireEvent : function(evtName){
- // first do standard event for this node
- if(Roo.data.Node.superclass.fireEvent.apply(this, arguments) === false){
- return false;
- }
- // then bubble it up to the tree if the event wasn't cancelled
- var ot = this.getOwnerTree();
- if(ot){
- if(ot.proxyNodeEvent.apply(ot, arguments) === false){
- return false;
- }
- }
- return true;
- },
-
- /**
- * Returns true if this node is a leaf
- * @return {Boolean}
- */
- isLeaf : function(){
- return this.leaf === true;
- },
-
- // private
- setFirstChild : function(node){
- this.firstChild = node;
- },
-
- //private
- setLastChild : function(node){
- this.lastChild = node;
- },
-
-
- /**
- * Returns true if this node is the last child of its parent
- * @return {Boolean}
- */
- isLast : function(){
- return (!this.parentNode ? true : this.parentNode.lastChild == this);
- },
-
- /**
- * Returns true if this node is the first child of its parent
- * @return {Boolean}
- */
- isFirst : function(){
- return (!this.parentNode ? true : this.parentNode.firstChild == this);
- },
-
- hasChildNodes : function(){
- return !this.isLeaf() && this.childNodes.length > 0;
- },
-
- /**
- * Insert node(s) as the last child node of this node.
- * @param {Node/Array} node The node or Array of nodes to append
- * @return {Node} The appended node if single append, or null if an array was passed
- */
- appendChild : function(node){
- var multi = false;
- if(node instanceof Array){
- multi = node;
- }else if(arguments.length > 1){
- multi = arguments;
- }
- // if passed an array or multiple args do them one by one
- if(multi){
- for(var i = 0, len = multi.length; i < len; i++) {
- this.appendChild(multi[i]);
- }
- }else{
- if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
- return false;
- }
- var index = this.childNodes.length;
- var oldParent = node.parentNode;
- // it's a move, make sure we move it cleanly
- if(oldParent){
- if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
- return false;
- }
- oldParent.removeChild(node);
- }
- index = this.childNodes.length;
- if(index == 0){
- this.setFirstChild(node);
- }
- this.childNodes.push(node);
- node.parentNode = this;
- var ps = this.childNodes[index-1];
- if(ps){
- node.previousSibling = ps;
- ps.nextSibling = node;
- }else{
- node.previousSibling = null;
- }
- node.nextSibling = null;
- this.setLastChild(node);
- node.setOwnerTree(this.getOwnerTree());
- this.fireEvent("append", this.ownerTree, this, node, index);
- if(oldParent){
- node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
- }
- return node;
- }
- },
-
- /**
- * Removes a child node from this node.
- * @param {Node} node The node to remove
- * @return {Node} The removed node
- */
- removeChild : function(node){
- var index = this.childNodes.indexOf(node);
- if(index == -1){
- return false;
- }
- if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
- return false;
- }
-
- // remove it from childNodes collection
- this.childNodes.splice(index, 1);
-
- // update siblings
- if(node.previousSibling){
- node.previousSibling.nextSibling = node.nextSibling;
- }
- if(node.nextSibling){
- node.nextSibling.previousSibling = node.previousSibling;
- }
-
- // update child refs
- if(this.firstChild == node){
- this.setFirstChild(node.nextSibling);
- }
- if(this.lastChild == node){
- this.setLastChild(node.previousSibling);
- }
-
- node.setOwnerTree(null);
- // clear any references from the node
- node.parentNode = null;
- node.previousSibling = null;
- node.nextSibling = null;
- this.fireEvent("remove", this.ownerTree, this, node);
- return node;
- },
-
- /**
- * Inserts the first node before the second node in this nodes childNodes collection.
- * @param {Node} node The node to insert
- * @param {Node} refNode The node to insert before (if null the node is appended)
- * @return {Node} The inserted node
- */
- insertBefore : function(node, refNode){
- if(!refNode){ // like standard Dom, refNode can be null for append
- return this.appendChild(node);
- }
- // nothing to do
- if(node == refNode){
- return false;
- }
- if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
- return false;
- }
- var index = this.childNodes.indexOf(refNode);
- var oldParent = node.parentNode;
- var refIndex = index;
+ Roo.data.Tree.superclass.constructor.call(this);
+};
- // when moving internally, indexes will change after remove
- if(oldParent == this && this.childNodes.indexOf(node) < index){
- refIndex--;
- }
+Roo.extend(Roo.data.Tree, Roo.util.Observable, {
+ pathSeparator: "/",
- // it's a move, make sure we move it cleanly
- if(oldParent){
- if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
- return false;
- }
- oldParent.removeChild(node);
- }
- if(refIndex == 0){
- this.setFirstChild(node);
- }
- this.childNodes.splice(refIndex, 0, node);
- node.parentNode = this;
- var ps = this.childNodes[refIndex-1];
- if(ps){
- node.previousSibling = ps;
- ps.nextSibling = node;
- }else{
- node.previousSibling = null;
- }
- node.nextSibling = refNode;
- refNode.previousSibling = node;
- node.setOwnerTree(this.getOwnerTree());
- this.fireEvent("insert", this.ownerTree, this, node, refNode);
- if(oldParent){
- node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
- }
- return node;
+ proxyNodeEvent : function(){
+ return this.fireEvent.apply(this, arguments);
},
/**
- * Returns the child node at the specified index.
- * @param {Number} index
+ * Returns the root node for this tree.
* @return {Node}
*/
- item : function(index){
- return this.childNodes[index];
+ getRootNode : function(){
+ return this.root;
},
/**
- * Replaces one child node in this node with another.
- * @param {Node} newChild The replacement node
- * @param {Node} oldChild The node to replace
- * @return {Node} The replaced node
+ * Sets the root node for this tree.
+ * @param {Node} node
+ * @return {Node}
*/
- replaceChild : function(newChild, oldChild){
- this.insertBefore(newChild, oldChild);
- this.removeChild(oldChild);
- return oldChild;
+ setRootNode : function(node){
+ this.root = node;
+ node.ownerTree = this;
+ node.isRoot = true;
+ this.registerNode(node);
+ return node;
},
/**
- * Returns the index of a child node
- * @param {Node} node
- * @return {Number} The index of the node or -1 if it was not found
+ * Gets a node in this tree by its id.
+ * @param {String} id
+ * @return {Node}
*/
- indexOf : function(child){
- return this.childNodes.indexOf(child);
+ getNodeById : function(id){
+ return this.nodeHash[id];
},
- /**
- * Returns the tree this node is in.
- * @return {Tree}
- */
- getOwnerTree : function(){
- // if it doesn't have one, look for one
- if(!this.ownerTree){
- var p = this;
- while(p){
- if(p.ownerTree){
- this.ownerTree = p.ownerTree;
- break;
- }
- p = p.parentNode;
- }
- }
- return this.ownerTree;
+ registerNode : function(node){
+ this.nodeHash[node.id] = node;
},
- /**
- * Returns depth of this node (the root node has a depth of 0)
- * @return {Number}
- */
- getDepth : function(){
- var depth = 0;
- var p = this;
- while(p.parentNode){
- ++depth;
- p = p.parentNode;
- }
- return depth;
+ unregisterNode : function(node){
+ delete this.nodeHash[node.id];
},
- // private
- setOwnerTree : function(tree){
- // if it's move, we need to update everyone
- if(tree != this.ownerTree){
- if(this.ownerTree){
- this.ownerTree.unregisterNode(this);
- }
- this.ownerTree = tree;
- var cs = this.childNodes;
- for(var i = 0, len = cs.length; i < len; i++) {
- cs[i].setOwnerTree(tree);
- }
- if(tree){
- tree.registerNode(this);
- }
- }
- },
+ toString : function(){
+ return "[Tree"+(this.id?" "+this.id:"")+"]";
+ }
+});
+/**
+ * @class Roo.data.Node
+ * @extends Roo.util.Observable
+ * @cfg {Boolean} leaf true if this node is a leaf and does not have children
+ * @cfg {String} id The id for this node. If one is not specified, one is generated.
+ * @constructor
+ * @param {Object} attributes The attributes/config for the node
+ */
+Roo.data.Node = function(attributes){
/**
- * Returns the path for this node. The path can be used to expand or select this node programmatically.
- * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
- * @return {String} The path
+ * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
+ * @type {Object}
*/
- getPath : function(attr){
- attr = attr || "id";
- var p = this.parentNode;
- var b = [this.attributes[attr]];
- while(p){
- b.unshift(p.attributes[attr]);
- p = p.parentNode;
- }
- var sep = this.getOwnerTree().pathSeparator;
- return sep + b.join(sep);
- },
-
+ this.attributes = attributes || {};
+ this.leaf = this.attributes.leaf;
/**
- * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
- * function call will be the scope provided or the current node. The arguments to the function
- * will be the args provided or the current node. If the function returns false at any point,
- * the bubble is stopped.
- * @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope of the function (defaults to current node)
- * @param {Array} args (optional) The args to call the function with (default to passing the current node)
+ * The node id. @type String
*/
- bubble : function(fn, scope, args){
- var p = this;
- while(p){
- if(fn.call(scope || p, args || p) === false){
- break;
- }
- p = p.parentNode;
- }
- },
-
+ this.id = this.attributes.id;
+ if(!this.id){
+ this.id = Roo.id(null, "ynode-");
+ this.attributes.id = this.id;
+ }
+
+
/**
- * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
- * function call will be the scope provided or the current node. The arguments to the function
- * will be the args provided or the current node. If the function returns false at any point,
- * the cascade is stopped on that branch.
- * @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope of the function (defaults to current node)
- * @param {Array} args (optional) The args to call the function with (default to passing the current node)
+ * All child nodes of this node. @type Array
*/
- cascade : function(fn, scope, args){
- if(fn.call(scope || this, args || this) !== false){
- var cs = this.childNodes;
- for(var i = 0, len = cs.length; i < len; i++) {
- cs[i].cascade(fn, scope, args);
+ this.childNodes = [];
+ if(!this.childNodes.indexOf){ // indexOf is a must
+ this.childNodes.indexOf = function(o){
+ for(var i = 0, len = this.length; i < len; i++){
+ if(this[i] == o) {
+ return i;
+ }
}
- }
- },
-
+ return -1;
+ };
+ }
/**
- * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
- * function call will be the scope provided or the current node. The arguments to the function
- * will be the args provided or the current node. If the function returns false at any point,
- * the iteration stops.
- * @param {Function} fn The function to call
- * @param {Object} scope (optional) The scope of the function (defaults to current node)
- * @param {Array} args (optional) The args to call the function with (default to passing the current node)
+ * The parent node for this node. @type Node
*/
- eachChild : function(fn, scope, args){
- var cs = this.childNodes;
- for(var i = 0, len = cs.length; i < len; i++) {
- if(fn.call(scope || this, args || cs[i]) === false){
- break;
- }
- }
- },
-
+ this.parentNode = null;
/**
- * Finds the first child that has the attribute with the specified value.
- * @param {String} attribute The attribute name
- * @param {Mixed} value The value to search for
- * @return {Node} The found child or null if none was found
+ * The first direct child node of this node, or null if this node has no child nodes. @type Node
*/
- findChild : function(attribute, value){
- var cs = this.childNodes;
- for(var i = 0, len = cs.length; i < len; i++) {
- if(cs[i].attributes[attribute] == value){
- return cs[i];
- }
- }
- return null;
- },
+ this.firstChild = null;
+ /**
+ * The last direct child node of this node, or null if this node has no child nodes. @type Node
+ */
+ this.lastChild = null;
+ /**
+ * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
+ */
+ this.previousSibling = null;
+ /**
+ * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
+ */
+ this.nextSibling = null;
+
+ this.addEvents({
+ /**
+ * @event append
+ * Fires when a new child node is appended
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} node The newly appended node
+ * @param {Number} index The index of the newly appended node
+ */
+ "append" : true,
+ /**
+ * @event remove
+ * Fires when a child node is removed
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} node The removed node
+ */
+ "remove" : true,
+ /**
+ * @event move
+ * Fires when this node is moved to a new location in the tree
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} oldParent The old parent of this node
+ * @param {Node} newParent The new parent of this node
+ * @param {Number} index The index it was moved to
+ */
+ "move" : true,
+ /**
+ * @event insert
+ * Fires when a new child node is inserted.
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} node The child node inserted
+ * @param {Node} refNode The child node the node was inserted before
+ */
+ "insert" : true,
+ /**
+ * @event beforeappend
+ * Fires before a new child is appended, return false to cancel the append.
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} node The child node to be appended
+ */
+ "beforeappend" : true,
+ /**
+ * @event beforeremove
+ * Fires before a child is removed, return false to cancel the remove.
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} node The child node to be removed
+ */
+ "beforeremove" : true,
+ /**
+ * @event beforemove
+ * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} oldParent The parent of this node
+ * @param {Node} newParent The new parent this node is moving to
+ * @param {Number} index The index it is being moved to
+ */
+ "beforemove" : true,
+ /**
+ * @event beforeinsert
+ * Fires before a new child is inserted, return false to cancel the insert.
+ * @param {Tree} tree The owner tree
+ * @param {Node} this This node
+ * @param {Node} node The child node to be inserted
+ * @param {Node} refNode The child node the node is being inserted before
+ */
+ "beforeinsert" : true
+ });
+ this.listeners = this.attributes.listeners;
+ Roo.data.Node.superclass.constructor.call(this);
+};
- /**
- * Finds the first child by a custom function. The child matches if the function passed
- * returns true.
- * @param {Function} fn
- * @param {Object} scope (optional)
- * @return {Node} The found child or null if none was found
- */
- findChildBy : function(fn, scope){
- var cs = this.childNodes;
- for(var i = 0, len = cs.length; i < len; i++) {
- if(fn.call(scope||cs[i], cs[i]) === true){
- return cs[i];
- }
+Roo.extend(Roo.data.Node, Roo.util.Observable, {
+ fireEvent : function(evtName){
+ // first do standard event for this node
+ if(Roo.data.Node.superclass.fireEvent.apply(this, arguments) === false){
+ return false;
}
- return null;
- },
-
- /**
- * Sorts this nodes children using the supplied sort function
- * @param {Function} fn
- * @param {Object} scope (optional)
- */
- sort : function(fn, scope){
- var cs = this.childNodes;
- var len = cs.length;
- if(len > 0){
- var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
- cs.sort(sortFn);
- for(var i = 0; i < len; i++){
- var n = cs[i];
- n.previousSibling = cs[i-1];
- n.nextSibling = cs[i+1];
- if(i == 0){
- this.setFirstChild(n);
- }
- if(i == len-1){
- this.setLastChild(n);
- }
+ // then bubble it up to the tree if the event wasn't cancelled
+ var ot = this.getOwnerTree();
+ if(ot){
+ if(ot.proxyNodeEvent.apply(ot, arguments) === false){
+ return false;
}
}
+ return true;
},
/**
- * Returns true if this node is an ancestor (at any point) of the passed node.
- * @param {Node} node
+ * Returns true if this node is a leaf
* @return {Boolean}
*/
- contains : function(node){
- return node.isAncestor(this);
+ isLeaf : function(){
+ return this.leaf === true;
},
- /**
- * Returns true if the passed node is an ancestor (at any point) of this node.
- * @param {Node} node
- * @return {Boolean}
- */
- isAncestor : function(node){
- var p = this.parentNode;
- while(p){
- if(p == node){
- return true;
- }
- p = p.parentNode;
- }
- return false;
+ // private
+ setFirstChild : function(node){
+ this.firstChild = node;
+ },
+
+ //private
+ setLastChild : function(node){
+ this.lastChild = node;
},
- toString : function(){
- return "[Node"+(this.id?" "+this.id:"")+"]";
- }
-});/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-
-
-/**
- * @class Roo.ComponentMgr
- * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
- * @singleton
- */
-Roo.ComponentMgr = function(){
- var all = new Roo.util.MixedCollection();
-
- return {
- /**
- * Registers a component.
- * @param {Roo.Component} c The component
- */
- register : function(c){
- all.add(c);
- },
-
- /**
- * Unregisters a component.
- * @param {Roo.Component} c The component
- */
- unregister : function(c){
- all.remove(c);
- },
-
- /**
- * Returns a component by id
- * @param {String} id The component id
- */
- get : function(id){
- return all.get(id);
- },
-
- /**
- * Registers a function that will be called when a specified component is added to ComponentMgr
- * @param {String} id The component id
- * @param {Funtction} fn The callback function
- * @param {Object} scope The scope of the callback
- */
- onAvailable : function(id, fn, scope){
- all.on("add", function(index, o){
- if(o.id == id){
- fn.call(scope || o, o);
- all.un("add", fn, scope);
- }
- });
- }
- };
-}();/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-
-/**
- * @class Roo.Component
- * @extends Roo.util.Observable
- * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
- * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
- * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
- * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
- * All visual components (widgets) that require rendering into a layout should subclass Component.
- * @constructor
- * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
- * 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
- * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
- */
-Roo.Component = function(config){
- config = config || {};
- if(config.tagName || config.dom || typeof config == "string"){ // element object
- config = {el: config, id: config.id || config};
- }
- this.initialConfig = config;
-
- Roo.apply(this, config);
- this.addEvents({
- /**
- * @event disable
- * Fires after the component is disabled.
- * @param {Roo.Component} this
- */
- disable : true,
- /**
- * @event enable
- * Fires after the component is enabled.
- * @param {Roo.Component} this
- */
- enable : true,
- /**
- * @event beforeshow
- * Fires before the component is shown. Return false to stop the show.
- * @param {Roo.Component} this
- */
- beforeshow : true,
- /**
- * @event show
- * Fires after the component is shown.
- * @param {Roo.Component} this
- */
- show : true,
- /**
- * @event beforehide
- * Fires before the component is hidden. Return false to stop the hide.
- * @param {Roo.Component} this
- */
- beforehide : true,
- /**
- * @event hide
- * Fires after the component is hidden.
- * @param {Roo.Component} this
- */
- hide : true,
- /**
- * @event beforerender
- * Fires before the component is rendered. Return false to stop the render.
- * @param {Roo.Component} this
- */
- beforerender : true,
- /**
- * @event render
- * Fires after the component is rendered.
- * @param {Roo.Component} this
- */
- render : true,
- /**
- * @event beforedestroy
- * Fires before the component is destroyed. Return false to stop the destroy.
- * @param {Roo.Component} this
- */
- beforedestroy : true,
- /**
- * @event destroy
- * Fires after the component is destroyed.
- * @param {Roo.Component} this
- */
- destroy : true
- });
- if(!this.id){
- this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
- }
- Roo.ComponentMgr.register(this);
- Roo.Component.superclass.constructor.call(this);
- this.initComponent();
- if(this.renderTo){ // not supported by all components yet. use at your own risk!
- this.render(this.renderTo);
- delete this.renderTo;
- }
-};
-
-/** @private */
-Roo.Component.AUTO_ID = 1000;
-Roo.extend(Roo.Component, Roo.util.Observable, {
- /**
- * @scope Roo.Component.prototype
- * @type {Boolean}
- * true if this component is hidden. Read-only.
- */
- hidden : false,
- /**
- * @type {Boolean}
- * true if this component is disabled. Read-only.
- */
- disabled : false,
/**
- * @type {Boolean}
- * true if this component has been rendered. Read-only.
- */
- rendered : false,
-
- /** @cfg {String} disableClass
- * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
- */
- disabledClass : "x-item-disabled",
- /** @cfg {Boolean} allowDomMove
- * Whether the component can move the Dom node when rendering (defaults to true).
- */
- allowDomMove : true,
- /** @cfg {String} hideMode
- * How this component should hidden. Supported values are
- * "visibility" (css visibility), "offsets" (negative offset position) and
- * "display" (css display) - defaults to "display".
+ * Returns true if this node is the last child of its parent
+ * @return {Boolean}
*/
- hideMode: 'display',
-
- /** @private */
- ctype : "Roo.Component",
+ isLast : function(){
+ return (!this.parentNode ? true : this.parentNode.lastChild == this);
+ },
/**
- * @cfg {String} actionMode
- * which property holds the element that used for hide() / show() / disable() / enable()
- * default is 'el'
+ * Returns true if this node is the first child of its parent
+ * @return {Boolean}
*/
- actionMode : "el",
+ isFirst : function(){
+ return (!this.parentNode ? true : this.parentNode.firstChild == this);
+ },
- /** @private */
- getActionEl : function(){
- return this[this.actionMode];
+ hasChildNodes : function(){
+ return !this.isLeaf() && this.childNodes.length > 0;
},
- initComponent : Roo.emptyFn,
/**
- * If this is a lazy rendering component, render it to its container element.
- * @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.
+ * Insert node(s) as the last child node of this node.
+ * @param {Node/Array} node The node or Array of nodes to append
+ * @return {Node} The appended node if single append, or null if an array was passed
*/
- render : function(container, position){
- if(!this.rendered && this.fireEvent("beforerender", this) !== false){
- if(!container && this.el){
- this.el = Roo.get(this.el);
- container = this.el.dom.parentNode;
- this.allowDomMove = false;
+ appendChild : function(node){
+ var multi = false;
+ if(node instanceof Array){
+ multi = node;
+ }else if(arguments.length > 1){
+ multi = arguments;
+ }
+ // if passed an array or multiple args do them one by one
+ if(multi){
+ for(var i = 0, len = multi.length; i < len; i++) {
+ this.appendChild(multi[i]);
}
- this.container = Roo.get(container);
- this.rendered = true;
- if(position !== undefined){
- if(typeof position == 'number'){
- position = this.container.dom.childNodes[position];
- }else{
- position = Roo.getDom(position);
- }
+ }else{
+ if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
+ return false;
}
- this.onRender(this.container, position || null);
- if(this.cls){
- this.el.addClass(this.cls);
- delete this.cls;
+ var index = this.childNodes.length;
+ var oldParent = node.parentNode;
+ // it's a move, make sure we move it cleanly
+ if(oldParent){
+ if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
+ return false;
+ }
+ oldParent.removeChild(node);
}
- if(this.style){
- this.el.applyStyles(this.style);
- delete this.style;
+ index = this.childNodes.length;
+ if(index == 0){
+ this.setFirstChild(node);
}
- this.fireEvent("render", this);
- this.afterRender(this.container);
- if(this.hidden){
- this.hide();
+ this.childNodes.push(node);
+ node.parentNode = this;
+ var ps = this.childNodes[index-1];
+ if(ps){
+ node.previousSibling = ps;
+ ps.nextSibling = node;
+ }else{
+ node.previousSibling = null;
}
- if(this.disabled){
- this.disable();
+ node.nextSibling = null;
+ this.setLastChild(node);
+ node.setOwnerTree(this.getOwnerTree());
+ this.fireEvent("append", this.ownerTree, this, node, index);
+ if(oldParent){
+ node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
}
+ return node;
}
- return this;
},
- /** @private */
- // default function is not really useful
- onRender : function(ct, position){
- if(this.el){
- this.el = Roo.get(this.el);
- if(this.allowDomMove !== false){
- ct.dom.insertBefore(this.el.dom, position);
- }
+ /**
+ * Removes a child node from this node.
+ * @param {Node} node The node to remove
+ * @return {Node} The removed node
+ */
+ removeChild : function(node){
+ var index = this.childNodes.indexOf(node);
+ if(index == -1){
+ return false;
+ }
+ if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
+ return false;
}
- },
- /** @private */
- getAutoCreate : function(){
- var cfg = typeof this.autoCreate == "object" ?
- this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
- if(this.id && !cfg.id){
- cfg.id = this.id;
+ // remove it from childNodes collection
+ this.childNodes.splice(index, 1);
+
+ // update siblings
+ if(node.previousSibling){
+ node.previousSibling.nextSibling = node.nextSibling;
+ }
+ if(node.nextSibling){
+ node.nextSibling.previousSibling = node.previousSibling;
}
- return cfg;
- },
- /** @private */
- afterRender : Roo.emptyFn,
+ // update child refs
+ if(this.firstChild == node){
+ this.setFirstChild(node.nextSibling);
+ }
+ if(this.lastChild == node){
+ this.setLastChild(node.previousSibling);
+ }
+
+ node.setOwnerTree(null);
+ // clear any references from the node
+ node.parentNode = null;
+ node.previousSibling = null;
+ node.nextSibling = null;
+ this.fireEvent("remove", this.ownerTree, this, node);
+ return node;
+ },
/**
- * Destroys this component by purging any event listeners, removing the component's element from the DOM,
- * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
+ * Inserts the first node before the second node in this nodes childNodes collection.
+ * @param {Node} node The node to insert
+ * @param {Node} refNode The node to insert before (if null the node is appended)
+ * @return {Node} The inserted node
*/
- destroy : function(){
- if(this.fireEvent("beforedestroy", this) !== false){
- this.purgeListeners();
- this.beforeDestroy();
- if(this.rendered){
- this.el.removeAllListeners();
- this.el.remove();
- if(this.actionMode == "container"){
- this.container.remove();
- }
- }
- this.onDestroy();
- Roo.ComponentMgr.unregister(this);
- this.fireEvent("destroy", this);
+ insertBefore : function(node, refNode){
+ if(!refNode){ // like standard Dom, refNode can be null for append
+ return this.appendChild(node);
+ }
+ // nothing to do
+ if(node == refNode){
+ return false;
}
- },
- /** @private */
- beforeDestroy : function(){
+ if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
+ return false;
+ }
+ var index = this.childNodes.indexOf(refNode);
+ var oldParent = node.parentNode;
+ var refIndex = index;
- },
+ // when moving internally, indexes will change after remove
+ if(oldParent == this && this.childNodes.indexOf(node) < index){
+ refIndex--;
+ }
- /** @private */
- onDestroy : function(){
+ // it's a move, make sure we move it cleanly
+ if(oldParent){
+ if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
+ return false;
+ }
+ oldParent.removeChild(node);
+ }
+ if(refIndex == 0){
+ this.setFirstChild(node);
+ }
+ this.childNodes.splice(refIndex, 0, node);
+ node.parentNode = this;
+ var ps = this.childNodes[refIndex-1];
+ if(ps){
+ node.previousSibling = ps;
+ ps.nextSibling = node;
+ }else{
+ node.previousSibling = null;
+ }
+ node.nextSibling = refNode;
+ refNode.previousSibling = node;
+ node.setOwnerTree(this.getOwnerTree());
+ this.fireEvent("insert", this.ownerTree, this, node, refNode);
+ if(oldParent){
+ node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
+ }
+ return node;
+ },
+ /**
+ * Returns the child node at the specified index.
+ * @param {Number} index
+ * @return {Node}
+ */
+ item : function(index){
+ return this.childNodes[index];
},
/**
- * Returns the underlying {@link Roo.Element}.
- * @return {Roo.Element} The element
+ * Replaces one child node in this node with another.
+ * @param {Node} newChild The replacement node
+ * @param {Node} oldChild The node to replace
+ * @return {Node} The replaced node
*/
- getEl : function(){
- return this.el;
+ replaceChild : function(newChild, oldChild){
+ this.insertBefore(newChild, oldChild);
+ this.removeChild(oldChild);
+ return oldChild;
},
/**
- * Returns the id of this component.
- * @return {String}
+ * Returns the index of a child node
+ * @param {Node} node
+ * @return {Number} The index of the node or -1 if it was not found
*/
- getId : function(){
- return this.id;
+ indexOf : function(child){
+ return this.childNodes.indexOf(child);
},
/**
- * Try to focus this component.
- * @param {Boolean} selectText True to also select the text in this component (if applicable)
- * @return {Roo.Component} this
+ * Returns the tree this node is in.
+ * @return {Tree}
*/
- focus : function(selectText){
- if(this.rendered){
- this.el.focus();
- if(selectText === true){
- this.el.dom.select();
+ getOwnerTree : function(){
+ // if it doesn't have one, look for one
+ if(!this.ownerTree){
+ var p = this;
+ while(p){
+ if(p.ownerTree){
+ this.ownerTree = p.ownerTree;
+ break;
+ }
+ p = p.parentNode;
}
}
- return this;
- },
-
- /** @private */
- blur : function(){
- if(this.rendered){
- this.el.blur();
- }
- return this;
+ return this.ownerTree;
},
/**
- * Disable this component.
- * @return {Roo.Component} this
+ * Returns depth of this node (the root node has a depth of 0)
+ * @return {Number}
*/
- disable : function(){
- if(this.rendered){
- this.onDisable();
+ getDepth : function(){
+ var depth = 0;
+ var p = this;
+ while(p.parentNode){
+ ++depth;
+ p = p.parentNode;
}
- this.disabled = true;
- this.fireEvent("disable", this);
- return this;
+ return depth;
},
- // private
- onDisable : function(){
- this.getActionEl().addClass(this.disabledClass);
- this.el.dom.disabled = true;
+ // private
+ setOwnerTree : function(tree){
+ // if it's move, we need to update everyone
+ if(tree != this.ownerTree){
+ if(this.ownerTree){
+ this.ownerTree.unregisterNode(this);
+ }
+ this.ownerTree = tree;
+ var cs = this.childNodes;
+ for(var i = 0, len = cs.length; i < len; i++) {
+ cs[i].setOwnerTree(tree);
+ }
+ if(tree){
+ tree.registerNode(this);
+ }
+ }
},
/**
- * Enable this component.
- * @return {Roo.Component} this
+ * Returns the path for this node. The path can be used to expand or select this node programmatically.
+ * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
+ * @return {String} The path
*/
- enable : function(){
- if(this.rendered){
- this.onEnable();
+ getPath : function(attr){
+ attr = attr || "id";
+ var p = this.parentNode;
+ var b = [this.attributes[attr]];
+ while(p){
+ b.unshift(p.attributes[attr]);
+ p = p.parentNode;
}
- this.disabled = false;
- this.fireEvent("enable", this);
- return this;
+ var sep = this.getOwnerTree().pathSeparator;
+ return sep + b.join(sep);
},
- // private
- onEnable : function(){
- this.getActionEl().removeClass(this.disabledClass);
- this.el.dom.disabled = false;
+ /**
+ * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
+ * function call will be the scope provided or the current node. The arguments to the function
+ * will be the args provided or the current node. If the function returns false at any point,
+ * the bubble is stopped.
+ * @param {Function} fn The function to call
+ * @param {Object} scope (optional) The scope of the function (defaults to current node)
+ * @param {Array} args (optional) The args to call the function with (default to passing the current node)
+ */
+ bubble : function(fn, scope, args){
+ var p = this;
+ while(p){
+ if(fn.call(scope || p, args || p) === false){
+ break;
+ }
+ p = p.parentNode;
+ }
},
/**
- * Convenience function for setting disabled/enabled by boolean.
- * @param {Boolean} disabled
+ * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
+ * function call will be the scope provided or the current node. The arguments to the function
+ * will be the args provided or the current node. If the function returns false at any point,
+ * the cascade is stopped on that branch.
+ * @param {Function} fn The function to call
+ * @param {Object} scope (optional) The scope of the function (defaults to current node)
+ * @param {Array} args (optional) The args to call the function with (default to passing the current node)
*/
- setDisabled : function(disabled){
- this[disabled ? "disable" : "enable"]();
+ cascade : function(fn, scope, args){
+ if(fn.call(scope || this, args || this) !== false){
+ var cs = this.childNodes;
+ for(var i = 0, len = cs.length; i < len; i++) {
+ cs[i].cascade(fn, scope, args);
+ }
+ }
},
/**
- * Show this component.
- * @return {Roo.Component} this
+ * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
+ * function call will be the scope provided or the current node. The arguments to the function
+ * will be the args provided or the current node. If the function returns false at any point,
+ * the iteration stops.
+ * @param {Function} fn The function to call
+ * @param {Object} scope (optional) The scope of the function (defaults to current node)
+ * @param {Array} args (optional) The args to call the function with (default to passing the current node)
*/
- show: function(){
- if(this.fireEvent("beforeshow", this) !== false){
- this.hidden = false;
- if(this.rendered){
- this.onShow();
- }
- this.fireEvent("show", this);
+ eachChild : function(fn, scope, args){
+ var cs = this.childNodes;
+ for(var i = 0, len = cs.length; i < len; i++) {
+ if(fn.call(scope || this, args || cs[i]) === false){
+ break;
+ }
}
- return this;
},
- // private
- onShow : function(){
- var ae = this.getActionEl();
- if(this.hideMode == 'visibility'){
- ae.dom.style.visibility = "visible";
- }else if(this.hideMode == 'offsets'){
- ae.removeClass('x-hidden');
- }else{
- ae.dom.style.display = "";
+ /**
+ * Finds the first child that has the attribute with the specified value.
+ * @param {String} attribute The attribute name
+ * @param {Mixed} value The value to search for
+ * @return {Node} The found child or null if none was found
+ */
+ findChild : function(attribute, value){
+ var cs = this.childNodes;
+ for(var i = 0, len = cs.length; i < len; i++) {
+ if(cs[i].attributes[attribute] == value){
+ return cs[i];
+ }
}
+ return null;
},
/**
- * Hide this component.
- * @return {Roo.Component} this
+ * Finds the first child by a custom function. The child matches if the function passed
+ * returns true.
+ * @param {Function} fn
+ * @param {Object} scope (optional)
+ * @return {Node} The found child or null if none was found
*/
- hide: function(){
- if(this.fireEvent("beforehide", this) !== false){
- this.hidden = true;
- if(this.rendered){
- this.onHide();
- }
- this.fireEvent("hide", this);
+ findChildBy : function(fn, scope){
+ var cs = this.childNodes;
+ for(var i = 0, len = cs.length; i < len; i++) {
+ if(fn.call(scope||cs[i], cs[i]) === true){
+ return cs[i];
+ }
}
- return this;
+ return null;
},
- // private
- onHide : function(){
- var ae = this.getActionEl();
- if(this.hideMode == 'visibility'){
- ae.dom.style.visibility = "hidden";
- }else if(this.hideMode == 'offsets'){
- ae.addClass('x-hidden');
- }else{
- ae.dom.style.display = "none";
+ /**
+ * Sorts this nodes children using the supplied sort function
+ * @param {Function} fn
+ * @param {Object} scope (optional)
+ */
+ sort : function(fn, scope){
+ var cs = this.childNodes;
+ var len = cs.length;
+ if(len > 0){
+ var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
+ cs.sort(sortFn);
+ for(var i = 0; i < len; i++){
+ var n = cs[i];
+ n.previousSibling = cs[i-1];
+ n.nextSibling = cs[i+1];
+ if(i == 0){
+ this.setFirstChild(n);
+ }
+ if(i == len-1){
+ this.setLastChild(n);
+ }
+ }
}
},
/**
- * Convenience function to hide or show this component by boolean.
- * @param {Boolean} visible True to show, false to hide
- * @return {Roo.Component} this
+ * Returns true if this node is an ancestor (at any point) of the passed node.
+ * @param {Node} node
+ * @return {Boolean}
*/
- setVisible: function(visible){
- if(visible) {
- this.show();
- }else{
- this.hide();
- }
- return this;
+ contains : function(node){
+ return node.isAncestor(this);
},
/**
- * Returns true if this component is visible.
+ * Returns true if the passed node is an ancestor (at any point) of this node.
+ * @param {Node} node
+ * @return {Boolean}
*/
- isVisible : function(){
- return this.getActionEl().isVisible();
+ isAncestor : function(node){
+ var p = this.parentNode;
+ while(p){
+ if(p == node){
+ return true;
+ }
+ p = p.parentNode;
+ }
+ return false;
},
- cloneConfig : function(overrides){
- overrides = overrides || {};
- var id = overrides.id || Roo.id();
- var cfg = Roo.applyIf(overrides, this.initialConfig);
- cfg.id = id; // prevent dup id
- return new this.constructor(cfg);
+ toString : function(){
+ return "[Node"+(this.id?" "+this.id:"")+"]";
}
});/*
* Based on:
a.h -= (this.offset + rad);
a.h += 1;
}
- break;
- };
-
- this.adjusts = a;
-};
-
-Roo.Shadow.prototype = {
- /**
- * @cfg {String} mode
- * The shadow display mode. Supports the following options:<br />
- * sides: Shadow displays on both sides and bottom only<br />
- * frame: Shadow displays equally on all four sides<br />
- * drop: Traditional bottom-right drop shadow (default)
- */
- /**
- * @cfg {String} offset
- * The number of pixels to offset the shadow from the element (defaults to 4)
- */
- offset: 4,
-
- // private
- defaultMode: "drop",
-
- /**
- * Displays the shadow under the target element
- * @param {String/HTMLElement/Element} targetEl The id or element under which the shadow should display
- */
- show : function(target){
- target = Roo.get(target);
- if(!this.el){
- this.el = Roo.Shadow.Pool.pull();
- if(this.el.dom.nextSibling != target.dom){
- this.el.insertBefore(target);
- }
- }
- this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
- if(Roo.isIE){
- this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
- }
- this.realign(
- target.getLeft(true),
- target.getTop(true),
- target.getWidth(),
- target.getHeight()
- );
- this.el.dom.style.display = "block";
- },
-
- /**
- * Returns true if the shadow is visible, else false
- */
- isVisible : function(){
- return this.el ? true : false;
- },
-
- /**
- * Direct alignment when values are already available. Show must be called at least once before
- * calling this method to ensure it is initialized.
- * @param {Number} left The target element left position
- * @param {Number} top The target element top position
- * @param {Number} width The target element width
- * @param {Number} height The target element height
- */
- realign : function(l, t, w, h){
- if(!this.el){
- return;
- }
- var a = this.adjusts, d = this.el.dom, s = d.style;
- var iea = 0;
- s.left = (l+a.l)+"px";
- s.top = (t+a.t)+"px";
- var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
-
- if(s.width != sws || s.height != shs){
- s.width = sws;
- s.height = shs;
- if(!Roo.isIE){
- var cn = d.childNodes;
- var sww = Math.max(0, (sw-12))+"px";
- cn[0].childNodes[1].style.width = sww;
- cn[1].childNodes[1].style.width = sww;
- cn[2].childNodes[1].style.width = sww;
- cn[1].style.height = Math.max(0, (sh-12))+"px";
- }
- }
- },
-
- /**
- * Hides this shadow
- */
- hide : function(){
- if(this.el){
- this.el.dom.style.display = "none";
- Roo.Shadow.Pool.push(this.el);
- delete this.el;
- }
- },
-
- /**
- * Adjust the z-index of this shadow
- * @param {Number} zindex The new z-index
- */
- setZIndex : function(z){
- this.zIndex = z;
- if(this.el){
- this.el.setStyle("z-index", z);
- }
- }
-};
-
-// Private utility class that manages the internal Shadow cache
-Roo.Shadow.Pool = function(){
- var p = [];
- var markup = Roo.isIE ?
- '<div class="x-ie-shadow"></div>' :
- '<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>';
- return {
- pull : function(){
- var sh = p.shift();
- if(!sh){
- sh = Roo.get(Roo.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
- sh.autoBoxAdjust = false;
- }
- return sh;
- },
-
- push : function(sh){
- p.push(sh);
- }
- };
-}();/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-
-/**
- * @class Roo.BoxComponent
- * @extends Roo.Component
- * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
- * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
- * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
- * layout containers.
- * @constructor
- * @param {Roo.Element/String/Object} config The configuration options.
- */
-Roo.BoxComponent = function(config){
- Roo.Component.call(this, config);
- this.addEvents({
- /**
- * @event resize
- * Fires after the component is resized.
- * @param {Roo.Component} this
- * @param {Number} adjWidth The box-adjusted width that was set
- * @param {Number} adjHeight The box-adjusted height that was set
- * @param {Number} rawWidth The width that was originally specified
- * @param {Number} rawHeight The height that was originally specified
- */
- resize : true,
- /**
- * @event move
- * Fires after the component is moved.
- * @param {Roo.Component} this
- * @param {Number} x The new x position
- * @param {Number} y The new y position
- */
- move : true
- });
-};
-
-Roo.extend(Roo.BoxComponent, Roo.Component, {
- // private, set in afterRender to signify that the component has been rendered
- boxReady : false,
- // private, used to defer height settings to subclasses
- deferHeight: false,
- /** @cfg {Number} width
- * width (optional) size of component
- */
- /** @cfg {Number} height
- * height (optional) size of component
- */
-
- /**
- * Sets the width and height of the component. This method fires the resize event. This method can accept
- * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
- * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
- * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
- * @return {Roo.BoxComponent} this
- */
- setSize : function(w, h){
- // support for standard size objects
- if(typeof w == 'object'){
- h = w.height;
- w = w.width;
- }
- // not rendered
- if(!this.boxReady){
- this.width = w;
- this.height = h;
- return this;
- }
-
- // prevent recalcs when not needed
- if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
- return this;
- }
- this.lastSize = {width: w, height: h};
-
- var adj = this.adjustSize(w, h);
- var aw = adj.width, ah = adj.height;
- if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
- var rz = this.getResizeEl();
- if(!this.deferHeight && aw !== undefined && ah !== undefined){
- rz.setSize(aw, ah);
- }else if(!this.deferHeight && ah !== undefined){
- rz.setHeight(ah);
- }else if(aw !== undefined){
- rz.setWidth(aw);
- }
- this.onResize(aw, ah, w, h);
- this.fireEvent('resize', this, aw, ah, w, h);
- }
- return this;
- },
+ break;
+ };
+
+ this.adjusts = a;
+};
+Roo.Shadow.prototype = {
/**
- * Gets the current size of the component's underlying element.
- * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
+ * @cfg {String} mode
+ * The shadow display mode. Supports the following options:<br />
+ * sides: Shadow displays on both sides and bottom only<br />
+ * frame: Shadow displays equally on all four sides<br />
+ * drop: Traditional bottom-right drop shadow (default)
*/
- getSize : function(){
- return this.el.getSize();
- },
-
/**
- * Gets the current XY position of the component's underlying element.
- * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
- * @return {Array} The XY position of the element (e.g., [100, 200])
+ * @cfg {String} offset
+ * The number of pixels to offset the shadow from the element (defaults to 4)
*/
- getPosition : function(local){
- if(local === true){
- return [this.el.getLeft(true), this.el.getTop(true)];
- }
- return this.xy || this.el.getXY();
- },
+ offset: 4,
+
+ // private
+ defaultMode: "drop",
/**
- * Gets the current box measurements of the component's underlying element.
- * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
- * @returns {Object} box An object in the format {x, y, width, height}
+ * Displays the shadow under the target element
+ * @param {String/HTMLElement/Element} targetEl The id or element under which the shadow should display
*/
- getBox : function(local){
- var s = this.el.getSize();
- if(local){
- s.x = this.el.getLeft(true);
- s.y = this.el.getTop(true);
- }else{
- var xy = this.xy || this.el.getXY();
- s.x = xy[0];
- s.y = xy[1];
+ show : function(target){
+ target = Roo.get(target);
+ if(!this.el){
+ this.el = Roo.Shadow.Pool.pull();
+ if(this.el.dom.nextSibling != target.dom){
+ this.el.insertBefore(target);
+ }
}
- return s;
+ this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
+ if(Roo.isIE){
+ this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
+ }
+ this.realign(
+ target.getLeft(true),
+ target.getTop(true),
+ target.getWidth(),
+ target.getHeight()
+ );
+ this.el.dom.style.display = "block";
},
/**
- * Sets the current box measurements of the component's underlying element.
- * @param {Object} box An object in the format {x, y, width, height}
- * @returns {Roo.BoxComponent} this
+ * Returns true if the shadow is visible, else false
*/
- updateBox : function(box){
- this.setSize(box.width, box.height);
- this.setPagePosition(box.x, box.y);
- return this;
- },
-
- // protected
- getResizeEl : function(){
- return this.resizeEl || this.el;
- },
-
- // protected
- getPositionEl : function(){
- return this.positionEl || this.el;
+ isVisible : function(){
+ return this.el ? true : false;
},
/**
- * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
- * This method fires the move event.
- * @param {Number} left The new left
- * @param {Number} top The new top
- * @returns {Roo.BoxComponent} this
+ * Direct alignment when values are already available. Show must be called at least once before
+ * calling this method to ensure it is initialized.
+ * @param {Number} left The target element left position
+ * @param {Number} top The target element top position
+ * @param {Number} width The target element width
+ * @param {Number} height The target element height
*/
- setPosition : function(x, y){
- this.x = x;
- this.y = y;
- if(!this.boxReady){
- return this;
+ realign : function(l, t, w, h){
+ if(!this.el){
+ return;
}
- var adj = this.adjustPosition(x, y);
- var ax = adj.x, ay = adj.y;
-
- var el = this.getPositionEl();
- if(ax !== undefined || ay !== undefined){
- if(ax !== undefined && ay !== undefined){
- el.setLeftTop(ax, ay);
- }else if(ax !== undefined){
- el.setLeft(ax);
- }else if(ay !== undefined){
- el.setTop(ay);
+ var a = this.adjusts, d = this.el.dom, s = d.style;
+ var iea = 0;
+ s.left = (l+a.l)+"px";
+ s.top = (t+a.t)+"px";
+ var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
+
+ if(s.width != sws || s.height != shs){
+ s.width = sws;
+ s.height = shs;
+ if(!Roo.isIE){
+ var cn = d.childNodes;
+ var sww = Math.max(0, (sw-12))+"px";
+ cn[0].childNodes[1].style.width = sww;
+ cn[1].childNodes[1].style.width = sww;
+ cn[2].childNodes[1].style.width = sww;
+ cn[1].style.height = Math.max(0, (sh-12))+"px";
}
- this.onPosition(ax, ay);
- this.fireEvent('move', this, ax, ay);
}
- return this;
},
/**
- * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
- * This method fires the move event.
- * @param {Number} x The new x position
- * @param {Number} y The new y position
- * @returns {Roo.BoxComponent} this
+ * Hides this shadow
*/
- setPagePosition : function(x, y){
- this.pageX = x;
- this.pageY = y;
- if(!this.boxReady){
- return;
- }
- if(x === undefined || y === undefined){ // cannot translate undefined points
- return;
- }
- var p = this.el.translatePoints(x, y);
- this.setPosition(p.left, p.top);
- return this;
- },
-
- // private
- onRender : function(ct, position){
- Roo.BoxComponent.superclass.onRender.call(this, ct, position);
- if(this.resizeEl){
- this.resizeEl = Roo.get(this.resizeEl);
- }
- if(this.positionEl){
- this.positionEl = Roo.get(this.positionEl);
- }
- },
-
- // private
- afterRender : function(){
- Roo.BoxComponent.superclass.afterRender.call(this);
- this.boxReady = true;
- this.setSize(this.width, this.height);
- if(this.x || this.y){
- this.setPosition(this.x, this.y);
- }
- if(this.pageX || this.pageY){
- this.setPagePosition(this.pageX, this.pageY);
+ hide : function(){
+ if(this.el){
+ this.el.dom.style.display = "none";
+ Roo.Shadow.Pool.push(this.el);
+ delete this.el;
}
},
/**
- * Force the component's size to recalculate based on the underlying element's current height and width.
- * @returns {Roo.BoxComponent} this
- */
- syncSize : function(){
- delete this.lastSize;
- this.setSize(this.el.getWidth(), this.el.getHeight());
- return this;
- },
-
- /**
- * Called after the component is resized, this method is empty by default but can be implemented by any
- * subclass that needs to perform custom logic after a resize occurs.
- * @param {Number} adjWidth The box-adjusted width that was set
- * @param {Number} adjHeight The box-adjusted height that was set
- * @param {Number} rawWidth The width that was originally specified
- * @param {Number} rawHeight The height that was originally specified
- */
- onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
-
- },
-
- /**
- * Called after the component is moved, this method is empty by default but can be implemented by any
- * subclass that needs to perform custom logic after a move occurs.
- * @param {Number} x The new x position
- * @param {Number} y The new y position
+ * Adjust the z-index of this shadow
+ * @param {Number} zindex The new z-index
*/
- onPosition : function(x, y){
+ setZIndex : function(z){
+ this.zIndex = z;
+ if(this.el){
+ this.el.setStyle("z-index", z);
+ }
+ }
+};
- },
+// Private utility class that manages the internal Shadow cache
+Roo.Shadow.Pool = function(){
+ var p = [];
+ var markup = Roo.isIE ?
+ '<div class="x-ie-shadow"></div>' :
+ '<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>';
+ return {
+ pull : function(){
+ var sh = p.shift();
+ if(!sh){
+ sh = Roo.get(Roo.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
+ sh.autoBoxAdjust = false;
+ }
+ return sh;
+ },
- // private
- adjustSize : function(w, h){
- if(this.autoWidth){
- w = 'auto';
- }
- if(this.autoHeight){
- h = 'auto';
+ push : function(sh){
+ p.push(sh);
}
- return {width : w, height: h};
- },
-
- // private
- adjustPosition : function(x, y){
- return {x : x, y: y};
- }
-});/*
+ };
+}();/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.