Code:
Ext.AbstractComponent.override({
frameInfoRe: /ext-frame#(.+)"/,
getElConfig : function() {
var me = this,
autoEl = me.autoEl,
frameInfo = me.getFrameInfo(),
config = {
tag: 'div',
tpl: frameInfo ? me.initFramingTpl(frameInfo.table) : me.initRenderTpl()
},
protoEl = me.protoEl,
i, frameElNames, len, suffix, frameGenId, frameData;
me.initStyles(protoEl);
protoEl.writeTo(config);
protoEl.flush();
if (Ext.isString(autoEl)) {
config.tag = autoEl;
} else {
Ext.apply(config, autoEl); // harmless if !autoEl
}
// It's important to assign the id here as an autoEl.id could have been (wrongly) applied and this would get things out of sync
config.id = me.id;
if (config.tpl) {
// Use the framingTpl as the main content creating template. It will call out to this.applyRenderTpl(out, values)
if (frameInfo) {
frameElNames = me.frameElNames;
len = frameElNames.length;
config.tplData = frameData = me.getFrameRenderData();
frameData.renderData = me.initRenderData();
frameGenId = frameData.fgid;
// Add the childEls for each of the frame elements
for (i = 0; i < len; i++) {
suffix = frameElNames[i];
me.addChildEls({ name: 'frame' + suffix, id: frameGenId + suffix });
}
// Panel must have a frameBody
me.addChildEls({
name: 'frameBody',
id: frameGenId + 'MC'
});
} else {
config.tplData = me.initRenderData();
}
}
return config;
},
/**
* @private
* On render, reads an encoded style attribute, "filter" from the style of this Component's element.
* This information is memoized based upon the CSS class name of this Component's element.
* Because child Components are rendered as textual HTML as part of the topmost Container, a dummy div is inserted
* into the document to receive the document element's CSS class name, and therefore style attributes.
*/
getFrameInfo: function() {
// If native framing can be used, or this component is not going to be framed, then do not attempt to read CSS framing info.
if (Ext.supports.CSS3BorderRadius || !this.frame) {
return false;
}
var me = this,
frameInfoCache = me.frameInfoCache,
cls = me.getFramingInfoCls() + '-frameInfo',
frameInfo = frameInfoCache[cls],
max = Math.max,
styleEl, match, info, frameTop, frameRight, frameBottom, frameLeft,
borderWidthT, borderWidthR, borderWidthB, borderWidthL,
paddingT, paddingR, paddingB, paddingL,
borderRadiusTL, borderRadiusTR, borderRadiusBR, borderRadiusBL;
if (frameInfo == null) {
// Get the singleton frame style proxy with our el class name stamped into it.
styleEl = Ext.fly(me.getStyleProxy(cls), 'frame-style-el');
info = styleEl.getStyle('filter');
if (info) {
match = info.match(me.frameInfoRe);
if (match) {
// The framing data is encoded as
//
// D=div|T=table
// | H=horz|V=vert
// | |
// | |
// ext-frame#[DT][HV]-[T-R-B-L]-[T-R-B-L]-[T-R-B-L]
// / / | | \ \
// / / | | \ \
// / / / \ \ \
// / / border-width \ \
// border-radius padding
//
// The first 2 chars hold the div/table and horizontal/vertical flags.
// The 3 sets of TRBL 4-tuples are the CSS3 values for border-radius,
// border-width and padding, respectively.
//
info = match[1].split('-');
borderRadiusTL = parseInt(info[1], 10);
borderRadiusTR = parseInt(info[2], 10);
borderRadiusBR = parseInt(info[3], 10);
borderRadiusBL = parseInt(info[4], 10);
borderWidthT = parseInt(info[5], 10);
borderWidthR = parseInt(info[6], 10);
borderWidthB = parseInt(info[7], 10);
borderWidthL = parseInt(info[8], 10);
paddingT = parseInt(info[9], 10);
paddingR = parseInt(info[10], 10);
paddingB = parseInt(info[11], 10);
paddingL = parseInt(info[12], 10);
// This calculation should follow ext-theme-base/etc/mixins/frame.css
// with respect to the CSS3 equivalent formulation:
frameTop = max(borderWidthT, max(borderRadiusTL, borderRadiusTR));
frameRight = max(borderWidthR, max(borderRadiusTR, borderRadiusBR));
frameBottom = max(borderWidthB, max(borderRadiusBL, borderRadiusBR));
frameLeft = max(borderWidthL, max(borderRadiusTL, borderRadiusBL));
frameInfo = {
table: info[0].charAt(0) === 't',
vertical: info[0].charAt(1) === 'v',
top: frameTop,
right: frameRight,
bottom: frameBottom,
left: frameLeft,
width: frameLeft + frameRight,
height: frameTop + frameBottom,
maxWidth: max(frameTop, frameRight, frameBottom, frameLeft),
border: {
top: borderWidthT,
right: borderWidthR,
bottom: borderWidthB,
left: borderWidthL,
width: borderWidthL + borderWidthR,
height: borderWidthT + borderWidthB
},
padding: {
top: paddingT,
right: paddingR,
bottom: paddingB,
left: paddingL,
width: paddingL + paddingR,
height: paddingT + paddingB
},
radius: {
tl: borderRadiusTL,
tr: borderRadiusTR,
br: borderRadiusBR,
bl: borderRadiusBL
}
};
} else {
frameInfo = false;
}
} else {
frameInfo = false;
}
//<debug error>
// This happens when you set frame: true explicitly without using the x-frame mixin in sass.
// This way IE can't figure out what sizes to use and thus framing can't work.
if (me.frame === true && !frameInfo) {
Ext.log.error('You have set frame: true explicity on this component (' + me.getXType() + ') and it ' +
'does not have any framing defined in the CSS template. In this case IE cannot figure out ' +
'what sizes to use and thus framing on this component will be disabled.');
}
//</debug>
frameInfoCache[cls] = frameInfo;
}
me.frame = !!frameInfo;
me.frameSize = frameInfo;
return frameInfo;
},
getFramingInfoCls: function(){
return this.baseCls + '-' + this.ui;
}
});
Finally, I combined these things in the sample: