;
(function ($) {
/**
* 布局类,这个类是一个抽象类,不能直接使用
* @class FR.Layout
* @extends FR.Widget
* @abstract
*
* @cfg {JSON} options 配置属性
* @cfg {Boolean} [options.scrollable=false] 内部区域在显示不下的时候是否要显示滚动条
* @cfg {Boolean} [options.scrollx=false] 内部区域在显示不下的时候是否要显示横向滚动条
* @cfg {Boolean} [options.scrolly=false] 内部区域在显示不下的时候是否要显示纵向滚动条
* @cfg {String} [options.widgetBackground=null] 布局容器的背景
* @cfg {JSON} [options.border=null] 边框
* @cfg {String} [options.border.type] 边框样式
* @cfg {String} [options.border.color] 边框颜色
* @cfg {String} [options.border.width] 边框宽度
* @cfg {Boolean} [options.border.corner=false] 是否是圆角边框
* @cfg {String} [options.border.borderStyle] 边框线阴影样式
*/
FR.Layout = FR.extend(FR.Widget, {
/**
* @private
*/
_defaultConfig: function () {
return $.extend(FR.Layout.superclass._defaultConfig.apply(), {
scrollable: false,
scrollx: false,
scrolly: false,
widgetBackground: null,
border: null,
onClick: null
});
},
/**
* @private
*/
_init: function () {
FR.Layout.superclass._init.apply(this, arguments);
this._init4Margin();
this._init4Style();
this._init4Scroll();
this._init4Click();
},
/**
* 初始化布局与外层容器的边间距
* @private
*/
_init4Margin: function () {
if (this.options.marginTop) {
this.element.css('marginTop', this.options.marginTop);
this.marginHeight = (this.marginHeight || 0) + parseInt(this.options.marginTop);
}
if (this.options.marginLeft) {
this.element.css('marginLeft', this.options.marginLeft);
this.marginWidth = (this.marginWidth || 0) + parseInt(this.options.marginLeft);
}
if (this.options.marginBottom) {
this.element.css('marginBottom', this.options.marginBottom);
this.marginHeight = (this.marginHeight || 0) + parseInt(this.options.marginBottom);
}
if (this.options.marginRight) {
this.element.css('marginRight', this.options.marginRight);
this.marginWidth = (this.marginWidth || 0) + parseInt(this.options.marginRight);
}
},
/**
* 初始化布局样式,包括背景,边框,圆角
* @private
*/
_init4Style: function () {
this._initBackGround();
var border = this.options.border;
if (border) {
this.element.css('border-style', border.type);
this.element.css('border-color', border.color);
this.element.css('border-width', border.width);
if (border.corner) {
this.element.css('border-radius', "15px 15px 15px 15px");
if ($.browser.msie) {
this.element.addClass('ie-border-radius');
}
}
if (!($.browser.msie && $.browser.version < '9.0')) {
this.element.css('box-shadow', border.borderStyle);
}
}
},
_initBackGround: function () {
//设置控件背景
if (!this.options.widgetBackground) {
return;
}
if (this.options.type && this.options.type == 'fit') {
this._initFitBackground();
return;
}
var alpha = this.options.widgetOpacity;
if (!alpha) {
this.element.css('background', this.options.widgetBackground.background);
return;
}
//因为有透明度, 如果直接设置opacity属性, 会被子层div继承, 因此平级放一个背景div
this.$background = $("<div class='widgetBackground'></div>");
//IE
this.$background.css('filter', 'alpha(opacity=' + alpha * 100 + ')');
//Chrome ff
this.$background.css('opacity', alpha);
this.element.css('background', this.options.widgetBackground.background);
this.$background.prependTo(this.element);
},
/**
* 自适应布局做为表单主体,背景要覆盖内边距区域,加一层同级div放在前面
*/
_initFitBackground: function () {
var parent = this.element.parent();
var margin = this.element.margin();
var w = this.element.width() + (margin.left || 0) + (margin.right || 0);
var h = this.element.height() + (margin.top || 0) + (margin.bottom || 0);
if (this.$background && parent.has(this.$background).length > 0) {
this.$background.css('width', (w || 0));
this.$background.css('height', (h || 0));
this.$background.css('top', this.element.css('top'));
this.$background.css('left', this.element.css('left'));
return;
}
this.$background = $("<div class='widgetBackground'></div>");
this.$background.css('position', 'absolute');
var alpha = this.options.widgetOpacity;
if (alpha) {
//IE
this.$background.css('filter', 'alpha(opacity=' + alpha * 100 + ')');
//Chrome ff
this.$background.css('opacity', alpha);
}
this.$background.css('width', (w || 0));
this.$background.css('height', (h || 0));
FR.setBackground(this.$background, this.options.widgetBackground, h);
this.$background.prependTo(parent);
},
/**
* 初始化布局的滚动形态
* @private
*/
_init4Scroll: function () {
if (!this.options.scrollable) {
this.element.css("overflow", "hidden");
} else {
this.element.css("overflow", "auto")
}
if (this.options.scrollx) {
this.element.css({
"overflow-x": "auto",
"overflow-y": "hidden"
});
}
if (this.options.scrolly) {
this.element.css({
"overflow-x": "hidden",
"overflow-y": "auto"
});
}
},
/**
* 初始化点击事件
* @private
*/
_init4Click: function () {
var self = this;
this.element.click(function (e) {
self.fireEvent(FR.Events.CLICK, e);
});
var opts = this.options;
if ($.isFunction(opts.onClick)) {
this.element.bind('click', opts.onClick.createDelegate(this));
}
},
/**
* 重新布局,一般在改变了布局内部组件的时候都需要重新布局
*/
doLayout: function () {
this.element.doLayout(arguments);
},
/**
* 设置布局的最小宽度和最小高度
*/
setMinSize: function () {
if (this.element.length > 0 && this.element[0].tagName == "BODY") {
var minSize = this.element["minimumSize"]();
this.element.css({"min-width": minSize.width, "min-height": minSize.height});
$("html").css("overflow", "auto");
}
},
/**
* 初始化后事件
* @private
*/
_confirmEvents: function () {
/*do nothing*/
}
});
/**
* 绝对布局,里面所有的元素由有横坐标、纵坐标、长以及宽属性决定其位置和大小
*
* @example
* var renderEl = $('body');
* var layout = new FR.AbsoluteLayout({
* renderEl : renderEl,
* items : [
* {
* type : 'button',
* text : '(0, 0, 120, 24)',
* x : 0,
* y : 0,
* width : 120,
* height : 24
* },
* {
* type : 'button',
* text : '(0, 0, auto, auto)',
* x : 40,
* y : 30
* }
* ]
* });
* layout.doLayout();
*
* @class FR.AbsoluteLayout
* @extends FR.Layout
*
* @cfg {JSON} options 配置属性
* @cfg {Array} options.items 字组件数组
*/
FR.AbsoluteLayout = FR.extend(FR.Layout, {
_defaultConfig: function () {
return $.extend(FR.AbsoluteLayout.superclass._defaultConfig.apply(), {
baseCls: 'fr-absolutelayout',
scrollable: false
});
},
_init: function () {
FR.AbsoluteLayout.superclass._init.apply(this, arguments);
var opts = this.options;
this.element.addClass(opts.baseCls);
if (!$.isArray(opts.items)) {
opts.items = [];
return;
}
var items = opts.items, i, len = items.length;
opts.widgets = [];
var $container = this.element;
if (opts.scrollable) {
$container = $('<div class="fr-core-layout-scrollable">').css({
position: 'absolute',
top: 0,
left: 0
}).appendTo(this.element);
opts.scrollContainer = $container;
}
for (i = 0; i < len; i++) {
var itemConfig = items[i];
// richie:复制父容器的样式给子控件
//itemConfig.style = o.style;
//Sean:改成如果控件有自己定义的style,则不使用上级控件传递下来的style,所有布局都统一
if (!itemConfig.style) {
itemConfig.style = opts.style;
}
if (itemConfig.type) {
itemConfig.el = itemConfig;
}
if (itemConfig.el.type) {
var widget = FR.createWidget($.extend(itemConfig.el, {
resultWidgets: opts.resultWidgets
}));
//Sean: TODO 表单改好后这个属性统一成resultWidgets,这个可以删
opts.widgets.push(widget);
var element = widget.element;
element.css({left: itemConfig.x, top: itemConfig.y, position: "absolute"});
// richer:由于已经生成了widget,就没必要再保存原来的JSON对象了
items[i].el = element;
$container.append(element);
widget.doResize({width: itemConfig.width, height: itemConfig.height});
} else if (itemConfig.el instanceof $) {
var element = itemConfig.el;
element.css({left: itemConfig.x, top: itemConfig.y, position: "absolute"});
$container.append(element);
}
}
this.element.data('jlayout', jLayout.absolute(opts));
// IE杂项模式下,如果高度是0,会是几十像素的高度,有边框的情况宽度为0不显示
if ($.browser.msie && !$.support.boxModel) {
if (opts.height === 0) {
opts.height = 1;
}
if (opts.width === 0) {
opts.width = 1;
}
}
},
doResize: function (give) {
FR.AbsoluteLayout.superclass.doResize.call(this, give);
var opts = this.options;
this.element.css({
width: (give ? (give.width || opts.width) : opts.width),
height: give ? (give.height || opts.height) : opts.height,
left: give ? (give.left || opts.left) : opts.left,
top: give ? (give.top || opts.top) : opts.top
});
//wei : 里面的控件也要doResize一下的。
for (var i = 0, len = this.options.widgets.length; i < len; i++) {
var widget = this.options.widgets[i];
if ($.isFunction(widget.doResize)) {
//我们有的控件判断了doResize的参数是否空,是就用option.width/height,有的就没做判断,调用doResize会抛错。
widget.doResize({});
}
}
},
doLayout: function () {
FR.AbsoluteLayout.superclass.doLayout.apply(this, arguments);
for (var i = 0, len = this.options.widgets.length; i < len; i++) {
var widget = this.options.widgets[i];
if ($.isFunction(widget.doLayout)) {
widget.doLayout();
}
}
}
});
$.shortcut('absolute', FR.AbsoluteLayout);
/**
* 流式布局
*
* @example
* var $area = $('<div>').css({width: 300, height:300, background:'gray'}).appendTo('body');
* var editor = new FR.FlowLayout({
* renderEl : $area,
* hgap : 5,
* vgap : 5,
* items : [
* {el: {type: 'button', text: 'flow1', width: 60, height: 50}},
* {el: {type: 'button', text: 'flow2', width: 60, height: 30}},
* {el: {type: 'button', text: 'flow3', width: 60, height: 30}},
* {el: {type: 'button', text: 'flow4', width: 90, height: 30}},
* {el: {type: 'button', text: 'flow5', width: 90, height: 30}},
* {el: {type: 'button', text: 'flow6', width: 90, height: 30}},
* {el: {type: 'button', text: 'flow7', width: 90, height: 30}},
* {el: {type: 'button', text: 'flow8', width: 180, height: 30}}
* ]
* });
* editor.doLayout();
*
* @class FR.FlowLayout
* @extends FR.Layout
*
* @cfg {JSON} options 配置属性
* @cfg {Number} [options.hgap=5] 水平间隙
* @cfg {Number} [options.vgap=5] 垂直间隙
*/
FR.FlowLayout = FR.extend(FR.Layout, /**@class FR.FlowLayout*/{
_defaultConfig: function () {
return $.extend(FR.FlowLayout.superclass._defaultConfig.apply(), {
hgap: 5,
vgap: 5,
baseCls: 'fr-flowlayout'
});
},
_init: function () {
FR.FlowLayout.superclass._init.apply(this, arguments);
var opts = this.options;
this.element.addClass(opts.baseCls);
var items = opts.items, i, len = items.length;
opts.widgets = [];
for (i = 0; i < len; i++) {
var itemConfig = items[i];
if (itemConfig.el && itemConfig.el.type) {
if (!itemConfig.el.style) {
itemConfig.el.style = opts.style;
}
var widget = FR.createWidget($.extend(itemConfig.el, {
resultWidgets: opts.resultWidgets
}));
// 将子widget放到widgets对象里面,以便在doLayout的时候方便使用
opts.widgets.push(widget);
var element = widget.element;
// richer:由于已经生成了widget,就没必要再保存原来的JSON对象了
items[i].el = element;
this.element.append(element);
} else if (itemConfig.el instanceof $) {
this.element.append(itemConfig.el);
}
}
this.element.data('jlayout', jLayout.flow(opts));
},
doResize: function (give) {
FR.FlowLayout.superclass.doResize.call(this, give);
var opts = this.options;
this.element.css({
width: opts.width,
height: opts.height,
left: opts.left,
top: opts.top
});
},
doLayout: function () {
FR.FlowLayout.superclass.doLayout.apply(this, arguments);
}
});
$.shortcut("flow", FR.FlowLayout);
/**
* 格子布局
*
* @example
* var $area = $('<div>').css({width: 300, height:300, background:'gray'}).appendTo('body');
* var layout = new FR.GridLayout({
* renderEl : $area,
* columns: 4,
* rows : 3,
* widths : ['auto', 30, 'auto', 'auto'],//手动设置宽度,auto表示把除手动设置的以外的宽度均分
* heights : ['auto', 'auto', 'auto'],//手动设置宽度,auto表示把除手动设置的以外的高度均分
* items : [
* { column : 0,
* row : 0,
* el : {type : 'button', text : 'button1'}
* },
* { column : 1,
* row : 1,
* el : $('<div>').css({background : 'green'})
* },
* { column : 3,
* row : 2,
* el : $('<div>').css({background : 'red'})
* }
* ]
* });
* layout.doLayout();
*
* @class FR.GridLayout
* @extends FR.Layout
*
* @cfg {JSON} options 配置属性
* @cfg {Number} [options.hgap=0] 子组件之间的水平间隙
* @cfg {Number} [options.vgap=0] 子组件之间的垂直间隙
* @cfg {Number} [options.leftGap=0] 左边留的空隙
* @cfg {Number} [options.rightGap=0] 右边留的空隙
* @cfg {Number} [options.topGap=0] 上边留的空隙
* @cfg {Number} [options.bottomGap=0] 下边留的空隙
*/
FR.GridLayout = FR.extend(FR.Layout, {
_defaultConfig: function () {
return $.extend(FR.GridLayout.superclass._defaultConfig.apply(), {
hgap: 0,
vgap: 0,
// 左边留的空隙
leftGap: 0,
rightGap: 0,
// 上边留的空隙
topGap: 0,
bottomGap: 0,
baseCls: 'fr-gridlayout'
});
},
_init: function () {
FR.GridLayout.superclass._init.apply(this, arguments);
var opts = this.options;
this.element.addClass(opts.baseCls);
var items = opts.items, len = items.length;
opts.widgets = [];
for (var j = 0; j < len; j++) {
var itemConfig = items[j];
if (itemConfig.el.type) {
// 根据items的配置文件生成控件
if (!itemConfig.el.style) {
itemConfig.el.style = opts.style;
}
var widget = FR.createWidget($.extend(itemConfig.el, {
resultWidgets: opts.resultWidgets
}));
opts.widgets.push(widget);
var element = widget.element;
} else {
element = itemConfig.el;
}
itemConfig.el = element;
this.element.append(element);
}
this.element.data('jlayout', jLayout.gridLayout(opts));
},
doResize: function (give) {
FR.GridLayout.superclass.doResize.call(this, give);
var opts = this.options;
this.element.css({
width: (give ? (give.width || opts.width) : opts.width),
height: (give ? (give.height || opts.height) : opts.height),
left: give ? (give.left || opts.left) : opts.left,
top: give ? (give.top || opts.top) : opts.top
});
},
doLayout: function () {
FR.GridLayout.superclass.doLayout.apply(this, arguments);
}
});
$.shortcut("grid", FR.GridLayout);
/**
* 冻结格子布局
* @class FR.FrozenGridLayout
* @extends FR.Layout
* @private
*/
FR.FrozenGridLayout = FR.extend(FR.Layout, /**FR.FrozenGridLayout*/{
_init: function () {
FR.FrozenGridLayout.superclass._init.apply(this, arguments);
var $thisEl = this.element;
var o = this.options;
$.each(o.items || [], function (idx, item) {
// alex:只有当regionEl.parent()不是container才调用appendTo方法,原因是appendTo会改变regionEl的位置
if (item.parent()[0] != $thisEl[0]) {
item.appendTo($thisEl);
}
});
$thisEl.data('jlayout', jLayout.grid(o));
// 如果设置了layout,那么overflow必然要设置为hidden
},
doLayout: function () {
this.element.doLayout();
},
doResize: function (give) {
FR.FrozenGridLayout.superclass.doResize.apply(this, arguments);
var opts = this.options;
this.element.css({
width: (give ? (give.width || opts.width) : opts.width) - (this.marginWidth || 0),
height: (give ? (give.height || opts.height) : opts.height) - (this.marginHeight || 0),
left: give ? (give.left || opts.left) : opts.left,
top: give ? (give.top || opts.top) : opts.top
});
}
});
$.shortcut("frozengrid", FR.FrozenGridLayout);
/**
* 表格布局
*
* @example
* var $area = $('<div>').css({width: 300, height:200, background:'gray'}).appendTo('body');
* var layout = new FR.TableLayout({
* renderEl : $area,
* items: [
* [
* null,
* {el : {type: 'label', value: 'label1'}},
* {el : {type: 'button', text: '点击放大区域', handler : function() {
* $area.css({width : 500});
* layout.doLayout();
* }}}
* ],
* [
* null,
* {el : {type: 'label', value: 'label2'}},
* {el : {type: 'button', text: '点击缩小区域', handler : function() {
* $area.css({width : 300});
* layout.doLayout();
* }}}
* ],
* [
*
* {el : $("<div>Space</div>")},
* {el : {type: 'label', value: 'label3'}},
* {el : $("<div>I am a div, align to left!</div>")}
* ]
* ],
* columnSize : [40, 0.4, 'fill'],
* rowSize : [24, 24, 24],
* vgap : 20
* });
* layout.doLayout();
*
* @class FR.TableLayout
* @extends FR.Layout
*
* @cfg {JSON} options 配置属性
* @cfg {Number} [options.vgap=5] 组件间的垂直间隙
* @cfg {Array} options.items 子组件
* @cfg {Array} options.columnSize 列宽数组,由数字组成,该数字的最后一个元素不是数字表示最后一列自适应剩下的宽度
* @cfg {Array} options.rowSize 行高数组,由数字组成,该数字的最后一个元素不是数字表示最后一列自适应剩下的高度
*/
FR.TableLayout = FR.extend(FR.Layout, {
_defaultConfig: function () {
return $.extend(FR.TableLayout.superclass._defaultConfig.apply(), {
baseCls: 'fr-layout-table',
vgap: 5,
items: [],
columnSize: [],
rowSize: [],
scrollable: false
});
},
_init: function () {
FR.TableLayout.superclass._init.apply(this, arguments);
var opts = this.options;
var items = opts.items;
var $container = this.element;
if (opts.scrollable) {
$container = $('<div class="fr-core-layout-scrollable">').css({
position: 'absolute',
top: 0,
left: 0
}).appendTo(this.element);
opts.scrollContainer = $container;
}
for (var i = 0; i < items.length; i++) {
var rowItems = items[i];
for (var j = 0; j < rowItems.length; j++) {
var item = rowItems[j];
if (item == null) {
continue;
}
// richie:需要防止item为null的情况
if (item && item.el && item.el.type) {
if (!item.el.style) {
item.el.style = opts.style;
}
var widget = FR.createWidget($.extend(item.el, {
resultWidgets: opts.resultWidgets
}));
item.element = widget.element;
} else if (item && item.el instanceof $) {
item.element = item.el;
}
$container.append(item.element);
}
}
this.element.data('jlayout', jLayout.tableLayout(opts));
},
/**
* 设置表格布局的指定行的可见性,如果该行不可见,其余的行会依次填补掉不可见行的位置
* @param {Number/Number[]} index 要改变的行或者行组成的数组
* @param {Boolean} flag 可见性,true表示要设置为可见,false表示要设置为不可见
*/
setRowVisible: function (index, flag) {
if ($.isArray(index)) {
for (var r = 0; r < index.length; r++) {
this.setRowVisible(index[r], flag);
}
} else {
var currentItem = this.options.items[index];
for (var i = 0; i < currentItem.length; i++) {
var item = currentItem[i];
if (item && item.element) {
if (flag === true) {
item.element.show();
} else {
item.element.hide();
}
}
}
}
},
/**
* 判断该行是否可见
* @param {Number} index 行数索引
* @returns {Boolean} 返回是否可见
*/
isRowVisible: function (index) {
var currentItem = this.options.items[index];
for (var i = 0; i < currentItem.length; i++) {
var item = currentItem[i];
if (item && item.element) {
if (!item.element.isVisible()) {
return false;
}
}
}
return true;
},
/**
* 重置行属性,并刷新布局
* @param {Number[]} rowSize 行高数组
*/
refreshRowSize: function (rowSize) {
this.options.rowSize = rowSize;
this.element.data('jlayout', jLayout.tableLayout(this.options));
this.doLayout();
},
doResize: function (give) {
FR.TableLayout.superclass.doResize.call(this, give);
var opts = this.options;
this.element.css({
width: (give ? (give.width || opts.width) : opts.width),
height: (give ? (give.height || opts.height) : opts.height),
left: give ? (give.left || opts.left) : opts.left,
top: give ? (give.top || opts.top) : opts.top
});
this.doLayout();
},
doLayout: function () {
FR.TableLayout.superclass.doLayout.apply(this, arguments);
}
});
$.shortcut("tablelayout", FR.TableLayout);
/**
* 边界布局
*
* @example
* var $area = $('<div>').css({
* position : 'absolute',
* top : 5,
* left : 5,
* width: 300,
* height:120,
* background:'gray'}).appendTo('body');
* var editor = new FR.BorderLayout({
* renderEl : $area,
* items : [
* {
* region: 'north',
* height: 20,
* el: {type: 'button', text: 'North'}
* },
* {
* region: 'south',
* height: 20,
* el: {type: 'button', text: 'South'}
* },
* {
* region: 'center',
* el: {type: 'button', text: 'Center'}
* },
* {
* region: 'east',
* width: 30,
* el: {type: 'button',text: 'East'}
* },
* {
* region: 'west',
* width: 30,
* el: {type: 'button',text: 'West'}
* }
* ]
* });
* editor.doLayout();
*
* @class FR.BorderLayout
* @extends FR.Layout
*
* @cfg {JSON} options 配置属性
* @cfg {Array} options.items 布局容器中的内容
*/
FR.BorderLayout = FR.extend(FR.Layout, {
_defaultConfig: function () {
return $.extend(FR.BorderLayout.superclass._defaultConfig.apply(), {
baseCls: 'fr-quick-border-layout'
});
},
_init: function () {
FR.BorderLayout.superclass._init.apply(this, arguments);
var opts = this.options;
var items = opts.items;
var regionsAvailable = ["north", "south", "east", "west", "center"];
this.regionField = {};
for (var i = 0; i < items.length; i++) {
var item = items[i];
var region = item['region'];
if (regionsAvailable.indexOf(region) != -1) {
if (item.el && item.el.type) {
if (!item.el.style) {
item.el.style = opts.style;
}
var widget = FR.createWidget($.extend(item.el, {
width: item.width,
height: item.height,
resultWidgets: opts.resultWidgets
}));
item.el = widget.element;
}
this.element.append(item.el);
this.regionField[region] = item;
}
}
this.element.data('jlayout', jLayout.borderlayout(this.regionField));
},
/**
* 动态改变区域的尺寸
* @param {"north"/"south"/"east"/"west"} region 区域,可以是东南西北四个位置的任意一个
* @param {Number} wh 高度或者宽度值
*/
setRegionWH: function (region, wh) {
if (!region || isNaN(wh)) {
return;
}
switch (region) {
case 'north' :
this.regionField['north'].height = wh;
break;
case 'south' :
this.regionField['south'].height = wh;
break;
case 'east' :
this.regionField['east'].width = wh;
break;
case 'west' :
this.regionField['west'].width = wh;
break;
default :
}
this.element.data('jlayout', jLayout.borderlayout(this.regionField));
},
doResize: function (give) {
FR.BorderLayout.superclass.doResize.call(this, give);
var opts = this.options;
this.element.css({
width: (give ? (give.width || opts.width) : opts.width),
height: (give ? (give.height || opts.height) : opts.height),
left: give ? (give.left || opts.left) : opts.left,
top: give ? (give.top || opts.top) : opts.top
});
this.doLayout();
},
doLayout: function () {
FR.BorderLayout.superclass.doLayout.apply(this, arguments);
}
});
$.shortcut('border', FR.BorderLayout);
/**
* 居中布局
*
* @example
* var $wrapper = $('<div>').css({
* width : 300,
* height : 200,
* top : 5,
* left : 5,
* position : 'absolute',
* background : 'red'
* }).appendTo('body');
* var layout = FR.createWidget({
* renderEl : $wrapper,
* type : 'center',
* item : {
* width : 150,
* height : 150,
* el : $('<div>').css({background:'green'})
* }
* });
* layout.doLayout();
*
* @class FR.CenterLayout
* @extends FR.Layout
*
* @cfg {JSON} options 居中布局的各种属性配置
* @cfg {JSON} options.item 布局中的元素配置属性
* @cfg {Number/'auto'} [options.item.width='auto'] 中间部分的宽度
* @cfg {Number/'auto'} [options.item.height='auto'] 中间部分的高度
* @cfg {JSON/jQuery} options.item.el 布局中元素对象,可以是一个JSON格式的控件配置属性,也可以是一个jQuery对象
*/
FR.CenterLayout = FR.extend(FR.Layout, {
_defaultConfig: function () {
return $.extend(FR.CenterLayout.superclass._defaultConfig.apply(), {
baseCls: 'fr-quick-center-layout'
});
},
_init: function () {
FR.CenterLayout.superclass._init.apply(this, arguments);
var opts = this.options, item = opts.item;
if (item && item.el) {
if (item.el.type) {
if (!item.el.style) {
item.el.style = opts.style;
}
var widget = FR.createWidget($.extend(item.el, {
width: item.width,
height: item.height,
resultWidgets: opts.resultWidgets
}));
item.el = widget.element;
} else if (!(item.el instanceof $)) {
FR.Msg.toast('el must be a widget or a jQuery element!');
item.el = $('<div>');
}
this.element.append(item.el);
}
this.element.data('jlayout', jLayout.center(opts));
},
doLayout: function () {
FR.CenterLayout.superclass.doLayout.apply(this, arguments);
}
});
$.shortcut('center', FR.CenterLayout);
/**
* 卡片布局
* @class FR.CardLayout
* @extends FR.Layout
*
* @cfg {JSON} options 配置属性
* @cfg {Number} [options.defaultShowIndex=0] 默认加载完显示的tab子组件索引
* @cfg {Function} [hideAction=null] 子组件隐藏函数,默认会调用jQuery的hide()
* @cfg {JSON} hideAction.item 隐藏函数的参数,表示即将隐藏的当前项
*/
FR.CardLayout = FR.extend(FR.Layout, {
_defaultConfig: function () {
return $.extend(FR.CardLayout.superclass._defaultConfig.apply(), {
baseCls: 'fr-quick-card-layout',
defaultShowIndex: 0,
hideAction : null,
showAction : null
});
},
_init: function () {
FR.CardLayout.superclass._init.apply(this, arguments);
var opts = this.options;
this.name2Index = {};
this.cardsHasCreated = [];
this._initNameMap();
this.showCardByIndex(opts.defaultShowIndex);
},
/**
* 初始化控件名索引
* @private
*/
_initNameMap: function () {
var items = this.options.items;
for (var i = 0; i < items.length; i++) {
var name;
if (items[i].el) {
name = items[i].el.widgetName;
} else {
name = items[i].widgetName;
}
if (!FR.isEmpty(name)) {
this.name2Index[name] = i;
}
}
},
showPaneByIndex: function(index) {
this.showCardByIndex(index);
},
/**
* 显示指定位置的布局容器
* @param index 位置索引
*/
showCardByIndex: function (index) {
var opts = this.options;
var items = opts.items;
this.showIndex = index;
for (var h = 0; h < this.cardsHasCreated.length; h++) {
var idx = this.cardsHasCreated[h];
var it = items[idx];
this._hideItem(it);
}
if (index > -1 && index < items.length) {
var ii = this.cardsHasCreated.indexOf(index);
if (ii == -1) {
var item = items[index];
if (!item.el) {
item.el = item;
}
if (item && item.el && item.el.type) {
var widget = FR.createWidget($.extend(item.el, {
resultWidgets: opts.resultWidgets
}));
item.el = widget.element;
}
item.el.hide();
this.element.append(item.el);
this.cardsHasCreated.push(index);
this.element.data('jlayout', jLayout.card(opts));
this._showItem(item);
} else {
it = items[index];
this._showItem(it);
}
}
this.doLayout();
},
_hideItem : function(item) {
var opts = this.options;
if ($.isFunction(opts.hideAction)) {
opts.hideAction.apply(this, [item]);
} else {
item.el.hide();
}
},
_showItem : function(item) {
item.el.show();
},
/**
* 获取当前所显示布局容器的索引位置
* @returns {*}
*/
getShowIndex: function(){
return this.showIndex? this.showIndex:this.options.defaultShowIndex;
},
/**
* 根据子容器的控件名显示指定位置的布局容器
* @param name 控件名
*/
showPaneByName: function(name) {
return this.showCardByName(name);
},
/**
* 根据子容器的控件名显示指定位置的布局容器
* @param name 控件名
*/
showCardByName: function (name) {
if (FR.isEmpty(name)) {
return;
}
this.showCardByIndex(this.name2Index[name.toUpperCase()]);
},
doResize: function (give) {
FR.CardLayout.superclass.doResize.call(this, give);
var opts = this.options;
this.element.css({
width: (give ? (give.width || opts.width) : opts.width),
height: (give ? (give.height || opts.height) : opts.height),
left: give ? (give.left || opts.left) : opts.left,
top: give ? (give.top || opts.top) : opts.top
});
this.doLayout();
},
doLayout: function () {
FR.CardLayout.superclass.doLayout.apply(this, arguments);
}
});
$.shortcut('card', FR.CardLayout);
})(jQuery);