ソースを参照

merged footer changes

Yoni Jah 10 年 前
コミット
9f5f22f680
2 ファイル変更154 行追加60 行削除
  1. 3 0
      src/bootstrap-table.css
  2. 151 60
      src/bootstrap-table.js

+ 3 - 0
src/bootstrap-table.css

@@ -20,7 +20,10 @@
     -moz-border-radius: 4px;
 }
 
+.fixed-table-footer,
 .fixed-table-header {
+    height: 37px; /*cellHeight*/
+    border-bottom: 1px solid #dddddd;
     overflow: hidden;
     border-radius: 4px 4px 0 0;
     -webkit-border-radius: 4px 4px 0 0;

+ 151 - 60
src/bootstrap-table.js

@@ -5,9 +5,9 @@
  */
 
 !function ($) {
-
     'use strict';
 
+    var cellHeight = 37; // update css if changed
     // TOOLS DEFINITION
     // ======================
 
@@ -54,24 +54,28 @@
         return index;
     };
 
+    var cachedWidth = null;
     var getScrollBarWidth = function () {
-        var inner = $('<p/>').addClass('fixed-table-scroll-inner'),
-            outer = $('<div/>').addClass('fixed-table-scroll-outer'),
-            w1, w2;
+        if (cachedWidth === null) {
+            var inner = $('<p/>').addClass('fixed-table-scroll-inner'),
+                outer = $('<div/>').addClass('fixed-table-scroll-outer'),
+                w1, w2;
 
-        outer.append(inner);
-        $('body').append(outer);
+            outer.append(inner);
+            $('body').append(outer);
 
-        w1 = inner[0].offsetWidth;
-        outer.css('overflow', 'scroll');
-        w2 = inner[0].offsetWidth;
+            w1 = inner[0].offsetWidth;
+            outer.css('overflow', 'scroll');
+            w2 = inner[0].offsetWidth;
 
-        if (w1 === w2) {
-            w2 = outer[0].clientWidth;
-        }
+            if (w1 === w2) {
+                w2 = outer[0].clientWidth;
+            }
 
-        outer.remove();
-        return w1 - w2;
+            outer.remove();
+            cachedWidth = w1 - w2;
+        }
+        return cachedWidth;
     };
 
     var calculateObjectValue = function (self, name, args, defaultValue) {
@@ -117,6 +121,7 @@
         this.$el = $(el);
         this.$el_ = this.$el.clone();
         this.timeoutId_ = 0;
+        this.timeoutFooter_ = 0;
 
         this.init();
     };
@@ -153,6 +158,7 @@
         searchAlign: 'right',
         selectItemName: 'btSelectItem',
         showHeader: true,
+        showFooter: false,
         showColumns: false,
         showPaginationSwitch: false,
         showRefresh: false,
@@ -282,6 +288,7 @@
         'class': undefined,
         align: undefined, // left, right, center
         halign: undefined, // left, right, center
+        falign: undefined, // left, right, center
         valign: undefined, // top, middle, bottom
         width: undefined,
         sortable: false,
@@ -290,6 +297,7 @@
         switchable: true,
         clickToSelect: true,
         formatter: undefined,
+        footerFormatter: undefined,
         events: undefined,
         sorter: undefined,
         cellStyle: undefined,
@@ -320,6 +328,7 @@
         this.initTable();
         this.initHeader();
         this.initData();
+        this.initFooter();
         this.initToolbar();
         this.initPagination();
         this.initBody();
@@ -337,6 +346,7 @@
             this.options.formatLoadingMessage(),
             '</div>',
             '</div>',
+            '<div class="fixed-table-footer"><table><tr></tr></table></div>',
             '<div class="fixed-table-pagination"></div>',
             '</div>',
             '</div>'].join(''));
@@ -498,7 +508,7 @@
         } else {
             this.$header.show();
             this.$container.find('.fixed-table-header').show();
-            this.$loading.css('top', '37px');
+            this.$loading.css('top', cellHeight + 'px');
         }
 
         this.$selectAll = this.$header.find('[name="btSelectAll"]');
@@ -509,6 +519,78 @@
             });
     };
 
+    BootstrapTable.prototype.initFooter = function () {
+        this.$footer =  this.$container.find('.fixed-table-footer');
+        if (!this.options.showFooter || this.options.cardView) {
+            this.$footer.hide();
+        } else {
+            this.$footer.show();
+        }
+    };
+
+    BootstrapTable.prototype.resetFooter = function () {
+        var bt   = this,
+            data = bt.getData(),
+            html = [];
+
+        if (!this.options.showFooter || this.options.cardView) { //do nothing
+            return;
+        }
+
+        $.each(bt.options.columns, function (i, column) {
+            var falign = '', // footer align style
+                style  = '',
+                class_ = sprintf(' class="%s"', column['class']);
+
+            if (!column.visible) {
+                return;
+            }
+
+            falign = sprintf('text-align: %s; ', column.falign ? column.falign : column.align);
+            style = sprintf('vertical-align: %s; ', column.valign);
+
+            html.push('<td', class_, sprintf(' style="%s"', falign + style), '>');
+
+
+            html.push(calculateObjectValue(column, column.footerFormatter, [data], '&nbsp;') || '&nbsp;');
+            html.push('</td>');
+        });
+
+        bt.$footer.find('tr').html(html.join(''));
+        clearTimeout(bt.timeoutFooter_);
+        bt.timeoutFooter_ = setTimeout($.proxy(bt.fitFooter, bt), bt.$el.is(':hidden') ? 100: 0);
+        return;
+    };
+
+    BootstrapTable.prototype.fitFooter = function () {
+        var bt = this,
+            $fixedBody,
+            $footerTd,
+            elWidth,
+            scrollWidth;
+        clearTimeout(bt.timeoutFooter_);
+        if (bt.$el.is(':hidden')) {
+            bt.timeoutFooter_ = setTimeout($.proxy(bt.fitFooter, bt), 100);
+            return;
+        }
+
+        $fixedBody  = bt.$container.find('.fixed-table-body');
+        elWidth     = bt.$el.css('width');
+        scrollWidth = elWidth > $fixedBody.width() ? getScrollBarWidth() : 0;
+
+        bt.$footer.css({
+            'margin-right': scrollWidth
+        }).find('table').css('width', elWidth)
+            .attr('class', bt.$el.attr('class'));
+
+        $footerTd = bt.$footer.find('td');
+
+        $fixedBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function(i) {
+            $footerTd.eq(i).outerWidth($(this).outerWidth());
+        });
+    };
+
+
     /**
      * @param data
      * @param type: append / prepend
@@ -1027,7 +1109,8 @@
         }
 
         for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
-            var item = data[i],
+            var key,
+                item = data[i],
                 style = {},
                 csses = [],
                 attributes = {},
@@ -1036,7 +1119,7 @@
             style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style);
 
             if (style && style.css) {
-                for (var key in style.css) {
+                for (key in style.css) {
                     csses.push(key + ': ' + style.css[key]);
                 }
             }
@@ -1045,7 +1128,7 @@
                 this.options.rowAttributes, [item, i], attributes);
 
             if (attributes) {
-                for (var key in attributes) {
+                for (key in attributes) {
                     htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key])));
                 }
             }
@@ -1348,49 +1431,50 @@
     };
 
     BootstrapTable.prototype.resetHeader = function () {
-        var that = this,
-            $fixedHeader = this.$container.find('.fixed-table-header'),
-            $fixedBody = this.$container.find('.fixed-table-body'),
-            scrollWidth = this.$el.width() > $fixedBody.width() ? getScrollBarWidth() : 0;
-
+        this.$el.css('margin-top', -this.$header.height());
         // fix #61: the hidden table reset header bug.
-        if (this.$el.is(':hidden')) {
-            clearTimeout(this.timeoutId_); // doesn't matter if it's 0
-            this.timeoutId_ = setTimeout($.proxy(this.resetHeader, this), 100); // 100ms
-            return;
-        }
-
-        this.$header_ = this.$header.clone(true, true);
-        this.$selectAll_ = this.$header_.find('[name="btSelectAll"]');
-
         // fix bug: get $el.css('width') error sometime (height = 500)
-        setTimeout(function () {
-            $fixedHeader.css({
-                'height': '37px',
-                'border-bottom': '1px solid #dddddd',
-                'margin-right': scrollWidth
-            }).find('table').css('width', that.$el.css('width'))
-                .html('').attr('class', that.$el.attr('class'))
-                .append(that.$header_);
-
-            // fix bug: $.data() is not working as expected after $.append()
-            that.$header.find('th').each(function (i) {
-                that.$header_.find('th').eq(i).data($(this).data());
-            });
-
-            that.$body.find('tr:first-child:not(.no-records-found) > *').each(function (i) {
-                that.$header_.find('div.fht-cell').eq(i).width($(this).innerWidth());
-            });
+        clearTimeout(this.timeoutId_);
+        this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), this.$el.is(':hidden') ? 100 : 0);
+        return;
+    };
 
-            that.$el.css('margin-top', -that.$header.height());
+    BootstrapTable.prototype.fitHeader = function () {
+        var bt = this,
+            $fixedHeader,
+            $fixedBody,
+            scrollWidth;
 
-            // horizontal scroll event
-            $fixedBody.off('scroll').on('scroll', function () {
-                $fixedHeader.scrollLeft($(this).scrollLeft());
-            });
+        if (bt.$el.is(':hidden')) {
+            bt.timeoutFooter_ = setTimeout($.proxy(bt.fitHeader, bt), 100);
+            return;
+        }
+        $fixedHeader = bt.$container.find('.fixed-table-header'),
+        $fixedBody = bt.$container.find('.fixed-table-body'),
+        scrollWidth = bt.$el.width() > $fixedBody.width() ? getScrollBarWidth() : 0;
+
+        bt.$header_ = bt.$header.clone(true, true);
+        bt.$selectAll_ = bt.$header_.find('[name="btSelectAll"]');
+        $fixedHeader.css({
+            'margin-right': scrollWidth
+        }).find('table').css('width', bt.$el.css('width'))
+            .html('').attr('class', bt.$el.attr('class'))
+            .append(bt.$header_);
+
+        // fix bug: $.data() is not working as expected after $.append()
+        bt.$header.find('th').each(function (i) {
+            bt.$header_.find('th').eq(i).data($(this).data());
+        });
 
-            that.trigger('post-header');
+        bt.$body.find('tr:first-child:not(.no-records-found) > *').each(function (i) {
+            bt.$header_.find('div.fht-cell').eq(i).width($(this).innerWidth());
         });
+        // horizontal scroll event
+        // TODO: it's probably better improving the layout than binding to scroll event
+        $fixedBody.off('scroll').on('scroll', function () {
+            $fixedHeader.scrollLeft($(this).scrollLeft());
+        });
+        bt.trigger('post-header');
     };
 
     BootstrapTable.prototype.toggleColumn = function (index, checked, needUpdate) {
@@ -1421,7 +1505,8 @@
 
     BootstrapTable.prototype.resetView = function (params) {
         var that = this,
-            header = this.header;
+            padding = 0,
+            $tableContainer = that.$container.find('.fixed-table-container');
 
         if (params && params.height) {
             this.options.height = params.height;
@@ -1435,25 +1520,31 @@
                 paginationHeight = +this.$pagination.children().outerHeight(true),
                 height = this.options.height - toolbarHeight - paginationHeight;
 
-            this.$container.find('.fixed-table-container').css('height', height + 'px');
+            $tableContainer.css('height', height + 'px');
         }
 
         if (this.options.cardView) {
             // remove the element css
             that.$el.css('margin-top', '0');
-            that.$container.find('.fixed-table-container').css('padding-bottom', '0');
+            $tableContainer.css('padding-bottom', '0');
             return;
         }
 
         if (this.options.showHeader && this.options.height) {
             this.resetHeader();
+            padding += cellHeight;
         } else {
             this.trigger('post-header');
         }
 
-        if (this.options.height && this.options.showHeader) {
-            this.$container.find('.fixed-table-container').css('padding-bottom', '37px');
+        if (this.options.showFooter) {
+            this.resetFooter();
+            if (this.options.height) {
+                padding += cellHeight;
+            }
         }
+
+        $tableContainer.css('padding-bottom', padding + 'px');
     };
 
     BootstrapTable.prototype.getData = function () {