ソースを参照

Merge pull request #5 from wenzhixin/master

Merging with recent changes
Troy Morehouse 10 年 前
コミット
94c185e3e7

+ 12 - 0
CHANGELOG.md

@@ -1,5 +1,17 @@
 ## ChangeLog
 
+### 1.8.2
+
+- [enh] Update bootstrap-table-cookie.js.
+- [enh] Use options for detailView's open/close icons.
+- [enh] Added `refreshOptions` and `gtHiddenColumns` method.
+- [enh] Added `datepicker` option to Filter Control.
+- [bug] Fix #936 Sort carets shouldn't be inline-styled by JS.
+- [bug] Fix table header width bug when setting table to no bordered.
+- [bug] Fix #938, fix #940: Multiple Sort and Hide/Show column.
+- [bug] Fix #970: click and dblclick bug on no-rows table.
+- [bug] Fix #967: unselected column while column sorted display error.
+
 ### 1.8.1
 
 - [enh] Accessing field name in formatter.

+ 23 - 5
docs/_i18n/en/extensions/cookie.md

@@ -10,23 +10,41 @@ Use Plugin: [bootstrap-table-cookie](https://github.com/wenzhixin/bootstrap-tabl
 
 ## Options
 
-### stateSave
+### cookie
 
 * type: Boolean
 * description: Set true to save the state of a table (its paging position, ordering state, records per page).
 * default: `false`
 
-### stateSaveExpire
+### cookieExpire
 
 * type: String
-* description: You must set this property if stateSave is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position
+* description: You must set this property if cookie option is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position
                		you can use: 's','mi','h','d','m','y', these means: 'seconds', 'minutes', 'hours', 'days', 'months', 'years'.
 * default: `2h`
 
-### stateSaveIdTable
+### cookiePath
 
 * type: String
-* description: You must set this property if stateSave is enable to sets an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
+* description: you can tell the browser what path the cookie belongs to. By default, the cookie belongs to the current page.
+* default: `null`
+
+### cookieDomain
+
+* type: String
+* description: This is the website domain, with the www. prefix removed.
+* default: `null`
+
+### cookieSecure
+
+* type: Boolean
+* description: This property keeps cookie communication limited to encrypted transmission, directing browsers to use cookies only via secure/encrypted connections.
+* default: `null`
+
+### cookieIdTable
+
+* type: String
+* description: You must set this property if the cookie property is enabled to set an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
 * default: ``
 
 ## This plugin saves

+ 2 - 2
docs/_i18n/en/extensions/filter-control.md

@@ -1,6 +1,6 @@
 # Table Filter Control
 
-Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control)
+Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control) </br>
 Dependence if you use the datepicker option: [bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker) v1.4.0
 
 ## Usage
@@ -22,7 +22,7 @@ Dependence if you use the datepicker option: [bootstrap-datepicker](https://gith
 ### filterControl
 
 * type: String
-* description: Set `input`: show an input control, `select`: show a select control, 'datepicker': show a datepicker control.
+* description: Set `input`: show an input control, `select`: show a select control, `datepicker`: show a datepicker control.
 * default: `undefined`
 
 ### filterDatepickerOptions

+ 6 - 0
docs/_i18n/en/extensions/flat-json.md

@@ -15,3 +15,9 @@ Use Plugin: [bootstrap-table-flat-json](https://github.com/djhvscf/bootstrap-tab
 * type: Boolean
 * description: Set true to flat the JSON object.
 * default: `false`
+
+### flatSeparator
+
+* type: String
+* description: Set the default separator between object levels.
+* default: `.`

+ 23 - 5
docs/_i18n/es/extensions/cookie.md

@@ -10,23 +10,41 @@ Use Plugin: [bootstrap-table-cookie](https://github.com/wenzhixin/bootstrap-tabl
 
 ## Options
 
-### stateSave
+### cookie
 
 * type: Boolean
 * description: Set true to save the state of a table (its paging position, ordering state, records per page).
 * default: `false`
 
-### stateSaveExpire
+### cookieExpire
 
 * type: String
-* description: You must set this property if stateSave is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position
+* description: You must set this property if cookie option is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position
                		you can use: 's','mi','h','d','m','y', these means: 'seconds', 'minutes', 'hours', 'days', 'months', 'years'.
 * default: `2h`
 
-### stateSaveIdTable
+### cookiePath
 
 * type: String
-* description: You must set this property if stateSave is enable to sets an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
+* description: you can tell the browser what path the cookie belongs to. By default, the cookie belongs to the current page.
+* default: `null`
+
+### cookieDomain
+
+* type: String
+* description: This is the website domain, with the www. prefix removed.
+* default: `null`
+
+### cookieSecure
+
+* type: Boolean
+* description: This property keeps cookie communication limited to encrypted transmission, directing browsers to use cookies only via secure/encrypted connections.
+* default: `null`
+
+### cookieIdTable
+
+* type: String
+* description: You must set this property if the cookie property is enabled to set an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
 * default: ``
 
 ## This plugin saves

+ 2 - 2
docs/_i18n/es/extensions/filter-control.md

@@ -1,6 +1,6 @@
 # Table Filter Control
 
-Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control)
+Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control) </br>
 Dependence if you use the datepicker option: [bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker) v1.4.0
 
 ## Usage
@@ -22,7 +22,7 @@ Dependence if you use the datepicker option: [bootstrap-datepicker](https://gith
 ### filterControl
 
 * type: String
-* description: Set `input`: show an input control, `select`: show a select control, 'datepicker': show a datepicker control.
+* description: Set `input`: show an input control, `select`: show a select control, `datepicker`: show a datepicker control.
 * default: `undefined`
 
 ### filterDatepickerOptions

+ 6 - 0
docs/_i18n/es/extensions/flat-json.md

@@ -15,3 +15,9 @@ Use Plugin: [bootstrap-table-flat-json](https://github.com/djhvscf/bootstrap-tab
 * type: Boolean
 * description: Set true to flat the JSON object.
 * default: `false`
+
+### flatSeparator
+
+* type: String
+* description: Set the default separator between object levels.
+* default: `.`

+ 23 - 5
docs/_i18n/zh-cn/extensions/cookie.md

@@ -10,23 +10,41 @@ Use Plugin: [bootstrap-table-cookie](https://github.com/wenzhixin/bootstrap-tabl
 
 ## Options
 
-### stateSave
+### cookie
 
 * type: Boolean
 * description: Set true to save the state of a table (its paging position, ordering state, records per page).
 * default: `false`
 
-### stateSaveExpire
+### cookieExpire
 
 * type: String
-* description: You must set this property if stateSave is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position
+* description: You must set this property if cookie option is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position
                		you can use: 's','mi','h','d','m','y', these means: 'seconds', 'minutes', 'hours', 'days', 'months', 'years'.
 * default: `2h`
 
-### stateSaveIdTable
+### cookiePath
 
 * type: String
-* description: You must set this property if stateSave is enable to sets an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
+* description: you can tell the browser what path the cookie belongs to. By default, the cookie belongs to the current page.
+* default: `null`
+
+### cookieDomain
+
+* type: String
+* description: This is the website domain, with the www. prefix removed.
+* default: `null`
+
+### cookieSecure
+
+* type: Boolean
+* description: This property keeps cookie communication limited to encrypted transmission, directing browsers to use cookies only via secure/encrypted connections.
+* default: `null`
+
+### cookieIdTable
+
+* type: String
+* description: You must set this property if the cookie property is enabled to set an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
 * default: ``
 
 ## This plugin saves

+ 2 - 2
docs/_i18n/zh-cn/extensions/filter-control.md

@@ -1,6 +1,6 @@
 # Table Filter Control
 
-Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control)
+Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control) </br>
 Dependence if you use the datepicker option: [bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker) v1.4.0
 
 ## Usage
@@ -22,7 +22,7 @@ Dependence if you use the datepicker option: [bootstrap-datepicker](https://gith
 ### filterControl
 
 * type: String
-* description: Set `input`: show an input control, `select`: show a select control, 'datepicker': show a datepicker control.
+* description: Set `input`: show an input control, `select`: show a select control, `datepicker`: show a datepicker control.
 * default: `undefined`
 
 ### filterDatepickerOptions

+ 6 - 0
docs/_i18n/zh-cn/extensions/flat-json.md

@@ -15,3 +15,9 @@ Use Plugin: [bootstrap-table-flat-json](https://github.com/djhvscf/bootstrap-tab
 * type: Boolean
 * description: Set true to flat the JSON object.
 * default: `false`
+
+### flatSeparator
+
+* type: String
+* description: Set the default separator between object levels.
+* default: `.`

+ 15 - 8
src/bootstrap-table.js

@@ -1055,10 +1055,11 @@
                 this.options.pageSize = this.options.totalRows;
                 $allSelected = true;
             } else if (this.options.pageSize === this.options.totalRows) {
-                // Fix #667 Table with pagination, multiple pages and a search that matches to one page throws exception
+                // Fix #667 Table with pagination,
+                // multiple pages and a search that matches to one page throws exception
                 var pageLst = typeof this.options.pageList === 'string' ?
-                    this.options.pageList.replace('[', '').replace(']', '').replace(/ /g, '').toLowerCase().split(',') :
-                    this.options.pageList;
+                    this.options.pageList.replace('[', '').replace(']', '')
+                        .replace(/ /g, '').toLowerCase().split(',') : this.options.pageList;
                 if (pageLst.indexOf(this.options.formatAllRows().toLowerCase()) > -1) {
                     $allSelected = true;
                 }
@@ -1087,9 +1088,12 @@
         html.push('<span class="page-list">');
 
         var pageNumber = [
-                sprintf('<span class="btn-group %s">', this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ?
+                sprintf('<span class="btn-group %s">',
+                    this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ?
                     'dropdown' : 'dropup'),
-                '<button type="button" class="btn btn-default ' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + ' dropdown-toggle" data-toggle="dropdown">',
+                '<button type="button" class="btn btn-default ' +
+                    (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) +
+                    ' dropdown-toggle" data-toggle="dropdown">',
                 '<span class="page-size">',
                 $allSelected ? this.options.formatAllRows() : this.options.pageSize,
                 '</span>',
@@ -1100,7 +1104,8 @@
             pageList = this.options.pageList;
 
         if (typeof this.options.pageList === 'string') {
-            var list = this.options.pageList.replace('[', '').replace(']', '').replace(/ /g, '').split(',');
+            var list = this.options.pageList.replace('[', '').replace(']', '')
+                .replace(/ /g, '').split(',');
 
             pageList = [];
             $.each(list, function (i, value) {
@@ -1469,8 +1474,10 @@
             // if click to select - then trigger the checkbox/radio click
             if (e.type === 'click' && that.options.clickToSelect) {
                 if (that.header.clickToSelects[$tr.children().index($(this))]) {
-                    $tr.find(sprintf('[name="%s"]',
-                        that.options.selectItemName))[0].click(); // #144: .trigger('click') bug
+                    var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName));
+                    if ($selectItem.length) {
+                        $selectItem[0].click(); // #144: .trigger('click') bug
+                    }
                 }
             }
         });

+ 216 - 0
src/extensions/group-by/bootstrap-table-group-by.js

@@ -0,0 +1,216 @@
+/**
+ * @author: Dennis Hernández
+ * @webSite: http://djhvscf.github.io/Blog
+ * @version: v1.0.0
+ */
+
+!function ($) {
+
+    'use strict';
+
+    var originalRowAttr,
+        dataTTId ="data-tt-id",
+        dataTTParentId = "data-tt-parent-id",
+        obj = {},
+        parentId = undefined;
+
+    var rowAttr = function (row, index) {
+        //Call the User Defined Function
+        originalRowAttr.apply([row, index]);
+
+        obj[dataTTId.toString()] = index;
+
+        if (!row.IsParent) {
+            obj[dataTTParentId.toString()] = parentId === undefined ? index : parentId;
+        } else {
+            parentId = index;
+            delete obj[dataTTParentId.toString()];
+        }
+
+        return obj;
+    };
+
+    var setObjectKeys = function () {
+        // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+       Object.keys = function (o) {
+           if (o !== Object(o)) {
+               throw new TypeError('Object.keys called on a non-object');
+           }
+           var k = [],
+               p;
+           for (p in o) {
+               if (Object.prototype.hasOwnProperty.call(o, p)) {
+                   k.push(p);
+               }
+           }
+           return k;
+       }
+    };
+
+    var groupBy = function (array , f) {
+       var groups = {};
+       array.forEach(function(o) {
+           var group = JSON.stringify(f(o));
+           groups[group] = groups[group] || [];
+           groups[group].push(o);
+       });
+       return Object.keys(groups).map(function (group) {
+            return groups[group];
+       });
+    };
+
+    var makeGrouped = function (that) {
+        var newRow = {},
+            newData = [];
+
+        var result = groupBy(that.options.data, function (item) {
+            return [item[that.options.groupByField]];
+        });
+
+        for (var i = 0; i < result.length; i++) {
+            newRow[that.options.groupByField.toString()] = result[i][0][that.options.groupByField];
+            newRow.IsParent = true;
+            result[i].unshift(newRow);
+            newRow = {};
+        }
+
+        newData = newData.concat.apply(newData, result);
+
+        if (!that.options.loaded) {
+            that.options.loaded = true;
+            that.options.originalData = that.options.data;
+            that.options.data = newData;
+        }
+    };
+
+    var calculateObjectValue = function (self, name, args, defaultValue) {
+        var func = name;
+
+        if (typeof name === 'string') {
+            // support obj.func1.func2
+            var names = name.split('.');
+
+            if (names.length > 1) {
+                func = window;
+                $.each(names, function (i, f) {
+                    func = func[f];
+                });
+            } else {
+                func = window[name];
+            }
+        }
+        if (typeof func === 'object') {
+            return func;
+        }
+        if (typeof func === 'function') {
+            return func.apply(self, args);
+        }
+        if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) {
+            return sprintf.apply(this, [name].concat(args));
+        }
+        return defaultValue;
+    };
+
+    $.extend($.fn.bootstrapTable.defaults, {
+        groupBy: false,
+        groupByField: '',
+        //internal variables
+        loaded: false,
+        originalData: undefined
+    });
+
+    var BootstrapTable = $.fn.bootstrapTable.Constructor,
+        _init = BootstrapTable.prototype.init,
+        _initData = BootstrapTable.prototype.initData;
+
+    BootstrapTable.prototype.init = function () {
+        if ((this.options.groupBy) && (this.options.groupByField !== '')) {
+            var that = this;
+
+            // Compatibility: IE < 9 and old browsers
+            if (!Object.keys) {
+                setObjectKeys();
+            }
+
+            //Make sure that the internal variables are set correctly
+            this.options.loaded = false;
+            this.options.originalData = undefined;
+
+            originalRowAttr = this.options.rowAttributes;
+            this.options.rowAttributes = rowAttr;
+            this.$el.on('post-body.bs.table', function () {
+                that.$el.treetable({
+                    expandable: true
+                }, true);
+            });
+        }
+        _init.apply(this, Array.prototype.slice.apply(arguments));
+    };
+
+    BootstrapTable.prototype.initData = function () {
+        if ((this.options.groupBy) && (this.options.groupByField !== '')) {
+            makeGrouped(this);
+        }
+
+        _initData.apply(this, Array.prototype.slice.apply(arguments));
+    };
+
+    /*BootstrapTable.prototype.initSort = function () {
+        var that = this,
+            name = this.options.sortName,
+            order = this.options.sortOrder === 'desc' ? -1 : 1,
+            index = $.inArray(this.options.sortName, this.header.fields);
+
+        if (index !== -1) {
+            this.data.sort(function (a, b) {
+                if ((a.IsParent) || (b.IsParent)) {
+                    return order;
+                }
+                if (that.header.sortNames[index]) {
+                    name = that.header.sortNames[index];
+                }
+                var aa = a[name],
+                    bb = b[name],
+                    value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb]);
+
+                if (value !== undefined) {
+                    return order * value;
+                }
+
+                // Fix #161: undefined or null string sort bug.
+                if (aa === undefined || aa === null) {
+                    aa = '';
+                }
+                if (bb === undefined || bb === null) {
+                    bb = '';
+                }
+
+                // IF both values are numeric, do a numeric comparison
+                if ($.isNumeric(aa) && $.isNumeric(bb)) {
+                    // Convert numerical values form string to float.
+                    aa = parseFloat(aa);
+                    bb = parseFloat(bb);
+                    if (aa < bb) {
+                        return order * -1;
+                    }
+                    return order;
+                }
+
+                if (aa === bb) {
+                    return 0;
+                }
+
+                // If value is not a string, convert to string
+                if (typeof aa !== 'string') {
+                    aa = aa.toString();
+                }
+
+                if (aa.localeCompare(bb) === -1) {
+                    return order * -1;
+                }
+
+                return order;
+            });
+        }
+    };*/
+}(jQuery);

+ 6 - 0
src/extensions/reorder-columns/README.md

@@ -28,6 +28,12 @@ Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must incl
 * description: Moving only the header. Recommended for very large tables (cells > 1000)
 * default: `10`
 
+### dragaccept
+
+* type: String
+* description: Allow to drag only the rows that have the css class as attribute.
+* default: `null`
+
 ## Events
 
 ### onReorderColumn(reorder-column.bs.table)

+ 14 - 2
src/extensions/reorder-columns/bootstrap-table-reorder-columns.js

@@ -26,7 +26,8 @@
         maxMovingRows: 10,
         onReorderColumn: function (headerFields) {
             return false;
-        }
+        },
+        dragaccept: null
     });
 
     $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
@@ -84,22 +85,33 @@
     };
 
     BootstrapTable.prototype.makeRowsReorderable = function () {
-
         var that = this;
         try {
             $(this.$el).dragtable('destroy');
         } catch (e) {}
         $(this.$el).dragtable({
             maxMovingRows: that.options.maxMovingRows,
+            dragaccept: that.options.dragaccept,
             clickDelay:200,
             beforeStop: function() {
                 var ths = [],
                     columns = [],
+                    columnsHidden = [],
                     columnIndex = -1;
                 that.$header.find('th').each(function (i) {
                     ths.push($(this).data('field'));
                 });
 
+                //Exist columns not shown
+                if (ths.length < that.options.columns.length) {
+                    columnsHidden = $.grep(that.options.columns, function (column) {
+                       return !column.visible;
+                    });
+                    for (var i = 0; i < columnsHidden.length; i++) {
+                        ths.push(columnsHidden[i].field);
+                    }
+                }
+
                 for (var i = 0; i < ths.length; i++ ) {
                     columnIndex = getFieldIndex(that.options.columns, ths[i]);
                     if (columnIndex !== -1) {