PDA

View Full Version : Horizontal Accordion V2.0



Birgit
Apr 03, 2012, 10:20 AM
Is it possible to implement a horizontal accordion, like the following url:

http://nicolahibbert.com/demo/liteAccordion/

I now realize it with jquery, but then i have resizing problems of the ext.net components inside the <div> tags.
In version 1.3 it was possible with master and content page to have a viewport in a viewport and have the monitorresize property. Then when resizing, the ext.net controls resized too, but it v2.0 i can't use a viewport inside a viewport...

It would be great to have a plugin for the horizontal accordion...

Thanx!

Daniil
Apr 03, 2012, 3:24 PM
Hi,

Unfortunately, there is no horizontal accordion.

I think it's possible, all the more so HeaderPosition feature appeared. Though, anyways, it doesn't look to be a trivial task to implement it.


but it v2.0 i can't use a viewport inside a viewport...

Well, using several Viewports is wrong in Ext.NET v1 as well. There must be a single Viewport on a page.

Could you provide a simple sample to reproduce the problem with JQuery horizontal accordion? I would look.

Birgit
Apr 03, 2012, 8:01 PM
Hi Daniil,

Thanx for your reply, underneath you find a simple example


<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Test.aspx.vb" Inherits="Test" meta:resourcekey="PageResource2" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Horizontal Accordion</title>

<style type="text/css">
.accordion
{
text-align: left;
padding: 5px 5px 6px 0px;
border-width: 9px;
border-style: solid;
border-bottom-width: 8px;
border-color: #353535;
background: #FF4455;
}
.accordion > ol
{
position: relative;
overflow: hidden;
height: 100%;
margin: 0;
padding: 0;
list-style-type: none;
}
.accordion .slide > h2
{
background: #030303;
color: #000000;
font-size: 18px;
font-weight: normal;
z-index: 100;
position: absolute;
-webkit-transform: translateX(-100%) rotate(-90deg);
-webkit-transform-origin: right top;
-moz-transform: translateX(-100%) rotate(-90deg);
-moz-transform-origin: right top;
-o-transform: translateX(-100%) rotate(-90deg);
-o-transform-origin: right top;
transform: translateX(-100%) rotate(-90deg);
transform-origin: right top;
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotat ion=3)";
filter: progid:DXImageTransform.Microsoft.BasicImage(rotat ion=3);
}
.accordion .slide > h2 span
{
color: #FFFFFF;
display: block;
padding-right: 20px;
text-align: right;
height: 90%;
margin-top: 5px;
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;
font-weight: bold;
}
.accordion .slide > h2:hover { cursor: pointer }
.accordion .slide > div
{
height: 100%;
position: absolute;
z-index: 10;
background: #FFFFFF;
}
</style>
<script type="text/javascript">
var currentScreenWidth, currentScreenHeight, lastScreenWidth, lastScreenHeight;
var accordionIsInitialized;
function UpdateAccordion() {
var accordion_clientid = '<%= PanelAccordion.ClientID %>';
var accordion = $('#' + accordion_clientid);
getScreenSize();
if (accordionIsInitialized != 1) {
// init accordion
lastScreenWidth = currentScreenWidth;
lastScreenHeight = currentScreenHeight;
accordion.liteAccordion({ containerWidth: currentScreenWidth - 10, containerHeight: currentScreenHeight - 70});
accordionIsInitialized = 1;
} else {
if (currentScreenHeight != lastScreenHeight || currentScreenWidth != lastScreenWidth) {
lastScreenWidth = currentScreenWidth;
lastScreenHeight = currentScreenHeight;
accordion.liteAccordion('destroy');
accordion.liteAccordion({ containerWidth: currentScreenWidth - 10, containerHeight: currentScreenHeight - 70});
}
}
}
var getScreenSize = function () {
currentScreenWidth = 630;
currentScreenHeight = 460;
if (document.body && document.body.offsetWidth) {
currentScreenWidth = document.body.offsetWidth;
currentScreenHeight = document.body.offsetHeight;
}
if (document.compatMode == 'CSS1Compat' &&
document.documentElement &&
document.documentElement.offsetWidth) {
currentScreenWidth = document.documentElement.offsetWidth;
currentScreenHeight = document.documentElement.offsetHeight;
}
if (window.innerWidth && window.innerHeight) {
currentScreenWidth = window.innerWidth;
currentScreenHeight = window.innerHeight;
}
}

</script>

<script src="Scripts/jquery.min.js" type="text/javascript" />
<script src="Scripts/jquery.easing.1.3.js" type="text/javascript"></script>
<script type="text/javascript">
var LiteAccordion = function (elem, options) {
var defaults = {
containerWidth: 960, // fixed (px)
containerHeight: 320, // fixed (px)
headerWidth: 48, // fixed (px)
activateOn: 'click', // click or mouseover
firstSlide: 1, // displays slide (n) on page load
slideSpeed: 400, // slide animation speed
onTriggerSlide: function () { }, // callback on slide activate
onSlideAnimComplete: function () { }, // callback on slide anim complete
cycleSpeed: 6000, // time between slide cycles
easing: 'swing' // custom easing function
},
// merge defaults with options in new settings object
settings = $.extend({}, defaults, options),
// 'globals'
slides = elem.children('ol').children('li'),
header = slides.children(':first-child'),
slideLen = slides.length,
slideWidth = settings.containerWidth - slideLen * settings.headerWidth,
// public methods
methods = {
// start elem animation
play: function (index) {
var next = core.nextSlide(index && index);
if (core.playing) return;
// start autoplay
core.playing = setInterval(function () {
header.eq(next()).trigger('click.liteAccordion');
}, settings.cycleSpeed);
},
// stop elem animation
stop: function () {
clearInterval(core.playing);
core.playing = 0;
},
// trigger next slide
next: function () {
methods.stop();
header.eq(core.currentSlide === slideLen - 1 ? 0 : core.currentSlide + 1).trigger('click.liteAccordion');
},
// trigger next slide
selectslide: function (slideindex) {
methods.stop();
header.eq(core.currentSlide === slideindex || slideindex > slideLen - 1 ? 0 : slideindex).trigger('click.liteAccordion');
},
currentslide: function () {
methods.stop();
return core.currentSlide;
},
// trigger previous slide
prev: function () {
methods.stop();
header.eq(core.currentSlide - 1).trigger('click.liteAccordion');
},
// destroy plugin instance
destroy: function () {
// stop autoplay
methods.stop();
// remove hashchange event bound to window
$(window).unbind('.liteAccordion');
// remove generated styles, classes, data, events
elem
.attr('style', '')
.removeClass('accordion')
.removeData('liteAccordion')
.unbind('.liteAccordion')
.find('li > :first-child')
.unbind('.liteAccordion')
.filter('.selected')
.removeClass('selected')
.end()
.find('b')
.remove();
slides
.removeClass('slide')
.children()
.attr('style', '');
}
},
// core utility and animation methods
core = {
// set style properties
setStyles: function () {
// set container heights, widths, corner style
elem
.width(settings.containerWidth)
.height(settings.containerHeight)
.addClass('accordion');
// set tab width, height and selected class
slides
.addClass('slide')
.children(':first-child')
.width(settings.containerHeight)
.height(settings.headerWidth)
.eq(settings.firstSlide - 1)
.addClass('selected');
// set initial positions for each slide
header.each(function (index) {
var $this = $(this),
left = index * settings.headerWidth,
margin = header.first().next(),
offset = parseInt(margin.css('marginLeft'), 10) || parseInt(margin.css('marginRight'), 10);
if (index >= settings.firstSlide) left += slideWidth;
$this
.css('left', left)
.next()
.width(slideWidth - offset)
.css({ left: left, paddingLeft: settings.headerWidth });
});
},
// bind click and mouseover events
bindEvents: function () {
if (settings.activateOn === 'click') {
header.bind('click.liteAccordion', core.triggerSlide);
} else if (settings.activateOn === 'mouseover') {
header.bind({
'mouseover.liteAccordion': core.triggerSlide,
'click.liteAccordion': core.triggerSlide
});
}
},
// counter for autoPlay (zero index firstSlide on init)
currentSlide: settings.firstSlide - 1,
// next slide index
nextSlide: function (index) {
var next = index + 1 || core.currentSlide + 1;
// closure
return function () {
return next++ % slideLen;
};
},
// animates left and right groups of slides
// side: denotes left side
animSlideGroup: function (index, next, side) {
var filterExpr = side ? ':lt(' + (index + 1) + ')' : ':gt(' + index + ')';
slides
.filter(filterExpr)
.each(function () {
var $this = $(this),
slideIndex = slides.index($this);
$this
.children()
.stop(true)
.animate({
left: (side ? 0 : slideWidth) + slideIndex * settings.headerWidth
}
,
settings.slideSpeed,
settings.easing,
function () {
// flag ensures that fn is only called one time per triggerSlide
if (!core.slideAnimCompleteFlag) {
settings.onSlideAnimComplete.call(next);
core.slideAnimCompleteFlag = true;
}
}
);
});
},
slideAnimCompleteFlag: false,
// trigger slide animation
triggerSlide: function (e) {
var $this = $(this),
index = header.index($this),
next = $this.next();
// update core.currentSlide
core.currentSlide = index;
// reset onSlideAnimComplete callback flag
core.slideAnimCompleteFlag = false;
// remove, then add selected class
header.removeClass('selected').filter($this).addCl ass('selected');
// trigger callback in context of sibling div
settings.onTriggerSlide.call(next);
// animate left & right groups
core.animSlideGroup(index, next, true);
core.animSlideGroup(index, next);
},
ieClass: function () {
var version = +($.browser.version).charAt(0);
if (version < 7) methods.destroy();
if (version === 7 || version === 8) {
slides.each(function (index) {
$(this).addClass('slide-' + index);
});
}
elem.addClass('ie ie' + version);
},
init: function () {
// test for ie
if ($.browser.msie) core.ieClass();
// init styles and events
core.setStyles();
core.bindEvents();
// check slide speed is not faster than cycle speed
if (settings.cycleSpeed < settings.slideSpeed) settings.cycleSpeed = settings.slideSpeed;
}
};
// init plugin
core.init();
// expose methods
return methods;
};
var test = function (instance, elem, method) {
var liteAccordion;
// if plugin already instantiated, return
if (instance) return;
// otherwise create a new instance
try {
liteAccordion = new LiteAccordion(elem, method);
elem.data('liteAccordion', liteAccordion);
}
catch (e) {
}
}
$.fn.liteAccordion = function (method) {
var elem = this,
instance = elem.data('liteAccordion');
try {
// if creating a new instance
if (typeof method === 'object' || !method) {
return elem.each(test(instance, elem, method));
/*function() {
var liteAccordion;
// if plugin already instantiated, return
if (instance) return;
// otherwise create a new instance
liteAccordion = new LiteAccordion(elem, method);
elem.data('liteAccordion', liteAccordion);
}*/
//return elem.each(test(method, elem, instance));
// otherwise, call method on current instance
} else if (typeof method === 'string') {
if (instance) {
if (instance[method]) {
// debug method isn't chainable b/c we need the debug object to be returned
if (method === 'debug' || method === 'currentslide') {
return instance[method].call(elem);
} else { // the rest of the methods are chainable though
instance[method].call(elem);
return elem;
}
} else {
var startindex = method.toString().indexOf('(');
var endindex = method.toString().indexOf(')');
if (method.toString().substring(0, startindex) === 'selectslide') {
var param = method.toString().substring(startindex + 1, endindex);
//instance.selectslide(param);
instance['selectslide'].call(elem, param);
}
}
}
}
}
catch (e) {
}
};
</script>

</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager runat="server" />
<ext:Viewport runat="server" Layout="BorderLayout">
<Items>
<ext:Panel runat="server" Region="North" Html="Panel 1" Height="60" />
<ext:Panel runat="server" Region="Center" Layout="FitLayout">
<Content>
<ext:Panel ID="panelMain" runat="server" Cls="documentwizardform" >
<Content>
<div id="PanelAccordion" runat="server" >
<ol>
<li>
<h2><span><asp:Literal runat="server" Text="Panel Left" /></span></h2>
<div>
<ext:Panel runat="server" Layout="VBoxLayout" ButtonAlign="Right">
<Items>
<ext:FormPanel ID="FormPanelCreateWizard" runat="server" Border="False"
Layout="AnchorLayout" Width="600" Height="250" AutoScroll="True" >
<Defaults>
<ext:Parameter Name="anchor" Value="95%" />
</Defaults>
<FieldDefaults LabelWidth="140" />
<Items>
<ext:TextField ID="TextField1" runat="server" FieldLabel="Label 1" />
<ext:TextField ID="TextField2" runat="server" FieldLabel="Label 1" />
<ext:TextField ID="TextField3" runat="server" FieldLabel="Label 1" />
</Items>
</ext:FormPanel>
</Items>
<Buttons>
<ext:Button runat="server" Text="Button 1" Scale="Large" IconAlign="Right" />
</Buttons>
</ext:Panel>
</div>
</li>
<li>
<h2><span><asp:Literal runat="server" Text="Panel Center" /></span></h2>
<div>
<ext:Panel runat="server" Layout="FitLayout" BodyPadding="10" >
<Content>
<ext:GridPanel ID="GridPanelDocumentQueue" runat="server" AutoScroll="True" >
<Store>
<ext:Store ID="Store1" runat="server" PageSize="20" >
<Model>
<ext:Model runat="server" >
<Fields>
<ext:ModelField Name="Field1" />
<ext:ModelField Name="Field2" />
<ext:ModelField Name="Field3" />
<ext:ModelField Name="ID" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<TopBar>
<ext:Toolbar ID="Toolbar2" runat="server">
<Items>
<ext:TextField runat="server" Width="570" />
<ext:Button runat="server" Scale="Medium" Type="Submit" ToolTip="Search" />
</Items>
</ext:Toolbar>
</TopBar>
<ColumnModel>
<Columns>
<ext:Column runat="server" DataIndex="Field1" Text="Field1" />
<ext:Column runat="server" DataIndex="Field2" Text="Field2" />
<ext:Column runat="server" DataIndex="Field3" Text="Field3" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel ID="RowSelectionModel1" runat="server" />
</SelectionModel>
<BottomBar>
<ext:PagingToolBar ID="PagingToolbarDocumentQueue"
runat="server"
StoreID="Store1"
DisplayInfo="True">
<Items>
<ext:ToolbarSpacer ID="ToolbarSpacer1" runat="server" />
<ext:ToolbarSeparator ID="ToolbarSeparator3" runat="server" />
<ext:ToolbarSpacer ID="ToolbarSpacer2" runat="server" Width="10" />
<ext:ComboBox
ID="cboRecordsPerPage"
runat="server"
Title="Records per page"
Width="120" >
<Items>
<ext:ListItem Text="5" Value="5" />
<ext:ListItem Text="15" Value="15" />
<ext:ListItem Text="20" Value="20" />
<ext:ListItem Text="30" Value="30" />
<ext:ListItem Text="50" Value="50" />
<ext:ListItem Text="100" Value="100" />
</Items>
<SelectedItems>
<ext:ListItem Text="20" Value="20" />
</SelectedItems>
</ext:ComboBox>
</Items>
</ext:PagingToolBar>
</BottomBar>
</ext:GridPanel>
</Content>
<Buttons>
<ext:Button runat="server" Text="Button 2" IconAlign="Right" Scale="Large" />
</Buttons>
</ext:Panel>
</div>
</li>
<li>
<h2><span><asp:Literal runat="server" Text="Panel Right" /></span></h2>
<div>
<ext:Panel runat="server" Layout="FitLayout" >
<Loader runat="server" AutoLoad="False" Url="" Mode="Frame" >
<LoadMask Msg="Loading" ShowMask="True" />
<Params>
<ext:Parameter Name="Param1" />
<ext:Parameter Name="Param2" />
<ext:Parameter Name="Param3" />
</Params>
</Loader>
</ext:Panel>
</div>
</li>
</ol>
</div>
</Content>
<Listeners>
<Resize Handler="UpdateAccordion();this.doLayout;" />
</Listeners>
</ext:Panel>
</Content>
</ext:Panel>
</Items>
</ext:Viewport>


</form>
<script language="javascript" type="text/javascript">
<!--
UpdateAccordion();
-->
</script>
</body>
</html>




The jquery script files you can find over here: https://github.com/nikki/liteAccordion/tree/master/js

It would be great to have a solution for this! I'm already strubbling with this for some months

Thanx!

Daniil
Apr 04, 2012, 4:40 PM
Ok, I was able to run the page.

Though I can't see any problems. Could you provide more details about the problem?

Could you also simplify that sample as much as you can to get the problem more clear?

Birgit
Apr 04, 2012, 6:17 PM
Hi Daniil,

As you can see, if you resize the page, the ext.net controls inside the panels aren't resized! If you load the first time the page with your browser maximized and afterwards, you resize it to a smaller window, you can see that the ext.net controls doesn't resize with the window.

As you can see in the attachment, the accordion_resize doesn't contain the "button 1" anymore...

Thanx!

geoffrey.mcgill
Apr 05, 2012, 5:05 AM
Hi,

You might also need to call .doLayout() on that visible Ext.NET Panel after the accordion is resized. This should force a re-calc of it's dimensions.

Hope this helps.

Birgit
Apr 05, 2012, 7:21 AM
Hi,

the doLayout() was the trick! You guys are great :).
Now the only thing is the height of the panels, they also need to fit the entire height. Appaerantly the height is automatically set to 150px.
How to fit height?

Thanx a lot!

Birgit
Apr 05, 2012, 9:33 AM
I found a solution: i manually set the height of the panels to the container height via the function setHeight before i do the doLayout

Thanx a lot guys!!

Daniil
Aug 16, 2012, 9:48 AM
Hi,

I am able to get the "horizontal accordion" scenario working with HBoxLayout.

Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Ext.NET v2 Example</title>

<script type="text/javascript">
var onRender = function (panel) {
var leftDockedItems = panel.getDockedItems("header[dock='left']"),
leftDockedItem;

if (leftDockedItems.length > 0) {
leftDockedItem = leftDockedItems[0];
leftDockedItem.on("click", onLeftDockedItemClick, panel)
} else {
panel.on("collapse", onRender, panel, { single : true });
}
};

var onLeftDockedItemClick = function () {
var me = this;

me.ownerCt.items.each(function (item) {
if (me !== item && item.collapse && !item.collapsed) {
item.collapse();
}
});
me.expand();
};
</script>
</head>
<body>
<ext:ResourceManager runat="server" />

<ext:Window runat="server" Width="600" Height="150">
<LayoutConfig>
<ext:HBoxLayoutConfig Align="Stretch" DefaultMargins="2 0" />
</LayoutConfig>
<Items>
<ext:Panel
runat="server"
Flex="1"
Title="Panel 1"
CollapseDirection="Left"
HideCollapseTool="true"
AnimCollapse="false">
<Listeners>
<Render Fn="onRender" />
</Listeners>
</ext:Panel>

<ext:Panel
runat="server"
Flex="1"
Title="Panel 2"
CollapseDirection="Left"
HideCollapseTool="true"
Collapsed="true"
AnimCollapse="false">
<Listeners>
<Render Fn="onRender" />
</Listeners>
</ext:Panel>

<ext:Panel
runat="server"
Flex="1"
Title="Panel 3"
CollapseDirection="Left"
HideCollapseTool="true"
Collapsed="true"
AnimCollapse="false">
<Listeners>
<Render Fn="onRender" />
</Listeners>
</ext:Panel>
</Items>
</ext:Window>
</body>
</html>

Birgit
Nov 14, 2012, 11:16 AM
Hi Daniil,

I just saw your post, this is really great!! :)

One more question, is it possible to put a timer on the expanding of the panel? So that it expands slower, like the panel is really sliding? Now it goes really fast, which is good of course, but we want it to see expanding for the visual effect.
Something like the sliding speed like in jquery.

Regards

Daniil
Nov 15, 2012, 11:04 AM
I think it should be possible.

1. Remove AnimCollapse="false"

2. Re-work the JavaScript to expand a Panel when the rest ones are actually collapsed (i.e. after animation)

Birgit
Nov 16, 2012, 9:11 AM
Hi Daniil,

When i remove the AnimCollapse and when i don't change anything to the javascript. Then the collapsing isn't working correct anymore.
It still calls the .collapse in the javascript, but it's not executed in the browser.

Regards

Daniil
Nov 16, 2012, 9:21 AM
Please review.


2. Re-work the JavaScript to expand a Panel when the rest ones are actually collapsed (i.e. after animation)

Birgit
Nov 16, 2012, 12:29 PM
Yes i saw this one, but i don't understand. Because the collapse is already called.
When do i need to do the collapse then?

Kind Regards

Daniil
Nov 20, 2012, 11:34 AM
Well, the main point in my statement is:

(i.e. after animation)

If a collapse call occurs before animation stops, it breaks the things.

So, it needs to call the collapse method after animation.

vgvallee
Jun 27, 2013, 8:10 PM
This is an older thread but I have the same requirement to use a horizontal accordion layout. The proposed code does have the basic behaviour of the accordion but it's missing the visual cues of the accordion, the +/- icons, and some behaviours such as opening up the next panel when the current panel is collapsed or the previous one if it's the last panel being collapsed...

I am trying to get the +/- icons to be displayed.

If I add a minus tool to the panels and code to collapse the panel on click, how can I get the plus tool to show on the collapsed header?

I noticed that if I change the markup to show the collapse tool instead, I get a collapse-left and expand-right icon, almost what I want, but I can't get to change the icons to +/- and I would also have to override the normal code for collapse/expand...

Thanks,
Vincent

Baidaly
Jun 27, 2013, 11:43 PM
Hello!


This is an older thread but I have the same requirement to use a horizontal accordion layout. The proposed code does have the basic behaviour of the accordion but it's missing the visual cues of the accordion, the +/- icons, and some behaviours such as opening up the next panel when the current panel is collapsed or the previous one if it's the last panel being collapsed...

I am trying to get the +/- icons to be displayed.

If I add a minus tool to the panels and code to collapse the panel on click, how can I get the plus tool to show on the collapsed header?

I noticed that if I change the markup to show the collapse tool instead, I get a collapse-left and expand-right icon, almost what I want, but I can't get to change the icons to +/- and I would also have to override the normal code for collapse/expand...

Thanks,
Vincent

Since, your requirements are different and you are a Premium Member, it's better to start a new thread.

Baidaly
Jun 28, 2013, 2:34 AM
I modified Daniil's sample. You can use it to start:



<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Ext.NET v2 Example</title>

<script type="text/javascript">
var onRender = function (panel) {
var leftDockedItems = panel.getDockedItems("header[dock='left']"),
leftDockedItem;

if (leftDockedItems.length > 0) {
leftDockedItem = leftDockedItems[0];
leftDockedItem.on("click", onLeftDockedItemClick, panel);

var task = new Ext.util.DelayedTask(function () {
leftDockedItem.addTool({
"type": "left",
listeners: {
click: {
fn: onLeftDockedItemClick,
scope: panel
}
}
});
});
task.delay(10);

} else {
panel.on("collapse", onRender, panel, { single: true });
}
};

var onLeftDockedItemClick = function () {
var me = this;

me.ownerCt.items.each(function (item) {
if (me !== item && item.collapse && !item.collapsed) {
item.collapse();
}
});
me.expand();
};
</script>
</head>
<body>
<ext:ResourceManager runat="server" SourceFormatting="True" />

<ext:Window runat="server" Width="600" Height="150">
<LayoutConfig>
<ext:HBoxLayoutConfig Align="Stretch" DefaultMargins="2 0" />
</LayoutConfig>
<Items>
<ext:Panel
runat="server"
ID="Panel1"
Flex="1"
Title="Panel 1"
CollapseDirection="Left"
HideCollapseTool="true"
AnimCollapse="false">
<Listeners>
<Render Fn="onRender" />
</Listeners>
<HeaderConfig TitlePosition="0">
<Items>
<ext:Tool runat="server" Type="Left"></ext:Tool>
</Items>
</HeaderConfig>
</ext:Panel>

<ext:Panel
runat="server"
ID="Panel2"
Flex="1"
Title="Panel 2"
CollapseDirection="Left"
HideCollapseTool="true"
Collapsed="true"
AnimCollapse="false">
<Listeners>
<Render Fn="onRender" />
</Listeners>
<HeaderConfig TitlePosition="0">
<Items>
<ext:Tool runat="server" Type="Left"></ext:Tool>
</Items>
</HeaderConfig>
</ext:Panel>

<ext:Panel
runat="server"
ID="Panel3"
Flex="1"
Title="Panel 3"
CollapseDirection="Left"
HideCollapseTool="true"
Collapsed="true"
AnimCollapse="false">
<Listeners>
<Render Fn="onRender" />
</Listeners>
<HeaderConfig TitlePosition="0">
<Items>
<ext:Tool runat="server" Type="Left"></ext:Tool>
</Items>
</HeaderConfig>
</ext:Panel>
</Items>
</ext:Window>
</body>
</html>