/* * YUI Extensions 0.33 RC2 * Copyright(c) 2006, Jack Slocum. */ /** * @class YAHOO.ext.LayoutRegion * @extends YAHOO.ext.util.Observable * This class represents a region in a layout manager. */ YAHOO.ext.LayoutRegion = function(mgr, config, pos){ this.mgr = mgr; this.position = pos; var dh = YAHOO.ext.DomHelper; /** This regions container element @type YAHOO.ext.Element */ this.el = dh.append(mgr.el.dom, {tag: 'div', cls: 'ylayout-panel ylayout-panel-' + this.position}, true); /** This regions title element @type YAHOO.ext.Element */ this.titleEl = dh.append(this.el.dom, {tag: 'div', unselectable: 'on', cls: 'yunselectable ylayout-panel-hd ylayout-title-'+this.position, children:[ {tag: 'span', cls: 'yunselectable ylayout-panel-hd-text', unselectable: 'on', html: ' '}, {tag: 'div', cls: 'yunselectable ylayout-panel-hd-tools', unselectable: 'on'} ]}, true); this.titleEl.enableDisplayMode(); /** This regions title text element @type HTMLElement */ this.titleTextEl = this.titleEl.dom.firstChild; this.tools = getEl(this.titleEl.dom.childNodes[1], true); this.closeBtn = this.createTool(this.tools.dom, 'ylayout-close'); this.closeBtn.enableDisplayMode(); this.closeBtn.on('click', this.closeClicked, this, true); this.closeBtn.hide(); /** This regions body element @type YAHOO.ext.Element */ this.bodyEl = dh.append(this.el.dom, {tag: 'div', cls: 'ylayout-panel-body'}, true); this.events = { /** * @event invalidated * Fires when the layout for this region is changed. * @param {YAHOO.ext.LayoutRegion} this */ 'invalidated' : new YAHOO.util.CustomEvent('invalidated'), /** * @event visibilitychange * Fires when this region is shown or hidden * @param {YAHOO.ext.LayoutRegion} this * @param {Boolean} visibility true or false */ 'visibilitychange' : new YAHOO.util.CustomEvent('visibilitychange'), /** * @event paneladded * Fires when a panel is added. * @param {YAHOO.ext.LayoutRegion} this * @param {YAHOO.ext.ContentPanel} panel The panel */ 'paneladded' : new YAHOO.util.CustomEvent('paneladded'), /** * @event panelremoved * Fires when a panel is removed. * @param {YAHOO.ext.LayoutRegion} this * @param {YAHOO.ext.ContentPanel} panel The panel */ 'panelremoved' : new YAHOO.util.CustomEvent('panelremoved'), /** * @event collapsed * Fires when this region is collapsed. * @param {YAHOO.ext.LayoutRegion} this */ 'collapsed' : new YAHOO.util.CustomEvent('collapsed'), /** * @event expanded * Fires when this region is expanded. * @param {YAHOO.ext.LayoutRegion} this */ 'expanded' : new YAHOO.util.CustomEvent('expanded'), /** * @event panelactivated * Fires when a panel is activated. * @param {YAHOO.ext.LayoutRegion} this * @param {YAHOO.ext.ContentPanel} panel The activated panel */ 'panelactivated' : new YAHOO.util.CustomEvent('panelactivated'), /** * @event resized * Fires when the user resizes this region. * @param {YAHOO.ext.LayoutRegion} this * @param {Number} newSize The new size (width for east/west, height for north/south) */ 'resized' : new YAHOO.util.CustomEvent('resized') }; /** A collection of panels in this region. @type YAHOO.ext.util.MixedCollection */ this.panels = new YAHOO.ext.util.MixedCollection(); this.panels.getKey = this.getPanelId.createDelegate(this); this.box = null; this.visible = false; this.collapsed = false; this.hide(); this.on('paneladded', this.validateVisibility, this, true); this.on('panelremoved', this.validateVisibility, this, true); this.activePanel = null; this.applyConfig(config); /* One day this will get finished this.draggable = config.draggable || false; if(YAHOO.ext.LayoutRegionDD && mgr.enablePanelDD){ this.dd = new YAHOO.ext.LayoutRegionDD(this); }*/ }; YAHOO.extendX(YAHOO.ext.LayoutRegion, YAHOO.ext.util.Observable, { getPanelId : function(p){ return p.getId(); }, applyConfig : function(config){ if(config.collapsible && this.position != 'center' && !this.collapsedEl){ var dh = YAHOO.ext.DomHelper; this.collapseBtn = this.createTool(this.tools.dom, 'ylayout-collapse-'+this.position); this.collapseBtn.mon('click', this.collapse, this, true); /** This regions collapsed element @type YAHOO.ext.Element */ this.collapsedEl = dh.append(this.mgr.el.dom, {tag: 'div', cls: 'ylayout-collapsed ylayout-collapsed-'+this.position, children:[ {tag: 'div', cls: 'ylayout-collapsed-tools'} ]}, true); if(config.floatable !== false){ this.collapsedEl.addClassOnOver('ylayout-collapsed-over'); this.collapsedEl.mon('click', this.collapseClick, this, true); } this.expandBtn = this.createTool(this.collapsedEl.dom.firstChild, 'ylayout-expand-'+this.position); this.expandBtn.mon('click', this.expand, this, true); } if(this.collapseBtn){ this.collapseBtn.setVisible(config.collapsible == true); } this.cmargins = config.cmargins || this.cmargins || (this.position == 'west' || this.position == 'east' ? {top: 0, left: 2, right:2, bottom: 0} : {top: 2, left: 0, right:0, bottom: 2}); this.margins = config.margins || this.margins || {top: 0, left: 0, right:0, bottom: 0}; this.bottomTabs = config.tabPosition != 'top'; this.autoScroll = config.autoScroll || false; if(this.autoScroll){ this.bodyEl.setStyle('overflow', 'auto'); }else{ this.bodyEl.setStyle('overflow', 'hidden'); } if((!config.titlebar && !config.title) || config.titlebar === false){ this.titleEl.hide(); }else{ this.titleEl.show(); if(config.title){ this.titleTextEl.innerHTML = config.title; } } this.duration = config.duration || .30; this.slideDuration = config.slideDuration || .45; this.config = config; if(config.collapsed){ this.collapse(true); } }, /** * Resizes the region to the specified size. For vertical regions (west, east) this adjusts * the width, for horizontal (north, south) the height. * @param {Number} newSize The new width or height */ resizeTo : function(newSize){ switch(this.position){ case 'east': case 'west': this.el.setWidth(newSize); this.fireEvent('resized', this, newSize); break; case 'north': case 'south': this.el.setHeight(newSize); this.fireEvent('resized', this, newSize); break; } }, getBox : function(){ var b; if(!this.collapsed){ b = this.el.getBox(false, true); }else{ b = this.collapsedEl.getBox(false, true); } return b; }, getMargins : function(){ return this.collapsed ? this.cmargins : this.margins; }, highlight : function(){ this.el.addClass('ylayout-panel-dragover'); }, unhighlight : function(){ this.el.removeClass('ylayout-panel-dragover'); }, updateBox : function(box){ this.box = box; if(!this.collapsed){ this.el.dom.style.left = box.x + 'px'; this.el.dom.style.top = box.y + 'px'; this.el.setSize(box.width, box.height); var bodyHeight = this.config.titlebar ? box.height - (this.titleEl.getHeight()||0) : box.height; bodyHeight -= this.el.getBorderWidth('tb'); bodyWidth = box.width - this.el.getBorderWidth('rl'); this.bodyEl.setHeight(bodyHeight); this.bodyEl.setWidth(bodyWidth); var tabHeight = bodyHeight; if(this.tabs){ tabHeight = this.tabs.syncHeight(bodyHeight); if(YAHOO.ext.util.Browser.isIE) this.tabs.el.repaint(); } this.panelSize = {width: bodyWidth, height: tabHeight}; if(this.activePanel){ this.activePanel.setSize(bodyWidth, tabHeight); } }else{ this.collapsedEl.dom.style.left = box.x + 'px'; this.collapsedEl.dom.style.top = box.y + 'px'; this.collapsedEl.setSize(box.width, box.height); } if(this.tabs){ this.tabs.autoSizeTabs(); } }, /** * Returns the container element for this region. * @return {YAHOO.ext.Element} */ getEl : function(){ return this.el; }, /** * Hides this region. */ hide : function(){ if(!this.collapsed){ this.el.dom.style.left = '-2000px'; this.el.hide(); }else{ this.collapsedEl.dom.style.left = '-2000px'; this.collapsedEl.hide(); } this.visible = false; this.fireEvent('visibilitychange', this, false); }, /** * Shows this region if it was previously hidden. */ show : function(){ if(!this.collapsed){ this.el.show(); }else{ this.collapsedEl.show(); } this.visible = true; this.fireEvent('visibilitychange', this, true); }, /** * Returns true if this region is currently visible. * @return {Boolean} */ isVisible : function(){ return this.visible; }, closeClicked : function(){ if(this.activePanel){ this.remove(this.activePanel); } }, collapseClick : function(e){ if(this.isSlid){ e.stopPropagation(); this.slideIn(); }else{ e.stopPropagation(); this.slideOut(); } }, /** * Collapses this region. * @param {Boolean} skipAnim (optional) true to collapse the element without animation (if animate is true) */ collapse : function(skipAnim){ if(this.collapsed) return; this.collapsed = true; if(this.split){ this.split.el.hide(); } if(this.config.animate && skipAnim !== true){ this.animateCollapse(); }else{ this.el.setLocation(-20000,-20000); this.el.hide(); this.collapsedEl.show(); this.fireEvent('collapsed', this); } this.fireEvent('invalidated', this); }, animateCollapse : function(){ // overridden }, /** * Expand this region if it was previously collapsed. * @param {YAHOO.ext.EventObject} e The event that triggered the expand (or null if calling manually) * @param {Boolean} skipAnim (optional) true to expand the element without animation (if animate is true) */ expand : function(e, skipAnim){ if(e) e.stopPropagation(); if(!this.collapsed) return; if(this.isSlid){ this.slideIn(this.expand.createDelegate(this)); return; } this.collapsed = false; this.el.show(); if(this.config.animate && skipAnim !== true){ this.animateExpand(); }else{ if(this.split){ this.split.el.show(); } this.collapsedEl.setLocation(-2000,-2000); this.collapsedEl.hide(); this.fireEvent('invalidated', this); this.fireEvent('expanded', this); } }, animateExpand : function(){ // overridden }, initTabs : function(){ this.bodyEl.setStyle('overflow', 'hidden'); var ts = new YAHOO.ext.TabPanel(this.bodyEl.dom, this.bottomTabs); this.tabs = ts; ts.resizeTabs = this.config.resizeTabs === true; ts.minTabWidth = this.config.minTabWidth || 40; ts.maxTabWidth = this.config.maxTabWidth || 250; ts.preferredTabWidth = this.config.preferredTabWidth || 150; ts.monitorResize = false; ts.bodyEl.setStyle('overflow', this.config.autoScroll ? 'auto' : 'hidden'); this.panels.each(this.initPanelAsTab, this); }, initPanelAsTab : function(panel){ var ti = this.tabs.addTab(panel.getEl().id, panel.getTitle(), null, this.config.closeOnTab && panel.isClosable()); ti.on('activate', function(){ this.setActivePanel(panel); }, this, true); if(this.config.closeOnTab){ ti.on('beforeclose', function(t, e){ e.cancel = true; this.remove(panel); }, this, true); } return ti; }, updatePanelTitle : function(panel, title){ if(this.activePanel == panel){ this.updateTitle(title); } if(this.tabs){ this.tabs.getTab(panel.getEl().id).setText(title); } }, updateTitle : function(title){ if(this.titleTextEl && !this.config.title){ this.titleTextEl.innerHTML = (typeof title != 'undefined' && title.length > 0 ? title : " "); } }, setActivePanel : function(panel){ panel = this.getPanel(panel); if(this.activePanel && this.activePanel != panel){ this.activePanel.setActiveState(false); } this.activePanel = panel; panel.setActiveState(true); if(this.panelSize){ panel.setSize(this.panelSize.width, this.panelSize.height); } this.closeBtn.setVisible(!this.config.closeOnTab && !this.isSlid && panel.isClosable()); this.updateTitle(panel.getTitle()); this.fireEvent('panelactivated', this, panel); /* if(this.dd && !panel.enableDD){ this.dd.lock(); }*/ }, /** * Show the specified panel. * @param {Number/String/ContentPanel} panelId The panels index, id or the panel itself * @return {YAHOO.ext.ContentPanel} The shown panel or null */ showPanel : function(panel){ if(panel = this.getPanel(panel)){ if(this.tabs){ this.tabs.activate(panel.getEl().id); }else{ this.setActivePanel(panel); } } return panel; }, /** * Get the active panel for this region. * @return {YAHOO.ext.ContentPanel} The active panel or null */ getActivePanel : function(){ return this.activePanel; }, validateVisibility : function(){ if(this.panels.getCount() < 1){ this.updateTitle(' '); this.closeBtn.hide(); this.hide(); }else{ if(!this.isVisible()){ this.show(); } } }, /** * Add the passed ContentPanel(s) * @param {ContentPanel...} panel The ContentPanel(s) to add (you can pass more than one) * @return {YAHOO.ext.ContentPanel} The panel added (if only one was added) */ add : function(panel){ if(arguments.length > 1){ for(var i = 0, len = arguments.length; i < len; i++) { this.add(arguments[i]); } return null; } panel.setRegion(this); this.panels.add(panel); if(this.panels.getCount() == 1 && !this.config.alwaysShowTabs){ this.bodyEl.dom.appendChild(panel.getEl().dom); this.setActivePanel(panel); this.fireEvent('paneladded', this, panel); return panel; } if(!this.tabs){ this.initTabs(); }else{ this.initPanelAsTab(panel); } this.tabs.activate(panel.getEl().id); this.fireEvent('paneladded', this, panel); return panel; }, /** * Returns true if the panel is in this region. * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself * @return {Boolean} */ hasPanel : function(panel){ if(typeof panel == 'object'){ // must be panel obj panel = panel.getId(); } return this.getPanel(panel) ? true : false; }, /** * Hides the tab for the specified panel. * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself */ hidePanel : function(panel){ if(this.tabs && (panel = this.getPanel(panel))){ this.tabs.hideTab(panel.getEl().id); } }, /** * Unhides the tab for a previously hidden panel. * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself */ unhidePanel : function(panel){ if(this.tabs && (panel = this.getPanel(panel))){ this.tabs.unhideTab(panel.getEl().id); } }, // broken //clearPanels : function(){ // this.panels.each(this.remove, this); //}, /** * Removes the specified panel. If preservePanel is not true (either here or in the config), the panel is destroyed. * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself * @param {Boolean} preservePanel Overrides the config preservePanel option * @return {YAHOO.ext.ContentPanel} The panel that was removed */ remove : function(panel, preservePanel){ panel = this.getPanel(panel); if(!panel){ return null; } preservePanel = (typeof preservePanel != 'undefined' ? preservePanel : this.config.preservePanels === true); var panelId = panel.getId(); this.panels.removeKey(panelId); if(preservePanel){ document.body.appendChild(panel.getEl().dom); } if(this.tabs){ this.tabs.removeTab(panel.getEl().id); }else if (!preservePanel){ this.bodyEl.dom.removeChild(panel.getEl().dom); } if(this.panels.getCount() == 1 && this.tabs && !this.config.alwaysShowTabs){ var p = this.panels.first(); var tempEl = document.createElement('span'); // temp holder to keep IE from deleting the node tempEl.appendChild(p.getEl().dom); this.bodyEl.update(''); this.bodyEl.dom.appendChild(p.getEl().dom); tempEl = null; this.updateTitle(p.getTitle()); this.tabs = null; this.bodyEl.setStyle('overflow', this.config.autoScroll ? 'auto' : 'hidden'); this.setActivePanel(p); } panel.setRegion(null); if(this.activePanel == panel){ this.activePanel = null; } if(this.config.autoDestroy !== false && preservePanel !== true){ try{panel.destroy();}catch(e){} } this.fireEvent('panelremoved', this, panel); return panel; }, /** * Returns the TabPanel component used by this region * @return {YAHOO.ext.TabPanel} */ getTabs : function(){ return this.tabs; }, /** * Returns the panel specified or null if it's not in this region. * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself * @return {YAHOO.ext.ContentPanel} */ getPanel : function(id){ if(typeof id == 'object'){ // must be panel obj return id; } return this.panels.get(id); }, /** * Returns this regions position (north/south/east/west/center). * @return {String} */ getPosition: function(){ return this.position; }, createTool : function(parentEl, className){ var btn = YAHOO.ext.DomHelper.append(parentEl, {tag: 'div', cls: 'ylayout-tools-button', children: [{tag: 'div', cls: 'ylayout-tools-button-inner ' + className, html: ' '}]}, true); btn.on('mouseover', btn.addClass.createDelegate(btn, ['ylayout-tools-button-over'])); btn.on('mouseout', btn.removeClass.createDelegate(btn, ['ylayout-tools-button-over'])); return btn; } });