; (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);