I have tabpanel:
{
xtype: 'tabpanel',
tabPosition: 'top', // it's default value
items: [/*tabs*/]
}
And some button which changes layout:
{
xtype: 'button',
text: 'Change layout',
handler: function (btn) {
var layout = App.helper.Registry.get('layout');
if (layout === this.getCurrentLayout()) {
return;
}
if (layout === 'horizontal') {
newContainer = this.down('container[cls~=split-horizontal]');//hbox laout
oldContainer = this.down('container[cls~=split-vertical]');//vbox layout
tabPanel.tabPosition = 'top';
} else {
newContainer = this.down('container[cls~=split-vertical]');
oldContainer = this.down('container[cls~=split-horizontal]');
tabPanel.tabPosition = 'bottom';
}
oldContainer.remove(somePanel, false);
oldContainer.remove(tabPanel, false);
newContainer.insert(0, somePanel);
newContainer.insert(2, tabPanel);
newContainer.show();
oldContainer.hide();
}
When I change layout, me also need change the position of the tabs.
Of course changing config property tabPosition has no effect.
How i can switch tabPosition dynamically?
I'm afraid in case of tabpanel the only way is to destroy the current panel and recreate it from config object with altered tabPosition setting. You can use cloneConfig() method to get config object from existing panel.
Related
I need to create custom legend for my donut chart using ChartJS library.
I have created donut with default legend provided by ChartJS but I need some modification.
I would like to have value above the car name. Also I don't like sticky legend I want to have it separate from donut so I can change the style for fonts, boxes (next to the text "Audi" for example)
I know there is some Legend generator but I'm not sure how to use it with VueJS - because I'm using VueJS as a framework
This is how my legend looks like now - http://imgur.com/a/NPUoi
My code:
From Vue component where I import a donut component:
<div class="col-md-6">
<div class="chart-box">
<p class="chart-title">Cars</p>
<donut-message id="chart-parent"></donut-message>
</div>
</div>
Javascript:
import { Doughnut } from 'vue-chartjs'
export default Doughnut.extend({
ready () {
Chart.defaults.global.tooltips.enabled = false;
Chart.defaults.global.legend.display = false;
this.render({
labels: ['Audi','BMW','Ford','Opel'],
datasets: [
{
label: 'Cars',
backgroundColor: ['#35d89b','#4676ea','#fba545','#e6ebfd'],
data: [40, 30, 20, 10]
}
]
},
{
responsive: true,
cutoutPercentage: 75,
legend: {
display: true,
position: "right",
fullWidth: true,
labels: {
boxWidth: 10,
fontSize: 14
}
},
animation: {
animateScale: true
}
})
}
});
I'm having the same problem trying to understand the documentation and this link might clarify the process of customize the legends:
https://codepen.io/michiel-nuovo/pen/RRaRRv
The trick is to track a callback to build your own HTML structure and return this new structure to ChartJS.
Inside the options object:
legendCallback: function(chart) {
var text = [];
text.push('<ul class="' + chart.id + '-legend">');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li><span style="background-color:' +
chart.data.datasets[0].backgroundColor[i] + '">');
if (chart.data.labels[i]) {
text.push(chart.data.labels[i]);
}
text.push('</span></li>');
}
text.push('</ul>');
return text.join("");
}
Second, you need a container to insert the new html and using the method myChart.generateLegend() to get the customized html:
$("#your-legend-container").html(myChart.generateLegend());
After that, if you need, track down the events:
$("#your-legend-container").on('click', "li", function() {
myChart.data.datasets[0].data[$(this).index()] += 50;
myChart.update();
console.log('legend: ' + data.datasets[0].data[$(this).index()]);
});
$('#myChart').on('click', function(evt) {
var activePoints = myChart.getElementsAtEvent(evt);
var firstPoint = activePoints[0];
if (firstPoint !== undefined) {
console.log('canvas: ' +
data.datasets[firstPoint._datasetIndex].data[firstPoint._index]);
}
else {
myChart.data.labels.push("New");
myChart.data.datasets[0].data.push(100);
myChart.data.datasets[0].backgroundColor.push("red");
myChart.options.animation.animateRotate = false;
myChart.options.animation.animateScale = false;
myChart.update();
$("#your-legend-container").html(myChart.generateLegend());
}
}
Another solution that I found, if you don't need to change the HTMl structure inside the legend, you can just insert the same HTML in your legend container and customize it by CSS, check this another link:
http://jsfiddle.net/vrwjfg9z/
Hope it works for you.
You can extract the legend markup.
data () {
return {
legendMarkup: ''
}
},
ready () {
this.legendMarkup = this._chart.generateLegend()
}
And in your template you can output it.
<div class="legend" ref="legend" v-html="legendMarkup"></div>
this._chart is the internal chartjs instance in vue-chartjs. So you can call all chartjs methods which are not exposed by vue-chartjs api over it.
However you can also use the legend generator. The usage is the same in vue. You can pass in the options, use callbacks etc.
please check this documentation
.
Legend Configuration
The chart legend displays data about the datasets that area appearing on the chart.
Configuration options
Position of the legend. Options are:
'top'
'left'
'bottom'
'right'
Legend Item Interface
Items passed to the legend onClick function are the ones returned from labels.generateLabels. These items must implement the following interface.
{
// Label that will be displayed
text: String,
// Fill style of the legend box
fillStyle: Color,
// If true, this item represents a hidden dataset. Label will be rendered with a strike-through effect
hidden: Boolean,
// For box border. See https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap
lineCap: String,
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
lineDash: Array[Number],
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
lineDashOffset: Number,
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
lineJoin: String,
// Width of box border
lineWidth: Number,
// Stroke style of the legend box
strokeStyle: Color
// Point style of the legend box (only used if usePointStyle is true)
pointStyle: String
}
Example
The following example will create a chart with the legend enabled and turn all of the text red in color.
var chart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
legend: {
display: true,
labels: {
fontColor: 'rgb(255, 99, 132)'
}
}
}
});
Custom On Click Actions
It can be common to want to trigger different behaviour when clicking an item in the legend. This can be easily achieved using a callback in the config object.
The default legend click handler is:
function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
var meta = ci.getDatasetMeta(index);
// See controller.isDatasetVisible comment
meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
// We hid a dataset ... rerender the chart
ci.update();
}
Lets say we wanted instead to link the display of the first two datasets. We could change the click handler accordingly.
var defaultLegendClickHandler = Chart.defaults.global.legend.onClick;
var newLegendClickHandler = function (e, legendItem) {
var index = legendItem.datasetIndex;
if (index > 1) {
// Do the original logic
defaultLegendClickHandler(e, legendItem);
} else {
let ci = this.chart;
[ci.getDatasetMeta(0),
ci.getDatasetMeta(1)].forEach(function(meta) {
meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
});
ci.update();
}
};
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
legend: {
}
}
});
Now when you click the legend in this chart, the visibility of the first two datasets will be linked together.
HTML Legends
Sometimes you need a very complex legend. In these cases, it makes sense to generate an HTML legend. Charts provide a generateLegend() method on their prototype that returns an HTML string for the legend.
To configure how this legend is generated, you can change the legendCallback config property.
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
legendCallback: function(chart) {
// Return the HTML string here.
}
}
});
I've got a bug which needs fixing in my iOS app developed on Appcelerator Titanium.
I've been using customTabBar (available on GitHub) to create a bespoke tabBar and it works great!
The only small issue is that it removes the option to tab on the icons and return to the root window (like a proper native tabBar would do in iOS).
So if I drill down 3 or 4 windows in my app, tapping the tab icon does nothing, I have to navigate back to the beginning by tapping back multiple times.
Here is the full customTabBar.js script I am using:
CustomTabBar = function(settings) {
var tabBarItems = [];
var tabCurrent = 2;
var resetTabs = function() {
for(var i = 0; i < tabBarItems.length; i++) {
// Clear all the images to make sure only
// one is shown as selected
tabBarItems[i].image = tabBarItems[i].backgroundImage;
}
};
var assignClick = function(tabItem) {
tabItem.addEventListener('click', function(e) {
// Just fetching the 'i' variable from the loop
var pos = e.source.pos;
if (tabCurrent == pos) {
// TODO
// Change back to root window, like the native tab action.
// code must go in here
return false;
}
// Switch to the tab associated with the image pressed
settings.tabBar.tabs[pos].active = true;
tabCurrent = pos;
// Reset all the tab images
resetTabs();
// Set the current tab as selected
tabBarItems[pos].image = settings.imagePath + settings.items[pos].selected;
});
};
// Create the container for our tab items
var customTabBar = Ti.UI.createWindow({
height: 48,
backgroundImage:'images/tabbarbackground.png',
bottom: 0
});
for(var i = 0; i < settings.items.length; i++) {
// Go through each item and create an imageView
tabBarItems[i] = Titanium.UI.createImageView({
// background is the default image
backgroundImage: settings.imagePath + settings.items[i].image,
width: settings.width,
height: settings.height,
left: settings.width * i
});
// Pass the item number (used later for changing tabs)
tabBarItems[i].pos = i;
assignClick(tabBarItems[i]);
// Add to the container window
customTabBar.add(tabBarItems[i]);
}
// Display the container and it's items
customTabBar.open();
// Set the first item as current :)
resetTabs();
//tabBarItems[0].image = settings.imagePath + settings.items[0].selected;
tabBarItems[2].image = settings.imagePath + settings.items[2].selected;
return {
hide: function() { customTabBar.hide(); },
show: function() { customTabBar.show(); }
};
};
The function that contains the bit I need adding is already marked up, but is just empty. Here it is:
var assignClick = function(tabItem) {
tabItem.addEventListener('click', function(e) {
// Just fetching the 'i' variable from the loop
var pos = e.source.pos;
if (tabCurrent == pos) {
// TODO
// Change back to root window, like the native tab action.
// code must go in here
return false;
}
// Switch to the tab associated with the image pressed
settings.tabBar.tabs[pos].active = true;
tabCurrent = pos;
// Reset all the tab images
resetTabs();
// Set the current tab as selected
tabBarItems[pos].image = settings.imagePath + settings.items[pos].selected;
});
};
customTabBar places a window (really, just a view) over the existing tab bar. Then it handles clicks that come through. But you must handle the click events to switch between tabs, and as you have noted, track all of the windows that are on the stack.
But you know what? You're working too hard. The platform already does all that for you.
Pass click events through (by disabling touch on the overlay), and the underlying tab group will work its own magic. Then all you need to do is update the UI with the tab group's focus event (evt.index is the focused tab, and evt.previousIndex the blurred).
app.js:
Ti.include('overrideTabs.js');
/*
This is a typical new project -- a tab group with three tabs.
*/
var tabGroup = Ti.UI.createTabGroup();
/*
Tab 1.
*/
var win1 = Ti.UI.createWindow({ title: 'Tab 1', backgroundColor: '#fff' });
var tab1 = Ti.UI.createTab({
backgroundImage: 'appicon.png',
window: win1
});
var button1 = Ti.UI.createButton({
title: 'Open Sub Window',
width: 200, height: 40
});
button1.addEventListener('click', function (evt) {
tab1.open(Ti.UI.createWindow({ title: 'Tab 1 Sub Window', backgroundColor: '#fff' }));
});
win1.add(button1);
tabGroup.addTab(tab1);
/*
Tab 2.
*/
tabGroup.addTab(Ti.UI.createTab({
backgroundImage: 'appicon.jpg',
window: Ti.UI.createWindow({ title: 'Tab 2', backgroundColor: '#fff' })
}));
/*
Tab 3.
*/
tabGroup.addTab(Ti.UI.createTab({
backgroundImage: 'appicon.png',
window: Ti.UI.createWindow({ title: 'Tab 3', backgroundColor: '#fff' })
}));
/*
Now call the overrideTabs function, and we're done!
*/
overrideTabs(
tabGroup, // The tab group
{ backgroundColor: '#f00' }, // View parameters for the background
{ backgroundColor: '#999', color: '#000', style: 0 }, // View parameters for selected tabs
{ backgroundColor: '#333', color: '#888', style: 0 } // View parameters for deselected tabs
);
tabGroup.open();
overrideTabs.js:
/**
* Override a tab group's tab bar on iOS.
*
* NOTE: Call this function on a tabGroup AFTER you have added all of your tabs to it! We'll look at the tabs that exist
* to generate the overriding tab bar view. If your tabs change, call this function again and we'll update the display.
*
* #param tabGroup The tab group to override
* #param backgroundOptions The options for the background view; use properties like backgroundColor, or backgroundImage.
* #param selectedOptions The options for a selected tab button.
* #param deselectedOptions The options for a deselected tab button.
*/
function overrideTabs(tabGroup, backgroundOptions, selectedOptions, deselectedOptions) {
// a bunch of our options need to default to 0 for everything to position correctly; we'll do it en mass:
deselectedOptions.top = deselectedOptions.bottom
= selectedOptions.top = selectedOptions.bottom
= backgroundOptions.left = backgroundOptions.right = backgroundOptions.bottom = 0;
// create the overriding tab bar using the passed in background options
backgroundOptions.height = 50;
var background = Ti.UI.createView(backgroundOptions);
// pass all touch events through to the tabs beneath our background
background.touchEnabled = false;
// create our individual tab buttons
var increment = 100 / tabGroup.tabs.length;
deselectedOptions.width = selectedOptions.width = increment + '%';
for (var i = 0, l = tabGroup.tabs.length; i < l; i++) {
var tab = tabGroup.tabs[i];
// position our views over the tab.
selectedOptions.left = deselectedOptions.left = increment * i + '%';
// customize the selected and deselected based on properties in the tab.
selectedOptions.title = deselectedOptions.title = tab.title;
if (tab.backgroundImage) {
selectedOptions.backgroundImage = deselectedOptions.backgroundImage = tab.backgroundImage;
}
if (tab.selectedBackgroundImage) {
selectedOptions.backgroundImage = tab.selectedBackgroundImage;
}
if (tab.deselectedBackgroundImage) {
deselectedOptions.backgroundImage = tab.deselectedBackgroundImage;
}
selectedOptions.visible = false;
background.add(tab.deselected = Ti.UI.createButton(deselectedOptions));
background.add(tab.selected = Ti.UI.createButton(selectedOptions));
}
// update the tab group, removing any old overrides
if (tabGroup.overrideTabs) {
tabGroup.remove(tabGroup.overrideTabs);
}
else {
tabGroup.addEventListener('focus', overrideFocusTab);
}
tabGroup.add(background);
tabGroup.overrideTabs = background;
}
function overrideFocusTab(evt) {
if (evt.previousIndex >= 0) {
evt.source.tabs[evt.previousIndex].selected.visible = false;
}
evt.tab.selected.visible = true;
}
https://gist.github.com/853935
In ExtJS 4, by default, the dragdrop proxy is displayed to the right bottom position of the mouse position during drag operation. Let say I click into the center of my target and move my mouse by 1 px. I would like the proxy to itself over the original element, shifted by 1 px.
Basically, I need proxy to behave like the example at http://jqueryui.com/demos/draggable/#sortable. In this example the proxy is over the original element and then moves around when the mouse is dragged.
How can I achieve this?
Here is sample code illustrating the problem when dragging a custom widget.
Ext.onReady(function(){
var hewgt = Ext.define('Demo.widget.Complex', {
extend: 'Ext.panel.Panel',
alias: 'widget.complex',
frameHeader: false,
draggable: false,
layout: 'table',
initComponent: function() {
this.callParent(arguments);
var txtFld;
this.superclass.add.call(this, txtFld = new Ext.form.field.Text({fieldLabel:'test'}));
this.superclass.add.call(this, new Ext.button.Button({text:'Save'}));
}
});
Ext.define('Demo.dd.DragSource', {
extend: 'Ext.dd.DragSource',
b4MouseDown: function(e) {
this.diffX = e.getX() - this.el.getX();
this.diffY = e.getY() - this.el.getY();
this.superclass.setDelta.call(this, 0, 0);
},
getTargetCoord: function(iPageX, iPageY) {
return {x: iPageX - this.diffX, y: iPageY - this.diffY};
}
});
var panel = Ext.create('Ext.panel.Panel', {
layout: 'absolute',
title: 'Navigation'
});
var vp = Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [panel]
});
var img = Ext.create('Demo.widget.Complex', { width: 400, height:100, x:20, y:20 });
panel.add(img);
new Demo.dd.DragSource(img.getEl());
img = Ext.create('Demo.widget.Complex', { width: 400, height:100, x:20, y:150 });
panel.add(img);
new Demo.dd.DragSource(img.getEl());
});
I am new to Ext JS.
Please let me know how can the dragged proxy be positioned correctly?
Thanks
I'm trying to make a drawing application with ExtJS4, the MVC-way.
For this, I want to make several widgets. This is my code for a widget:
VIEW:
Ext.define('VP.view.fields.Field' ,{
extend: 'Ext.draw.Sprite',
alias: 'widget.field',
constructor: function() {
var parentConfig = {
id: 'field',
fill: '#FFFF00',
type: 'rect',
width: '100%',
height: '100%',
x: 0,
y: 0
};
this.callParent([parentConfig]);
}
});
CONTROLLER:
Ext.define('VP.controller.Fields', {
extend: 'Ext.app.Controller',
views: [
'fields.Field'
],
init: function() {
console.log('Initialized Field controller!');
var me = this;
me.control({
'field': { //trying to control the widget.field, this fails
//'viewport > draw[surface]': { //this controls the surface successfully
//'viewport > draw[surface] > field': { //fails
click: this.addObject
}
});
},
addObject : function(event,el){
console.log(el);
//console.log(drawComponent);
}
});
How can I control this custom sprite? Can only Ext.components be controlled by a controller? (Ext.draw.Sprite doesn't extend Ext.component).
In addition to my previous answer, you could add the listener on the sprite and fire an event on some object. Then you could catch it in the controller.
Example:
spriteObj....{
listeners: {
click: {
var canvas = Ext.ComponentQuery.query('draw[id=something]')[0];
var sprite = this;
canvas.fireEvent('spriteclick',sprite);
}
}
}
In the controller:
init: function() {
console.log('Initialized Field controller!');
var me = this;
me.control({
'draw[id=something]': {
spriteclick: this.doSomething
}
});
},
doSomething: function (sprite) {
console.log(sprite);
}
I've been messing around with the same thing. It appears that you can't do it because it is an svg object that Ext just 'catches' and adds a few events to it. Because it doesn't have an actual alias (xtype) because it is not a component, it cannot be queried either. You have to do the listeners config on the sprite unfortunately.
Also, I tried doing the method like you have of extending the sprite. I couldn't get that to work, I assume because it is not a component.
I was able to keep this in the all in the controller because I draw the sprites in the controller. So, I can manually define the listeners in there and still use all the controller refs and such. Here's an example of one of my drawing functions:
drawPath: function(canvas,points,color,opacity,stroke,strokeWidth, listeners) {
// given an array of [x,y] coords relative to canvas axis, draws a path.
// only supports straight lines
if (typeof listeners == 'undefined' || listeners == "") {
listeners = null;
}
if (stroke == '' || strokeWidth == '' || typeof stroke == 'undefined' || typeof strokeWidth == 'undefined') {
stroke = null;
strokeWidth = null;
}
var path = path+"M"+points[0][0]+" "+points[0][1]+" "; // start svg path parameters with given array
for (i=1;i<points.length;i++) {
path = path+"L"+points[i][0]+" "+points[i][1]+" ";
}
path = path + "Z"; // end svg path params
var sprite = canvas.surface.add({
type: 'path',
opacity: opacity,
fill:color,
path: path,
stroke:stroke,
'stroke-width': strokeWidth,
listeners: listeners
}).show(true);
this.currFill = sprite;
}
You can see where I just pass in the parameter for the listeners and I can define the object elsewhere. You could do this in your own function or wherever in the controller. While the actual sprite should be in the view, this keeps them a little more dynamic and allows you to manipulate them a little easier.
how can I expand an ExtJS (version 3.3.1) Component, e.g. a Ext.Panel nested somewhere in the document hierarchy to "fullscreen" so that it takes up the whole browser window region? I guess I need to create an Ext.Viewport dynamically and reparent the component being "expanded", but I've had no success so far. Could someone provide a working sample?
Also, I'd like to be able to restore the component to its original place at some point later, if that's at all possible.
I tried the following:
new Ext.Button({ text: 'Fullscreen', renderTo : Ext.getBody(), onClick: function(){
var viewPort = new Ext.Viewport({
renderTo: Ext.getBody(),
layout: "fit",
items: [ panelToBeExpanded ]
});
viewPort.doLayout();
}});
which does not work very well. Upon clicking the button, the panel panelToBeExpanded seems to take up the viewport region, but only if there is no HTML in the BODY section, otherwise viewport is not fully expanded. Also, working with the reparented panel afterwards causes weird flicker in most browsers.
Is there a reliable way to universally (ideally temporarily) expand a component to the whole browser window?
UPDATE
Thanks to a suggestion in the comments, creating a new maximized Ext.Window seems to be a good solution. The second part is a bit tricky though - how to move the reparented component back to its original place in DOM (and ExtJS component hierarchy) once the window is closed?
Thanks for your help!
You could use Ext.Window.toggleMaximize method. I created a simple working example, check it out here
Pay attention that Ext.Window is maximized inside its rendering container, so if you use "renderTo" attribute and set it to some div inside your page Window will only be as big as div that contains it. That is why I used document body to render myWindow. Of course you could also use Ext.Window.x and Ext.Window.y configuration attributes to locate your window in wanted place.
This is a little late but stumbled upon this only now and remembered I had to do something similar and ended up overriding the text-area component which would automatically expand to full-screen on doubleclick by creating a copy of the component in a full-size window. On closing the values are automatically updated in the instantiating component which was hidden behind the full-screen window and hence never was taken out of the dom in the first place.
Here's my code I think it's fairly self-explanatory.
Hope it helps someone!
Rob.
/**
* Override for default Ext.form.TextArea. Growing to near full-screen/full-window on double-click.
*
* #author Rob Schmuecker (Ext forum name rob1308)
* #date September 13, 2010
*
* Makes all text areas enlargable by default on double-click - to prevent this behaviour set "popout:false" in the config
* By default the fieldLabel of the enhanced field is the fieldLabel of the popout - this can be set separately with "popoutLabel:'some string'" this will also inherit the same labelSeparator config value as that of the enhanced parent.
* The close text for the button defaults to "Close" but can be overriden by setting the "popoutClose:'some other text'" config
*/
Ext.override(Ext.form.TextArea, {
popout: true,
onRender: function(ct, position) {
if (!this.el) {
this.defaultAutoCreate = {
tag: "textarea",
style: "width:100px;height:60px;",
autocomplete: "off"
};
}
Ext.form.TextArea.superclass.onRender.call(this, ct, position);
if (this.grow) {
this.textSizeEl = Ext.DomHelper.append(document.body, {
tag: "pre",
cls: "x-form-grow-sizer"
});
if (this.preventScrollbars) {
this.el.setStyle("overflow", "hidden");
}
this.el.setHeight(this.growMin);
}
if (this.popout && !this.readOnly) {
if (!this.popoutLabel) {
this.popoutLabel = this.fieldLabel;
}
this.popoutClose = 'Close';
var field = this;
this.getEl().on('dblclick',
function() {
field.popoutTextArea(this.id);
});
};
},
popoutTextArea: function(elId) {
var field = this;
tBox = new Ext.form.TextArea({
popout: false,
anchor: '100% 100%',
labelStyle: 'font-weight:bold; font-size:14px;',
value: Ext.getCmp(elId).getValue(),
fieldLabel: field.popoutLabel,
labelSeparator: field.labelSeparator
});
viewSize = Ext.getBody().getViewSize();
textAreaWin = new Ext.Window({
width: viewSize.width - 50,
height: viewSize.height - 50,
closable: false,
draggable: false,
border: false,
bodyStyle: 'background-color:#badffd;',
//bodyBorder:false,
modal: true,
layout: 'form',
// explicitly set layout manager: override the default (layout:'auto')
labelAlign: 'top',
items: [tBox],
buttons: [{
text: field.popoutClose,
handler: function() {
Ext.getCmp(elId).setValue(tBox.getValue());
textAreaWin.hide(Ext.getCmp(elId).getEl(),
function(win) {
win.close();
});
}
}]
}).show(Ext.getCmp(elId).getEl());
}
});