From 53bf246e1f4f466d82e47c5130336d088e65117f Mon Sep 17 00:00:00 2001 From: zhixin Date: Sat, 27 Jun 2015 09:48:19 +0800 Subject: [PATCH 1/3] Fix #336: supported complex header with rowspans and colspans. --- src/bootstrap-table.css | 7 +- src/bootstrap-table.js | 332 +++++++++++------- .../cookie/bootstrap-table-cookie.js | 4 +- .../editable/bootstrap-table-editable.js | 4 +- .../bootstrap-table-filter-control.js | 6 +- .../filter/bootstrap-table-filter.js | 2 +- .../bootstrap-table-multiple-sort.js | 2 +- .../bootstrap-table-reorder-columns.js | 12 +- .../toolbar/bootstrap-table-toolbar.js | 2 +- 9 files changed, 227 insertions(+), 144 deletions(-) diff --git a/src/bootstrap-table.css b/src/bootstrap-table.css index 4eb7c8620c..aefd770f62 100644 --- a/src/bootstrap-table.css +++ b/src/bootstrap-table.css @@ -40,17 +40,12 @@ .fixed-table-footer, .fixed-table-header { - height: 37px; /*cellHeight*/ overflow: hidden; border-radius: 4px 4px 0 0; -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; } -.fixed-table-header { - border-bottom: 1px solid #dddddd; -} - .fixed-table-footer { border-top: 1px solid #dddddd; } @@ -265,7 +260,7 @@ .bootstrap-table .table > thead > tr > th { vertical-align: bottom; - border-bottom: 2px solid #ddd; + border-bottom: 1px solid #ddd; } /* support bootstrap 3 */ diff --git a/src/bootstrap-table.js b/src/bootstrap-table.js index 9027d71cb5..50c01af8b4 100644 --- a/src/bootstrap-table.js +++ b/src/bootstrap-table.js @@ -10,8 +10,7 @@ // TOOLS DEFINITION // ====================== - var cellHeight = 37, // update css if changed - cachedWidth = null; + var cachedWidth = null; // it only does '%s', and return '' when arguments are undefined var sprintf = function (str) { @@ -56,6 +55,48 @@ return index; }; + // http://jsfiddle.net/wenyi/47nz7ez9/3/ + var setFieldIndex = function (columns) { + var i, j, k, + totalCol = 0, + flag = []; + + for (i = 0; i < columns[0].length; i++) { + totalCol += columns[0][i].colspan || 1; + } + + for (i = 0; i < columns.length; i++) { + flag[i] = []; + for (j = 0; j < totalCol; j++) { + flag[i][j] = false; + } + } + + for (i = 0; i < columns.length; i++) { + for (j = 0; j < columns[i].length; j++) { + var r = columns[i][j], + rowspan = r.rowspan || 1, + colspan = r.colspan || 1, + index = $.inArray(false, flag[i]); + + if (colspan === 1) { + r.fieldIndex = index; + // when field is undefined, use index instead + if (typeof r.field === 'undefined') { + r.field = index; + } + } + + for (k = 0; k < rowspan; k++) { + flag[i + k][index] = true; + } + for (k = 0; k < colspan; k++) { + flag[i][index + k] = true; + } + } + } + } + var getScrollBarWidth = function () { if (cachedWidth === null) { var inner = $('

').addClass('fixed-table-scroll-inner'), @@ -191,7 +232,7 @@ sortName: undefined, sortOrder: 'asc', striped: false, - columns: [], + columns: [[]], data: [], method: 'get', url: undefined, @@ -522,23 +563,37 @@ if (!this.$header.length) { this.$header = $('').appendTo(this.$el); } - if (!this.$header.find('tr').length) { - this.$header.append(''); - } - this.$header.find('th').each(function () { - var column = $.extend({}, { - title: $(this).html(), - 'class': $(this).attr('class'), - titleTooltip: $(this).attr('title') - }, $(this).data()); - + this.$header.find('tr').each(function () { + var column = []; + + $(this).find('th').each(function () { + column.push($.extend({}, { + title: $(this).html(), + 'class': $(this).attr('class'), + titleTooltip: $(this).attr('title'), + rowspan: $(this).attr('rowspan') ? +$(this).attr('rowspan') : undefined, + colspan: $(this).attr('colspan') ? +$(this).attr('colspan') : undefined + }, $(this).data())); + }); columns.push(column); }); + if (!$.isArray(this.options.columns[0])) { + this.options.columns = [this.options.columns]; + } this.options.columns = $.extend(true, [], columns, this.options.columns); - $.each(this.options.columns, function (i, column) { - that.options.columns[i] = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, { - field: i - }, column); // when field is undefined, use index instead + this.columns = []; + + setFieldIndex(this.options.columns); + $.each(this.options.columns, function (i, columns) { + $.each(columns, function (j, column) { + column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, column); + + if (typeof column.fieldIndex !== 'undefined') { + that.columns[column.fieldIndex] = column; + } + + that.options.columns[i][j] = column; + }); }); // if options.data is setting, do not process tbody data @@ -555,7 +610,7 @@ row._data = getRealDataAttr($(this).data()); $(this).find('td').each(function (i) { - var field = that.options.columns[i].field; + var field = that.columns[i].field; row[field] = $(this).html(); // save td's id, class and data-* attributes @@ -572,7 +627,7 @@ BootstrapTable.prototype.initHeader = function () { var that = this, - visibleColumns = [], + visibleColumns = {}, html = []; this.header = { @@ -588,92 +643,102 @@ searchables: [] }; - if (!this.options.cardView && this.options.detailView) { - html.push('

'); - visibleColumns.push({}); - } + $.each(this.options.columns, function (i, columns) { + html.push(''); - $.each(this.options.columns, function (i, column) { - var text = '', - halign = '', // header align style - align = '', // body align style - style = '', - class_ = sprintf(' class="%s"', column['class']), - order = that.options.sortOrder || column.order, - unitWidth = 'px', - width = column.width; - - if (column.width !== undefined && (!that.options.cardView)) { - if (typeof column.width === 'string') { - if (column.width.indexOf('%') !== -1) { - unitWidth = '%'; - } - } - } - if (column.width && typeof column.width === 'string') { - width = column.width.replace('%', '').replace('px', ''); + if (i == 0 && !that.options.cardView && that.options.detailView) { + html.push(sprintf('
', + that.options.columns.length)); } - halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); - align = sprintf('text-align: %s; ', column.align); - style = sprintf('vertical-align: %s; ', column.valign); - style += sprintf('width: %s%s; ', column.checkbox || column.radio ? 36 : width, unitWidth); - - that.header.fields.push(column.field); - that.header.styles.push(align + style); - that.header.classes.push(class_); - that.header.formatters.push(column.formatter); - that.header.events.push(column.events); - that.header.sorters.push(column.sorter); - that.header.sortNames.push(column.sortName); - that.header.cellStyles.push(column.cellStyle); - that.header.clickToSelects.push(column.clickToSelect); - that.header.searchables.push(column.searchable); + $.each(columns, function (j, column) { + var text = '', + halign = '', // header align style + align = '', // body align style + style = '', + class_ = sprintf(' class="%s"', column['class']), + order = that.options.sortOrder || column.order, + unitWidth = 'px', + width = column.width; + + if (column.width !== undefined && (!that.options.cardView)) { + if (typeof column.width === 'string') { + if (column.width.indexOf('%') !== -1) { + unitWidth = '%'; + } + } + } + if (column.width && typeof column.width === 'string') { + width = column.width.replace('%', '').replace('px', ''); + } - if (!column.visible) { - return; - } + halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); + align = sprintf('text-align: %s; ', column.align); + style = sprintf('vertical-align: %s; ', column.valign); + style += sprintf('width: %s%s; ', column.checkbox || column.radio ? 36 : width, unitWidth); + + if (typeof column.fieldIndex !== 'undefined') { + that.header.fields[column.fieldIndex] = column.field; + that.header.styles[column.fieldIndex] = align + style; + that.header.classes[column.fieldIndex] = class_; + that.header.formatters[column.fieldIndex] = column.formatter; + that.header.events[column.fieldIndex] = column.events; + that.header.sorters[column.fieldIndex] = column.sorter; + that.header.sortNames[column.fieldIndex] = column.sortName; + that.header.cellStyles[column.fieldIndex] = column.cellStyle; + that.header.clickToSelects[column.fieldIndex] = column.clickToSelect; + that.header.searchables[column.fieldIndex] = column.searchable; + + if (!column.visible) { + return; + } - if (that.options.cardView && (!column.cardVisible)) { - return; - } + if (that.options.cardView && (!column.cardVisible)) { + return; + } - visibleColumns.push(column); + visibleColumns[column.field] = column; + } - html.push(''); + html.push(''); - html.push(sprintf('
', that.options.sortable && column.sortable ? - 'sortable both' : '')); + html.push(sprintf('
', that.options.sortable && column.sortable ? + 'sortable both' : '')); - text = column.title; + text = column.title; - if (column.checkbox) { - if (!that.options.singleSelect && that.options.checkboxHeader) { - text = ''; + if (column.checkbox) { + if (!that.options.singleSelect && that.options.checkboxHeader) { + text = ''; + } + that.header.stateField = column.field; + } + if (column.radio) { + text = ''; + that.header.stateField = column.field; + that.options.singleSelect = true; } - that.header.stateField = column.field; - } - if (column.radio) { - text = ''; - that.header.stateField = column.field; - that.options.singleSelect = true; - } - html.push(text); - html.push('
'); - html.push('
'); - html.push('
'); - html.push(''); + html.push(text); + html.push(''); + html.push('
'); + html.push(''); + html.push(''); + }); + html.push(''); }); - this.$header.find('tr').html(html.join('')); - this.$header.find('th').each(function (i) { - $(this).data(visibleColumns[i]); + this.$header.html(html.join('')); + this.$header.find('th[data-field]').each(function (i) { + $(this).data(visibleColumns[$(this).data('field')]); }); this.$container.off('click', '.th-inner').on('click', '.th-inner', function (event) { if (that.options.sortable && $(this).parent().data().sortable) { @@ -688,7 +753,7 @@ } else { this.$header.show(); this.$tableHeader.show(); - this.$tableLoading.css('top', cellHeight + 'px'); + this.$tableLoading.css('top', this.$header.outerHeight() + 1); // Assign the correct sortable arrow this.getCaret(); } @@ -875,7 +940,7 @@ '', '