khebs@live.com
8 May 2011, 9:42 AM
Yet another ribbon for ExtJS 4. Experimental UX.
- FIXME: Some CSS Problem with Firefox Chrome in XP. Specifically in ButtonGroups does not properly aligns the height with other groups if it has only 1 item or a menu button, etc. Please experiment, if you think you fixed it, please post back your magic solution here.
/**
* @class App.lib.ux.Ribbon
* @extend Ext.tab.Panel
*/
Ext.define('App.lib.ux.Ribbon', {
extend: 'Ext.tab.Panel',
alias: 'widget.appuxribbon',
cls: 'ui-ribbonbar',
activeTab: 0,
plain: true,
unstyled: true,
margin: '5 0 0 0',
autoHeight: true,
addTab: function (config, focus) {
var tab = this.add(config);
if (focus === true) this.setActiveTab(tab);
},
initComponent: function () {
this.callParent(arguments);
}
});
/**
* @class App.lib.ux.RibbonTab
* @extend Ext.tab.Tab
*/
Ext.define('App.lib.ux.RibbonTab', {
extend: 'Ext.panel.Panel',
alias: 'widget.appuxribbontab',
unstyled: true,
layout: 'hbox',
title: 'Untitled',
defaults: {
xtype: 'buttongroup',
headerPosition: 'bottom',
margins: '1 0 3 3'
},
initComponent: function () {
this.callParent(arguments);
this.on('added', function (o, c, i) {
Ext.each(this.items.items, function (btnGroups) {
Ext.each(btnGroups.items.items, function (item) {
if (item.scale !== 'small') {
var text = String(item.text);
if (text.indexOf('\n') != -1) { // has \n ?
text = text.replace('\n', '<br/>');
} else if (text.indexOf(' ') != -1) {
text = text.replace(/[ +]/gi, '<br/>');
} else {
if (!item.menu || item.arrowAlign !== 'bottom')
item.cls = 'x-btn-as-arrow';
}
if (item.setText)
item.setText(text);
}
});
});
});
this.on('render', function () {
this.doLayout(true);
});
}
});
The CSS
.ui-ribbonbar
{
border-color: #99BBE8;
background-image: none;
background-color: #DFE9F5;
background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(0%,#DFE9F5),color-stop(100%,#D3E1F1));
background-image: -moz-linear-gradient(top,#DFE9F5,#D3E1F1);
background-image: linear-gradient(top,#DFE9F5,#D3E1F1);
border-bottom: 1px solid #99BBE8 !important;
}
.ui-ribbonbar .x-btn-as-arrow em
{
display: block;
background-color: transparent;
padding-bottom: 15px;
font-size: 1px!important;
}
.x-chrome .ui-ribbonbar .x-btn-as-arrow em
{
padding-bottom: 13px;
}
.ui-ribbonbar .x-tab-bar-strip-default-plain-horizontal
{
height: 0px !important;
}
.ui-ribbonbar .x-tab-default-top
{
background-image: none;
background-color: transparent;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
-o-box-shadow: white 0 1px 0 0 inset,white -1px 0 0 0 inset,white 1px 0 0 0 inset;
border: 1px solid transparent;
}
.ui-ribbonbar .x-tab-default-top
{
margin-left: 2px !important;
}
.ui-ribbonbar .x-tab-default-closable
{
padding-right: 10px;
}
.ui-ribbonbar .x-tab-close-btn
{
font-size: 0px !important;
text-indent: -999px;
}
.ui-ribbonbar .x-tab-top-active
{
border: 1px solid #8DB2E3;
background-image: none;
background-color: #DFE9F5;
background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(30%,white),color-stop(100%,#DFE9F5));
background-image: -moz-linear-gradient(top,white,#F5F9FE 30%,#DEECFD 100%);
background-image: linear-gradient(top,white,#F5F9FE 30%,#DEECFD 100%);
}
.ui-ribbonbar .x-tab-default-top-active
{
border-bottom-color: #DFE9F5 !important;
}
.ui-ribbonbar .x-tab em
{
padding: 0 10px;
}
.ui-ribbonbar .x-tab em button
{
font-weight: normal !important;
}
.ui-ribbonbar .x-toolbar-default
{
border-color: #99BBE8;
background-image: none;
background-color: #D3E1F1;
background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(0%,#DFE9F5),color-stop(100%,#D3E1F1));
background-image: -moz-linear-gradient(top,#DFE9F5,#D3E1F1);
background-image: linear-gradient(top,#DFE9F5,#D3E1F1);
}
Sample Usage:
Make Ribbon Tabs
/**
* @class App.view.employees.list.Ribbon
* @extend App.lib.ux.RibbonTab
*/
Ext.define('App.view.employees.list.Ribbon', {
extend: 'App.lib.ux.RibbonTab',
alias: 'widget.employeeslistribbon',
title: 'Employees',
closable: false,
items: [{
title: 'Data',
items: [{
text: 'List of All\nEmployees',
iconCls: 'icon-ribbon-address32',
scale: 'large',
iconAlign: 'top',
action: 'list'
}]
}, {
title: 'New',
columns: 3,
items: [{
text: 'New Employee',
scale: 'large',
iconAlign: 'top',
iconCls: 'icon-ribbon-contact32',
action: 'newemployee'
}, {
text: 'New Department',
scale: 'large',
iconAlign: 'top',
iconCls: 'icon-ribbon-inbox32'
}, {
text: 'Archived Documents',
scale: 'large',
iconAlign: 'top',
iconCls: 'icon-ribbon-docs32'
}]
}, {
title: 'Action',
defaults: {
scale: 'large',
iconAlign: 'top'
},
items: [{
text: 'Delete',
action: 'delete',
iconCls: 'icon-ribbon-deletecontact32'
}, {
text: 'Refresh All',
iconCls: 'icon-ribbon-refresh32'
}]
}, {
title: 'Reports',
defaults: {
scale: 'large',
iconAlign: 'top'
},
items: [{
text: 'Available Reports',
iconCls: 'icon-ribbon-report32'
}]
}]
});
Ribbon Bar - which is probably the north region / dock: 'top' of your viewport / window
/**
* @class App.view.ui.RibbonBar
* @extend Ext.tab.Panel
*/
Ext.define('App.view.ui.RibbonBar', {
extend: 'App.lib.ux.Ribbon',
alias: 'widget.uiribbonbar',
initComponent: function () {
this.callParent(arguments);
}
});
...
Ext.Viewport({
...
items: [{
xtype: 'uiribbonbar', region: 'north'
}]
...
});
In your controller
/**
* @class App.controller.Employees
* @extend Ext.app.Controller
*/
Ext.define('App.controller.Employees', {
extend: 'Ext.app.Controller',
views: [
'employees.list.Ribbon',
...
],
refs: [
// List
{ ref: 'listRibbon', selector: 'employeeslistribbon', xtype: 'employeeslistribbon', autoCreate: true }.
{ ref: 'ribbonBar', selector: 'uiribbonbar' }.
...
...
],
// private
init: function () {
this.control({
'employeeslistribbon': {
activate: this.showList
},
...
...
});
},
// private
onLaunch: function () {
this.showList();
},
/**
* Shows Employee Listings
* @method showList
*/
showList: function () {
var rb = this.getRibbonBar(), ribbon = this.getListRibbon();
...
if (!ribbon.rendered) rb.add(ribbon);
...
//rb.setActiveTab(ribbon);
},
...
...
});
- FIXME: Some CSS Problem with Firefox Chrome in XP. Specifically in ButtonGroups does not properly aligns the height with other groups if it has only 1 item or a menu button, etc. Please experiment, if you think you fixed it, please post back your magic solution here.
/**
* @class App.lib.ux.Ribbon
* @extend Ext.tab.Panel
*/
Ext.define('App.lib.ux.Ribbon', {
extend: 'Ext.tab.Panel',
alias: 'widget.appuxribbon',
cls: 'ui-ribbonbar',
activeTab: 0,
plain: true,
unstyled: true,
margin: '5 0 0 0',
autoHeight: true,
addTab: function (config, focus) {
var tab = this.add(config);
if (focus === true) this.setActiveTab(tab);
},
initComponent: function () {
this.callParent(arguments);
}
});
/**
* @class App.lib.ux.RibbonTab
* @extend Ext.tab.Tab
*/
Ext.define('App.lib.ux.RibbonTab', {
extend: 'Ext.panel.Panel',
alias: 'widget.appuxribbontab',
unstyled: true,
layout: 'hbox',
title: 'Untitled',
defaults: {
xtype: 'buttongroup',
headerPosition: 'bottom',
margins: '1 0 3 3'
},
initComponent: function () {
this.callParent(arguments);
this.on('added', function (o, c, i) {
Ext.each(this.items.items, function (btnGroups) {
Ext.each(btnGroups.items.items, function (item) {
if (item.scale !== 'small') {
var text = String(item.text);
if (text.indexOf('\n') != -1) { // has \n ?
text = text.replace('\n', '<br/>');
} else if (text.indexOf(' ') != -1) {
text = text.replace(/[ +]/gi, '<br/>');
} else {
if (!item.menu || item.arrowAlign !== 'bottom')
item.cls = 'x-btn-as-arrow';
}
if (item.setText)
item.setText(text);
}
});
});
});
this.on('render', function () {
this.doLayout(true);
});
}
});
The CSS
.ui-ribbonbar
{
border-color: #99BBE8;
background-image: none;
background-color: #DFE9F5;
background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(0%,#DFE9F5),color-stop(100%,#D3E1F1));
background-image: -moz-linear-gradient(top,#DFE9F5,#D3E1F1);
background-image: linear-gradient(top,#DFE9F5,#D3E1F1);
border-bottom: 1px solid #99BBE8 !important;
}
.ui-ribbonbar .x-btn-as-arrow em
{
display: block;
background-color: transparent;
padding-bottom: 15px;
font-size: 1px!important;
}
.x-chrome .ui-ribbonbar .x-btn-as-arrow em
{
padding-bottom: 13px;
}
.ui-ribbonbar .x-tab-bar-strip-default-plain-horizontal
{
height: 0px !important;
}
.ui-ribbonbar .x-tab-default-top
{
background-image: none;
background-color: transparent;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
-o-box-shadow: white 0 1px 0 0 inset,white -1px 0 0 0 inset,white 1px 0 0 0 inset;
border: 1px solid transparent;
}
.ui-ribbonbar .x-tab-default-top
{
margin-left: 2px !important;
}
.ui-ribbonbar .x-tab-default-closable
{
padding-right: 10px;
}
.ui-ribbonbar .x-tab-close-btn
{
font-size: 0px !important;
text-indent: -999px;
}
.ui-ribbonbar .x-tab-top-active
{
border: 1px solid #8DB2E3;
background-image: none;
background-color: #DFE9F5;
background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(30%,white),color-stop(100%,#DFE9F5));
background-image: -moz-linear-gradient(top,white,#F5F9FE 30%,#DEECFD 100%);
background-image: linear-gradient(top,white,#F5F9FE 30%,#DEECFD 100%);
}
.ui-ribbonbar .x-tab-default-top-active
{
border-bottom-color: #DFE9F5 !important;
}
.ui-ribbonbar .x-tab em
{
padding: 0 10px;
}
.ui-ribbonbar .x-tab em button
{
font-weight: normal !important;
}
.ui-ribbonbar .x-toolbar-default
{
border-color: #99BBE8;
background-image: none;
background-color: #D3E1F1;
background-image: -webkit-gradient(linear,50% 0,50% 100%,color-stop(0%,#DFE9F5),color-stop(100%,#D3E1F1));
background-image: -moz-linear-gradient(top,#DFE9F5,#D3E1F1);
background-image: linear-gradient(top,#DFE9F5,#D3E1F1);
}
Sample Usage:
Make Ribbon Tabs
/**
* @class App.view.employees.list.Ribbon
* @extend App.lib.ux.RibbonTab
*/
Ext.define('App.view.employees.list.Ribbon', {
extend: 'App.lib.ux.RibbonTab',
alias: 'widget.employeeslistribbon',
title: 'Employees',
closable: false,
items: [{
title: 'Data',
items: [{
text: 'List of All\nEmployees',
iconCls: 'icon-ribbon-address32',
scale: 'large',
iconAlign: 'top',
action: 'list'
}]
}, {
title: 'New',
columns: 3,
items: [{
text: 'New Employee',
scale: 'large',
iconAlign: 'top',
iconCls: 'icon-ribbon-contact32',
action: 'newemployee'
}, {
text: 'New Department',
scale: 'large',
iconAlign: 'top',
iconCls: 'icon-ribbon-inbox32'
}, {
text: 'Archived Documents',
scale: 'large',
iconAlign: 'top',
iconCls: 'icon-ribbon-docs32'
}]
}, {
title: 'Action',
defaults: {
scale: 'large',
iconAlign: 'top'
},
items: [{
text: 'Delete',
action: 'delete',
iconCls: 'icon-ribbon-deletecontact32'
}, {
text: 'Refresh All',
iconCls: 'icon-ribbon-refresh32'
}]
}, {
title: 'Reports',
defaults: {
scale: 'large',
iconAlign: 'top'
},
items: [{
text: 'Available Reports',
iconCls: 'icon-ribbon-report32'
}]
}]
});
Ribbon Bar - which is probably the north region / dock: 'top' of your viewport / window
/**
* @class App.view.ui.RibbonBar
* @extend Ext.tab.Panel
*/
Ext.define('App.view.ui.RibbonBar', {
extend: 'App.lib.ux.Ribbon',
alias: 'widget.uiribbonbar',
initComponent: function () {
this.callParent(arguments);
}
});
...
Ext.Viewport({
...
items: [{
xtype: 'uiribbonbar', region: 'north'
}]
...
});
In your controller
/**
* @class App.controller.Employees
* @extend Ext.app.Controller
*/
Ext.define('App.controller.Employees', {
extend: 'Ext.app.Controller',
views: [
'employees.list.Ribbon',
...
],
refs: [
// List
{ ref: 'listRibbon', selector: 'employeeslistribbon', xtype: 'employeeslistribbon', autoCreate: true }.
{ ref: 'ribbonBar', selector: 'uiribbonbar' }.
...
...
],
// private
init: function () {
this.control({
'employeeslistribbon': {
activate: this.showList
},
...
...
});
},
// private
onLaunch: function () {
this.showList();
},
/**
* Shows Employee Listings
* @method showList
*/
showList: function () {
var rb = this.getRibbonBar(), ribbon = this.getListRibbon();
...
if (!ribbon.rendered) rb.add(ribbon);
...
//rb.setActiveTab(ribbon);
},
...
...
});