Coding, is? Fun!

Monday, February 09, 2009

Ext JS, Scriptaculous - Horizontal Portals

The Ext-js library has a portal example here. If you play around with that, you can see that the "portlets" move vertically when you drag and drop. It is a frequent requirement, instead, that the portlets dispose horizontally.
Imagine a horizontal panel as in the image:



There are two challenges to modify to horizontal:
1. Create a horizontal layout with a scrollbar
For this, the standard technique is to do the following steps:
a. Create a outer div with a fixed width, say 700px. Set "overflow:auto" in the outer div.
b. Create a div within it. Identify this div as, say, innerDiv.
c. In Javascript code, let us say you have 5 portlets, each of width 200px. Set the innerDiv width to 1100 px in code. In Ext-js, you do it thus:

var containerPanel = Ext.get("innerDiv");
var aItems = [];//this array should contain the list of portlets
var iMinWidth = 200;
var iWidth = iMinWidth*(aItems.length) + 60;
var strWidth = iWidth.toString() + "px";
containerPanel.setStyle("width",strWidth);


So, the key idea is that the inner div's width is set dynamically, depending on the number of portlets contained within. This also works if you have to add portlets on click of a button.

With the above steps you can create a scrollable container, with portlets laid out horizontally.

How to create the portlets
For this, I followed the portal example in Ext-js. I modified the sample.js to contain the following code for my horizontal portal sample:
The portal.html contains (for me):

<div id="divWork" style="overflow:auto;width:700px;" >
<div id="innerDiv">
</div>
</div>


The sample.js contains:

Ext.onReady(function(){

// create some portlet tools using built in Ext tool ids
var tools = [{
id:'gear',
handler: function(){
Ext.Msg.alert('Message', 'The Settings tool was clicked.');
}
},{
id:'close',
handler: function(e, target, panel){
Ext.Msg.alert('Message', 'The close tool was clicked.');

}
}];

var aItems = [{
title: 'Another Panel 1',
tools: tools,
html: Ext.example.shortBogusMarkup
},{
title: 'Another Panel 2',
tools: tools,
html: Ext.example.shortBogusMarkup
},{
title: 'Another Panel 3',
tools: tools,
html: Ext.example.shortBogusMarkup
},{
title: 'Another Panel 4',
tools: tools,
html: Ext.example.shortBogusMarkup
}];

var containerPanel = Ext.get("innerWork");
var ul = containerPanel.createChild({tag:'ul',id:"ulWork"});
var iMinWidth = 200;
var iWidth = iMinWidth*(aItems.length) + 60;
var strWidth = iWidth.toString() + "px";
containerPanel.setStyle("width",strWidth);

for(var x=0; x<aItems.length; x++)
{
var seqid = x;
var sStyle = "float:left;width:180px;height:100px;display:inline;margin:5px 5px 5px 5px;";

var li = ul.createChild({tag:'li', style:sStyle, id:"li_"+x });
var rd = new Ext.Panel(aItems[x]);
rd.render(li);

}

Sortable.create("ulWork", {tag:"li",constraint:"horizontal", onUpdate:function(){alert("Dropped");}});

});


Thus, within the inner Div, I have a "ul" and add the portlets as "li"s one by one.
The last line, is meant for drag and drop - as covered next.

2. For drag and drop of the portlets
I completely bypassed Ext. Since the above list can be considered a sortable list, I simply created a Sortable object on the ul.
This single line enables drag and drop. More details can be found here.


So, with the above, you can create a set of portlets that are horizontally laid out. Although other portions of our application uses Ext-js, this particular sample uses scriptaculous and regular Javascript to accomplish key functionality.

Labels: , ,