Code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Toolbar with Menus</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all-debug.js"></script>
<script type="text/javascript" src="../form/states.js"></script>
<style type="text/css">
.ux-float-layout-ct {
position: relative;
}
.ux-float-layout-ct .ux-float-layout-sizer {
background: transparent none;
border: 0 none;
padding: 0;
margin: 0;
width: 0;
}
.ux-float-layout-ct .x-box-inner {
overflow: auto;
}
.x-box-item {
position: absolute!important;
}
.test-item {
height: 77px;
width: 60px;
}
.test-item-inner {
margin-left: 5px;
margin-top: 5px;
background-image: url(http://demo.qooxdoo.org/current/demobrowser/resource/qx/icon/Tango/48/devices/computer.png);
height:48px;
width:48px;
}
.test-item-desc {
margin-top: 5px;
text-align: center;
}
.x-btn-text-icon em {
display: block;
height: 100%;
}
button.test-button {
height: 100%!important;
width: 100%!important;
background-image: url(http://demo.qooxdoo.org/current/demobrowser/resource/qx/icon/Tango/48/devices/computer.png)!important;
padding-left: 40px!important;
}
</style>
<script type="text/javascript">
Ext.override(Ext.Element, (function(){
var pxMatch = /(\d+\.?\d+)px/;
return {
// private.
// Return the addressable area of the element using explicit CSS style in preference to offsetHeight/offsetWidth.
// Optionally subtract padding if contentBox parameter is truthy
getStyleSize : function(contentBox){
var doc = document,
me = this,
d = me.dom,
extdom = Ext.lib.Dom,
isDoc = (d == doc || d == doc.body),
isBB, w, h, tbBorder = 0, lrBorder = 0,
tbPadding = 0, lrPadding = 0;
if (isDoc) {
return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
}
isBB = me.isBorderBox();
tbBorder = me.getBorderWidth('tb');
lrBorder = me.getBorderWidth('lr');
tbPadding = me.getPadding('tb');
lrPadding = me.getPadding('lr');
// Width calcs
// Try the style first, then offsetWidth
if (w = me.getStyle('width').match(pxMatch)){
if ((w = parseFloat(w[1])) && isBB){
// Style includes the padding and border if isBB
w -= (lrBorder + lrPadding);
}
w += lrPadding;
} else if (w = d.offsetWidth){
w -= lrBorder;
}
w && contentBox && (w -= lrPadding);
// Height calcs
// Try the style first, then offsetHeight
if (h = me.getStyle('height').match(pxMatch)){
if ((h = parseFloat(h[1])) && isBB){
// Style includes the padding and border if isBB
h -= (tbBorder + tbPadding);
}
h += tbPadding;
} else if (h = d.offsetHeight){
h -= tbBorder;
}
h && contentBox && (h -= tbPadding);
return {
width : w,
height : h
};
},
/**
* <p>Returns the dimensions of the element available to lay content out in.<p>
* <p>If the element (or any ancestor element) has CSS style <code>display : none</code>, the dimensions will be zero.</p>
* example:<pre><code>
var vpSize = Ext.getBody().getViewSize();
// all Windows created afterwards will have a default value of 90% height and 95% width
Ext.Window.override({
width: vpSize.width * 0.9,
height: vpSize.height * 0.95
});
// To handle window resizing you would have to hook onto onWindowResize.
</code></pre>
* @param {Boolean} contentBox True to return the W3 content box <i>within</i> the padding area of the element. False
* or omitted to return the full area of the element within the border. See <a href="http://www.w3.org/TR/CSS2/box.html">http://www.w3.org/TR/CSS2/box.html</a>
* @return {Object} An object containing the elements's area: <code>{width: <element width>, height: <element height>}</code>
*/
getViewSize : function(contentBox){
var doc = document,
me = this,
d = me.dom,
extdom = Ext.lib.Dom,
isDoc = (d == doc || d == doc.body),
ss = Ext.isIE ? me.getStyleSize(contentBox) : null, w, h;
if (isDoc) {
return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
}
// Width calcs
// Try clientWidth, then styleWidth
if (w = d.clientWidth){
// IE sometimes overestimates client size
Ext.isIE && w > ss.width && (w = ss.width);
if (contentBox){
w -= me.getPadding('lr');
}
} else {
if (!ss) ss = me.getStyleSize(contentBox);
w = ss.width;
}
// Height calcs
// Try clientHeight, then styleHeight
if (h = d.clientHeight){
// IE sometimes overestimates client size
Ext.isIE && h > ss.height && (h = ss.height);
if (contentBox){
h -= me.getPadding('tb');
}
} else {
if (!ss) ss = me.getStyleSize(contentBox);
h = ss.height;
}
return {
width : w,
height : h
};
}
};
})());
/**
* @class Ext.layout.FloatLayout
* @extends Ext.layout.BoxLayout
* <p>A layout that arranges items in a left to right flow similar to using HTML's <code>float: left</code> style.</p>
* <p>When a Component's width (including its padding) won't fit within the available width of the Container (within its padding)
* then the Component is wrapped to the beginning of a new line, clearing the tallest item on the current line.</p>
* <p>Items may be vertically aligned with the row they happen to fall within. A line's height is the height of its tallest child
* item (including its margins), and vertical alignment take place within this space. Vertical alignment is specified for the layout using the
* {@link #verticalAlign} config, and may be overriden for a single item by configuring an item with a verticalAlign value.</p>
* <p>Row content may be aligned within the available width of the Container using the {@link #horizontalAlign} config.</p>
* <p>Child items may be cleared left or right by configuring a <b>clear</b> value in the item.</p>
* <p>Row and column spacing may be specified using the {@link #verticalSpacing} and {@link #horizontalSpacing} options.
*/
Ext.layout.FloatLayout = Ext.extend(Ext.layout.BoxLayout, {
/**
* @cfg {Boolean} animate
* <p><code>true</code> to animate child items into their calculated positions.</p>
* <p>Defaults to <code>false</code>.</p>
*/
/**
* @cfg {String} verticalAlign
* <p>Vertical alignment of child items within each row. Defaults to 'middle'. Values may be</p>
* <code>'top'</code>, <code>'middle'</code> or <code>'bottom'</code>
* <p>May be overriden by an individual child item.</p>
*/
verticalAlign: 'middle',
/**
* @cfg {String} horizontalAlign
* <p>Horizontal alignment of child items within each row. Defaults to 'left'. Values may be</p>
* <code>'left'</code>, <code>'center'</code>, <code>'right'</code> or <code>'justify'</code>
* <p>May be overriden by an individual child item.</p>
*/
horizontalAlign: 'left',
/**
* @cfg {Number} horizontalSpacing
* <p>Horizontal space to leave between items.</p>
*/
horizontalSpacing: 0,
/**
* @cfg {Number} verticalSpacing
* <p>Vertical space to leave between rows.</p>
*/
verticalSpacing: 0,
targetCls : 'ux-float-layout-ct',
updateChildBoxes: function(b) {
for (var i = 0, l = b.length; i < l; i++) {
if (this.animate) {
Ext.lib.Anim.motion(b[i].component.getPositionEl().dom, {left: {to: b[i].left}, top: {to: b[i].top}}).animate();
} else {
b[i].component.setPosition([b[i].left, b[i].top]);
}
}
},
calculateChildBoxes: function() {
var ct = this.container,
ce = ct.getLayoutTarget(),
paddingLeft = this.padding.left + ce.getPadding('l'),
paddingTop = this.padding.top + ce.getPadding('t'),
s = ce.getStyleSize(),
rightLimit = (s.width -= (this.padding.right + ce.getPadding('r'))),
bottomLimit = s.height - (this.padding.bottom + ce.getPadding('b')),
rowStart = 0,
rowHeight = 0,
rowWidth = 0,
x = paddingLeft,
y = paddingTop,
items = this.getRenderedItems(ct),
l = items.length, i, c, cs, m, r,
boxes = [], a;
// We never want to see horizontal scroll bars if possible
ce.setStyle('overflow-x', 'hidden');
// Content Width.
s.width -= paddingLeft;
for (var i = 0, l = items.length; i < l; i++) {
c = items[i];
cs = c.getSize();
cs.width += c.getPositionEl().getMargins('lr');
cs.height += c.getPositionEl().getMargins('tb');
m = c.margins;
r = x + m.left + cs.width + m.right;
// This item won't fit on the row.
if ((r > rightLimit) || (c.clear == 'left') || ((i > 0) && items[i - 1].clear == 'right')) {
this.adjustRow(boxes, rowStart, i - 1, rowHeight, rowWidth, s.width);
x = paddingLeft;
y += rowHeight + this.verticalSpacing;
r = x + m.left + cs.width + m.right;
rowStart = i;
rowHeight = 0;
rowWidth = 0;
}
rowHeight = Math.max(rowHeight, cs.height);
rowWidth += cs.width;
// We are laying out an autoScroll Container, and this item is going to cause a vertical scrollbar:
// Adjust the right padding to account for that scrollbar, and reflow.
if (ct.autoScroll && !this.reflow && ((y + rowHeight) > bottomLimit)) {
r = this.padding.right;
this.padding.right += Ext.getScrollBarWidth();
this.reflow = true;
this.onLayout(ct, ce);
delete this.reflow;
this.padding.right = r;
return this.childBoxCache;
}
boxes.push({
component: c,
left : x,
top : y,
height : cs.height,
width : cs.width
});
x = r + this.horizontalSpacing;
}
// Adjust the last row
this.adjustRow(boxes, rowStart, i - 1, rowHeight, rowWidth, s.width);
// Stretch the container heightwise.
if (!this.sizer) {
this.sizer = this.innerCt.insertFirst({
cls: 'ux-float-layout-sizer'
});
}
this.sizer.setHeight(y + rowHeight - paddingTop);
return {
boxes: boxes,
meta: {}
};
},
// Adjust vertical alignment within row.
// Adjust horizontal alignment if required.
adjustRow: function(boxes, rowStart, rowEnd, rowHeight, rowWidth, availWidth) {
var i, c, h, j = 0, spareWidth = availWidth - rowWidth, gaps = rowEnd - rowStart, alignmentIncrement = 0;
switch (this.horizontalAlign) {
case 'middle':
case 'center':
alignmentIncrement = Math.max(spareWidth / 2, 0);
break;
case 'right':
alignmentIncrement = Math.max(spareWidth, 0);
break;
case 'justify':
if (gaps) {
j = Math.max(spareWidth / gaps, 0);
}
}
for (i = rowStart; i <= rowEnd; i++) {
c = boxes[i].component;
h = c.getHeight() + c.getPositionEl().getMargins('tb');
boxes[i].left += alignmentIncrement;
alignmentIncrement += j;
switch (c.verticalAlign || this.verticalAlign) {
case 'middle':
case 'center':
boxes[i].top += (rowHeight - h) / 2;
break;
case 'bottom':
boxes[i].top += (rowHeight - h);
}
}
}
});
Ext.Container.LAYOUTS['float'] = Ext.layout.FloatLayout;
Ext.onReady(function(){
Ext.QuickTips.init();
// Menus can be prebuilt and passed by reference
var dateMenu = new Ext.menu.DateMenu({
handler: function(dp, date){
Ext.example.msg('Date Selected', 'You chose {0}.', date.format('M j, Y'));
}
});
var colorMenu = new Ext.menu.ColorMenu({
handler: function(cm, color){
Ext.example.msg('Color Selected', 'You chose {0}.', color);
}
});
var store = new Ext.data.ArrayStore({
fields: ['abbr', 'state'],
data : Ext.exampledata.states // from states.js
});
var combo = new Ext.form.ComboBox({
store: store,
displayField: 'state',
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText: 'Select a state...',
selectOnFocus: true,
width: 135,
getListParent: function() {
return this.el.up('.x-menu');
},
iconCls: 'no-icon'
});
var menu = new Ext.menu.Menu({
id: 'mainMenu',
style: {
overflow: 'visible' // For the Combo popup
},
items: [
combo, // A Field in a Menu
{
text: 'I like Ext',
checked: true, // when checked has a boolean value, it is assumed to be a CheckItem
checkHandler: onItemCheck
}, '-', {
text: 'Radio Options',
menu: { // <-- submenu by nested config object
items: [
// stick any markup in a menu
'<b class="menu-title">Choose a Theme</b>',
{
text: 'Aero Glass',
checked: true,
group: 'theme',
checkHandler: onItemCheck
}, {
text: 'Vista Black',
checked: false,
group: 'theme',
checkHandler: onItemCheck
}, {
text: 'Gray Theme',
checked: false,
group: 'theme',
checkHandler: onItemCheck
}, {
text: 'Default Theme',
checked: false,
group: 'theme',
checkHandler: onItemCheck
}
]
}
},{
text: 'Choose a Date',
iconCls: 'calendar',
menu: dateMenu // <-- submenu by reference
},{
text: 'Choose a Color',
menu: colorMenu // <-- submenu by reference
}
]
});
var tb = new Ext.Toolbar({
id: 'tb',
layout: {
type: 'float',
verticalSpacing: 4,
horizontalSpacing: 4
}
});
tb.add({
text:'Button w/ Menu',
iconCls: 'bmenu', // <-- icon
menu: menu // assign menu by instance
}, {
text: 'Users',
iconCls: 'user',
menu: {
xtype: 'menu',
plain: true,
items: {
xtype: 'buttongroup',
title: 'User options',
autoWidth: true,
columns: 2,
defaults: {
xtype: 'button',
scale: 'large',
width: '100%',
iconAlign: 'left'
},
items: [{
text: 'User<br/>manager',
iconCls: 'edit'
},{
iconCls: 'add',
width: 'auto',
tooltip: 'Add user'
},{
colspan: 2,
text: 'Import',
scale: 'small'
},{
colspan: 2,
text: 'Who is online?',
scale: 'small'
}]
}
}
},
new Ext.Toolbar.SplitButton({
text: 'Split Button',
handler: onButtonClick,
tooltip: {text:'This is a an example QuickTip for a toolbar item', title:'Tip Title'},
iconCls: 'blist',
// Menus can be built/referenced by using nested menu config objects
menu : {
items: [{
text: '<b>Bold</b>', handler: onItemClick
}, {
text: '<i>Italic</i>', handler: onItemClick
}, {
text: '<u>Underline</u>', handler: onItemClick
}, '-', {
text: 'Pick a Color',
handler: onItemClick,
menu: {
items: [
new Ext.ColorPalette({
listeners: {
select: function(cp, color){
Ext.example.msg('Color Selected', 'You chose {0}.', color);
}
}
}), '-',
{
text: 'More Colors...',
handler: onItemClick
}
]
}
}, {
text: 'Extellent!',
handler: onItemClick
}]
}
}), '-', {
text: 'Toggle Me',
enableToggle: true,
toggleHandler: onItemToggle,
pressed: true
});
menu.addSeparator();
// Menus have a rich api for
// adding and removing elements dynamically
var item = menu.add({
text: 'Dynamically added Item'
});
// items support full Observable API
item.on('click', onItemClick);
// items can easily be looked up
menu.add({
text: 'Disabled Item',
id: 'disableMe' // <-- Items can also have an id for easy lookup
// disabled: true <-- allowed but for sake of example we use long way below
});
// access items by id or index
menu.items.get('disableMe').disable();
// They can also be referenced by id in or components
tb.add('-', {
icon: 'list-items.gif', // icons can also be specified inline
cls: 'x-btn-icon',
tooltip: '<b>Quick Tips</b><br/>Icon only button with tooltip'
}, '-');
var scrollMenu = new Ext.menu.Menu();
for (var i = 0; i < 50; ++i){
scrollMenu.add({
text: 'Item ' + (i + 1)
});
}
tb.add(new Ext.form.TextField());
// scrollable menu
tb.add({
scale: 'large',
icon: 'preview.png',
cls: 'x-btn-text-icon',
text: 'Scrolling Menu',
menu: scrollMenu
});
// add a combobox to the toolbar
var combo = new Ext.form.ComboBox({
store: store,
displayField: 'state',
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText:'Select a state...',
selectOnFocus:true,
width:135
});
tb.addField(combo);
tb.add({
text: 'Another'
}, {
text: 'Yet another'
}, {
text: 'Still another'
}, {
text: 'The last one!'
});
// sample static data for the store
var myData = [
['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am'],
['American Express Company',52.55,0.01,0.02,'9/1 12:00am'],
['American International Group, Inc.',64.13,0.31,0.49,'9/1 12:00am'],
['AT&T Inc.',31.61,-0.48,-1.54,'9/1 12:00am'],
['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],
['Caterpillar Inc.',67.27,0.92,1.39,'9/1 12:00am'],
['Citigroup, Inc.',49.37,0.02,0.04,'9/1 12:00am'],
['E.I. du Pont de Nemours and Company',40.48,0.51,1.28,'9/1 12:00am'],
['Exxon Mobil Corp',68.1,-0.43,-0.64,'9/1 12:00am'],
['General Electric Company',34.14,-0.08,-0.23,'9/1 12:00am'],
['General Motors Corporation',30.27,1.09,3.74,'9/1 12:00am'],
['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],
['Honeywell Intl Inc',38.77,0.05,0.13,'9/1 12:00am'],
['Intel Corporation',19.88,0.31,1.58,'9/1 12:00am'],
['International Business Machines',81.41,0.44,0.54,'9/1 12:00am'],
['Johnson & Johnson',64.72,0.06,0.09,'9/1 12:00am'],
['JP Morgan & Chase & Co',45.73,0.07,0.15,'9/1 12:00am'],
['McDonald\'s Corporation',36.76,0.86,2.40,'9/1 12:00am'],
['Merck & Co., Inc.',40.96,0.41,1.01,'9/1 12:00am'],
['Microsoft Corporation',25.84,0.14,0.54,'9/1 12:00am'],
['Pfizer Inc',27.96,0.4,1.45,'9/1 12:00am'],
['The Coca-Cola Company',45.07,0.26,0.58,'9/1 12:00am'],
['The Home Depot, Inc.',34.64,0.35,1.02,'9/1 12:00am'],
['The Procter & Gamble Company',61.91,0.01,0.02,'9/1 12:00am'],
['United Technologies Corporation',63.26,0.55,0.88,'9/1 12:00am'],
['Verizon Communications',35.57,0.39,1.11,'9/1 12:00am'],
['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']
];
/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val){
if(val > 0){
return '<span style="color:green;">' + val + '</span>';
}else if(val < 0){
return '<span style="color:red;">' + val + '</span>';
}
return val;
}
/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val){
if(val > 0){
return '<span style="color:green;">' + val + '%</span>';
}else if(val < 0){
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}
// create the data store
var store = new Ext.data.ArrayStore({
fields: [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]
});
// manually load local data
store.loadData(myData);
// create the Grid
var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{id:'company',header: 'Company', width: 160, sortable: true, dataIndex: 'company'},
{header: 'Price', width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},
{header: 'Change', width: 75, sortable: true, renderer: change, dataIndex: 'change'},
{header: '% Change', width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},
{header: 'Last Updated', width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
],
stripeRows: true,
autoExpandColumn: 'company',
border: false
});
new Ext.Window({
title: 'Test Float Toolbar',
height: 300,
width: 600,
tbar: tb,
layout: 'fit',
items: grid
}).show();
// functions to display feedback
function onButtonClick(btn){
Ext.example.msg('Button Click','You clicked the "{0}" button.', btn.text);
}
function onItemClick(item){
Ext.example.msg('Menu Click', 'You clicked the "{0}" menu item.', item.text);
}
function onItemCheck(item, checked){
Ext.example.msg('Item Check', 'You {1} the "{0}" menu item.', item.text, checked ? 'checked' : 'unchecked');
}
function onItemToggle(item, pressed){
Ext.example.msg('Button Toggled', 'Button "{0}" was toggled to {1}.', item.text, pressed);
}
var it = [];
for (var i = 0; i < 30; i++) {
it.push({
xtype: 'box',
autoEl: {
cls: 'test-item',
cn: [{
cls: 'test-item-inner'
}, {
cls: 'test-item-desc',
html: 'Item ' + (i + 1)
}]
}
});
}
new Ext.Window({
title: 'Flow Layout',
x: 100,
y: 100,
width: 314,
height: 521,
autoScroll: true,
layout: {
type: 'float',
animate: true
},
items: it,
bbar: {
xtype: 'container',
layout: {
type: 'hbox'
},
cls: 'x-toolbar',
style: {
overflow: 'hidden',
paddingLeft: 0,
paddingRight: 0,
},
defaultType: 'container',
items: [{
flex: 1,
autoHeight: true,
layout: {
type: 'float',
padding: '0 0 0 2'
},
items: {
xtype: 'button',
text: 'Left Button'
}
}, {
xtype: 'button',
text: 'Centre Button'
}, {
flex: 1,
autoHeight: true,
layout: {
type: 'float',
horizontalAlign: 'right',
padding: '0 2 0 0'
},
items: {
xtype: 'button',
text: 'Right Button'
}
}]
}
}).show();
it = [];
it.push({
xtype: 'button',
iconCls: 'test-button',
text: '1. First Button',
width: 140,
height: 56
});
it.push({
xtype: 'button',
iconCls: 'test-button',
text: '2. Second longer Button...',
width: 200,
height: 56,
clear: 'right'
});
it.push({
xtype: 'button',
iconCls: 'test-button',
text: '3. Third really, really long Button',
width: 240,
height: 100
});
it.push({
xtype: 'button',
iconCls: 'test-button',
text: 'Number 4',
width: 120,
height: 56,
verticalAlign: 'bottom'
});
it.push({
xtype: 'button',
text: '20px Margins around the great big 5th button!',
width: 240,
height: 100,
clear: 'right',
style: {
margin: '20px'
}
});
it.push({
xtype: 'button',
iconCls: 'test-button',
text: 'Number 6',
width: 120,
height: 56
});
it.push({
xtype: 'button',
text: '7th a wide, short button',
width: 120,
verticalAlign: 'top'
});
new Ext.Window({
title: 'Flow Layout',
x: 500,
y: 100,
width: 500,
height: 400,
autoScroll: true,
layout: {
type: 'float',
horizontalAlign: 'justify',
animate: true
},
items: it
}).show();
});
</script>
</head>
<body>
<h1>FloatLayout Toolbar with Menus</h1>
<p>The js is inline.</p>
</body>
</html>