bootstrap-table-rails 1.9.1 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -1
  3. data/lib/bootstrap-table-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/bootstrap-table-locale-all.js +30 -10
  5. data/vendor/assets/javascripts/bootstrap-table.js +157 -53
  6. data/vendor/assets/javascripts/extensions/bootstrap-table-cookie.js +8 -4
  7. data/vendor/assets/javascripts/extensions/bootstrap-table-editable.js +21 -0
  8. data/vendor/assets/javascripts/extensions/bootstrap-table-export.js +9 -2
  9. data/vendor/assets/javascripts/extensions/bootstrap-table-filter-control.js +127 -46
  10. data/vendor/assets/javascripts/extensions/bootstrap-table-group-by 2.js +226 -0
  11. data/vendor/assets/javascripts/extensions/bootstrap-table-mobile.js +5 -0
  12. data/vendor/assets/javascripts/extensions/bootstrap-table-natural-sorting.js +12 -2
  13. data/vendor/assets/javascripts/extensions/bootstrap-table-reorder-rows.js +1 -0
  14. data/vendor/assets/javascripts/extensions/bootstrap-table-sticky-header.js +104 -0
  15. data/vendor/assets/javascripts/locale/bootstrap-table-ca-ES.js +7 -6
  16. data/vendor/assets/javascripts/locale/bootstrap-table-en-US.js +2 -2
  17. data/vendor/assets/javascripts/locale/bootstrap-table-nl-NL.js +16 -1
  18. data/vendor/assets/javascripts/locale/bootstrap-table-ru-RU.js +3 -0
  19. data/vendor/assets/javascripts/locale/bootstrap-table-zh-TW.js +2 -2
  20. data/vendor/assets/stylesheets/bootstrap-table.css +7 -2
  21. data/vendor/assets/stylesheets/extensions/bootstrap-table-group-by 2.css +7 -0
  22. data/vendor/assets/stylesheets/extensions/bootstrap-table-sticky-header.css +22 -0
  23. metadata +6 -2
@@ -123,7 +123,7 @@
123
123
  cookieExpire = cookieExpire * 30 * 24 * 60 * 60;
124
124
  break;
125
125
  case 'y':
126
- cookieExpire = cookieExpire * 365 * 30 * 24 * 60 * 60;
126
+ cookieExpire = cookieExpire * 365 * 24 * 60 * 60;
127
127
  break;
128
128
  default:
129
129
  cookieExpire = undefined;
@@ -203,7 +203,7 @@
203
203
  searchControls = getCurrentSearchControls(that);
204
204
 
205
205
  header.find(searchControls).each(function (index, ele) {
206
- field = $(this).parent().parent().parent().data('field');
206
+ field = $(this).closest('[data-field]').data('field');
207
207
  result = $.grep(filterControl, function (valueObj) {
208
208
  return valueObj.field === field;
209
209
  });
@@ -317,8 +317,12 @@
317
317
  };
318
318
 
319
319
  BootstrapTable.prototype.onSearch = function () {
320
- _onSearch.apply(this, Array.prototype.slice.apply(arguments));
321
- setCookie(this, cookieIds.searchText, this.searchText);
320
+ var target = Array.prototype.slice.apply(arguments);
321
+ _onSearch.apply(this, target);
322
+
323
+ if ($(target[0].currentTarget).parent().hasClass('search')) {
324
+ setCookie(this, cookieIds.searchText, this.searchText);
325
+ }
322
326
  };
323
327
 
324
328
  BootstrapTable.prototype.deleteCookie = function (cookieName) {
@@ -47,14 +47,34 @@
47
47
  return;
48
48
  }
49
49
 
50
+ var editableOptions = {}, editableDataMarkup = [], editableDataPrefix = 'editable-';
51
+
52
+ var processDataOptions = function(key, value) {
53
+ // Replace camel case with dashes.
54
+ var dashKey = key.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();});
55
+ if (dashKey.slice(0, editableDataPrefix.length) == editableDataPrefix) {
56
+ var dataKey = dashKey.replace(editableDataPrefix, 'data-');
57
+ editableOptions[dataKey] = value;
58
+ }
59
+ };
60
+
61
+ $.each(that.options, processDataOptions);
62
+
50
63
  var _formatter = column.formatter;
51
64
  column.formatter = function (value, row, index) {
52
65
  var result = _formatter ? _formatter(value, row, index) : value;
53
66
 
67
+ $.each(column, processDataOptions);
68
+
69
+ $.each(editableOptions, function (key, value) {
70
+ editableDataMarkup.push(' ' + key + '="' + value + '"');
71
+ });
72
+
54
73
  return ['<a href="javascript:void(0)"',
55
74
  ' data-name="' + column.field + '"',
56
75
  ' data-pk="' + row[that.options.idField] + '"',
57
76
  ' data-value="' + result + '"',
77
+ editableDataMarkup.join(''),
58
78
  '>' + '</a>'
59
79
  ].join('');
60
80
  };
@@ -81,6 +101,7 @@
81
101
  row = data[index],
82
102
  oldValue = row[column.field];
83
103
 
104
+ $(this).data('value', params.submitValue);
84
105
  row[column.field] = params.submitValue;
85
106
  that.trigger('editable-save', column.field, row, oldValue, $(this));
86
107
  });
@@ -5,6 +5,7 @@
5
5
 
6
6
  (function ($) {
7
7
  'use strict';
8
+ var sprintf = $.fn.bootstrapTable.utils.sprintf;
8
9
 
9
10
  var TYPE_NAME = {
10
11
  json: 'JSON',
@@ -27,6 +28,10 @@
27
28
  exportOptions: {}
28
29
  });
29
30
 
31
+ $.extend($.fn.bootstrapTable.defaults.icons, {
32
+ export: 'glyphicon-export icon-share'
33
+ });
34
+
30
35
  var BootstrapTable = $.fn.bootstrapTable.Constructor,
31
36
  _initToolbar = BootstrapTable.prototype.initToolbar;
32
37
 
@@ -43,9 +48,11 @@
43
48
  if (!$export.length) {
44
49
  $export = $([
45
50
  '<div class="export btn-group">',
46
- '<button class="btn btn-default dropdown-toggle" ' +
51
+ '<button class="btn btn-default' +
52
+ sprintf(' btn-%s', this.options.iconSize) +
53
+ ' dropdown-toggle" ' +
47
54
  'data-toggle="dropdown" type="button">',
48
- '<i class="glyphicon glyphicon-export icon-share"></i> ',
55
+ sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.export),
49
56
  '<span class="caret"></span>',
50
57
  '</button>',
51
58
  '<ul class="dropdown-menu" role="menu">',
@@ -11,8 +11,9 @@
11
11
  var sprintf = $.fn.bootstrapTable.utils.sprintf;
12
12
 
13
13
  var addOptionToSelectControl = function (selectControl, value, text) {
14
+ value = $.trim(value);
14
15
  selectControl = $(selectControl.get(selectControl.length - 1));
15
- if (existsOptionInSelectControl(selectControl, value)) {
16
+ if (existOptionInSelectControl(selectControl, value)) {
16
17
  selectControl.append($("<option></option>")
17
18
  .attr("value", value)
18
19
  .text($('<div />').html(text).text()));
@@ -35,11 +36,11 @@
35
36
  }
36
37
  };
37
38
 
38
- var existsOptionInSelectControl = function (selectControl, value) {
39
+ var existOptionInSelectControl = function (selectControl, value) {
39
40
  var options = selectControl.get(selectControl.length - 1).options;
40
41
  for (var i = 0; i < options.length; i++) {
41
42
  if (options[i].value === value.toString()) {
42
- //The value is nor valid to add
43
+ //The value is not valid to add
43
44
  return false;
44
45
  }
45
46
  }
@@ -74,12 +75,12 @@
74
75
  var header = getCurrentHeader(that),
75
76
  searchControls = getCurrentSearchControls(that);
76
77
 
77
- that.options.values = [];
78
+ that.options.valuesFilterControl = [];
78
79
 
79
80
  header.find(searchControls).each(function () {
80
- that.options.values.push(
81
+ that.options.valuesFilterControl.push(
81
82
  {
82
- field: $(this).parent().parent().parent().data('field'),
83
+ field: $(this).closest('[data-field]').data('field'),
83
84
  value: $(this).val()
84
85
  });
85
86
  });
@@ -91,10 +92,10 @@
91
92
  header = getCurrentHeader(that),
92
93
  searchControls = getCurrentSearchControls(that);
93
94
 
94
- if (that.options.values.length > 0) {
95
+ if (that.options.valuesFilterControl.length > 0) {
95
96
  header.find(searchControls).each(function (index, ele) {
96
- field = $(this).parent().parent().parent().data('field');
97
- result = $.grep(that.options.values, function (valueObj) {
97
+ field = $(this).closest('[data-field]').data('field');
98
+ result = $.grep(that.options.valuesFilterControl, function (valueObj) {
98
99
  return valueObj.field === field;
99
100
  });
100
101
 
@@ -105,6 +106,24 @@
105
106
  }
106
107
  };
107
108
 
109
+ var collectBootstrapCookies = function cookiesRegex() {
110
+ var cookies = [],
111
+ foundCookies = document.cookie.match(/(?:bs.table.)(\w*)/g);
112
+
113
+ if (foundCookies) {
114
+ $.each(foundCookies, function (i, cookie) {
115
+ if (/./.test(cookie)) {
116
+ cookie = cookie.split(".").pop();
117
+ }
118
+
119
+ if ($.inArray(cookie, cookies) === -1) {
120
+ cookies.push(cookie);
121
+ }
122
+ });
123
+ return cookies;
124
+ }
125
+ };
126
+
108
127
  var createControls = function (that, header) {
109
128
  var addedFilterControl = false,
110
129
  isVisible,
@@ -122,24 +141,13 @@
122
141
  if (!column.filterControl) {
123
142
  html.push('<div style="height: 34px;"></div>');
124
143
  } else {
125
- html.push('<div style="margin: 0px 2px 2px 2px;" class="filterControl">');
144
+ html.push('<div style="margin: 0 2px 2px 2px;" class="filterControl">');
126
145
 
127
- if (column.filterControl && column.searchable) {
146
+ var nameControl = column.filterControl.toLowerCase();
147
+ if (column.searchable && that.options.filterTemplate[nameControl]) {
128
148
  addedFilterControl = true;
129
- isVisible = 'visible'
130
- }
131
- switch (column.filterControl.toLowerCase()) {
132
- case 'input' :
133
- html.push(sprintf('<input type="text" class="form-control" style="width: 100%; visibility: %s">', isVisible));
134
- break;
135
- case 'select':
136
- html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',
137
- column.field, isVisible))
138
- break;
139
- case 'datepicker':
140
- html.push(sprintf('<input type="text" class="date-filter-control %s form-control" style="width: 100%; visibility: %s">',
141
- column.field, isVisible));
142
- break;
149
+ isVisible = 'visible';
150
+ html.push(that.options.filterTemplate[nameControl](that, column.field, isVisible));
143
151
  }
144
152
  }
145
153
 
@@ -229,14 +237,42 @@
229
237
  }
230
238
  };
231
239
 
240
+ var getDirectionOfSelectOptions = function (alignment) {
241
+ alignment = alignment === undefined ? 'left' : alignment.toLowerCase();
242
+
243
+ switch (alignment) {
244
+ case 'left':
245
+ return 'ltr';
246
+ case 'right':
247
+ return 'rtl';
248
+ case 'auto':
249
+ return 'auto';
250
+ default:
251
+ return 'ltr'
252
+ }
253
+ };
254
+
232
255
  $.extend($.fn.bootstrapTable.defaults, {
233
256
  filterControl: false,
234
257
  onColumnSearch: function (field, text) {
235
258
  return false;
236
259
  },
237
260
  filterShowClear: false,
261
+ alignmentSelectControlOptions: undefined,
238
262
  //internal variables
239
- values: []
263
+ valuesFilterControl: [],
264
+ filterTemplate: {
265
+ input: function (that, field, isVisible) {
266
+ return sprintf('<input type="text" class="form-control %s" style="width: 100%; visibility: %s">', field, isVisible);
267
+ },
268
+ select: function (that, field, isVisible) {
269
+ return sprintf('<select class="%s form-control" style="width: 100%; visibility: %s" dir="%s"></select>',
270
+ field, isVisible, getDirectionOfSelectOptions(that.options.alignmentSelectControlOptions))
271
+ },
272
+ datepicker: function (that, field, isVisible) {
273
+ return sprintf('<input type="text" class="date-filter-control %s form-control" style="width: 100%; visibility: %s">', field, isVisible);
274
+ }
275
+ }
240
276
  });
241
277
 
242
278
  $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
@@ -250,6 +286,10 @@
250
286
  'column-search.bs.table': 'onColumnSearch'
251
287
  });
252
288
 
289
+ $.extend($.fn.bootstrapTable.defaults.icons, {
290
+ clear: 'glyphicon-trash icon-clear'
291
+ });
292
+
253
293
  var BootstrapTable = $.fn.bootstrapTable.Constructor,
254
294
  _init = BootstrapTable.prototype.init,
255
295
  _initToolbar = BootstrapTable.prototype.initToolbar,
@@ -258,11 +298,11 @@
258
298
  _initSearch = BootstrapTable.prototype.initSearch;
259
299
 
260
300
  BootstrapTable.prototype.init = function () {
261
- //Make sure that the filtercontrol option is set
301
+ //Make sure that the filterControl option is set
262
302
  if (this.options.filterControl) {
263
303
  var that = this;
264
304
  //Make sure that the internal variables are set correctly
265
- this.options.values = [];
305
+ this.options.valuesFilterControl = [];
266
306
 
267
307
  this.$el.on('reset-view.bs.table', function () {
268
308
  //Create controls on $tableHeader if the height is set
@@ -282,13 +322,20 @@
282
322
  if (that.options.height) {
283
323
  fixHeaderCSS(that);
284
324
  }
285
- }).on('column-switch.bs.table', function(field, checked) {
325
+ }).on('column-switch.bs.table', function() {
286
326
  setValues(that);
287
327
  });
288
328
  }
289
329
  _init.apply(this, Array.prototype.slice.apply(arguments));
290
330
  };
291
331
 
332
+ $.extend($.fn.bootstrapTable.locales, {
333
+ formatClearFilters: function () {
334
+ return 'Clear Filters';
335
+ }
336
+ });
337
+ $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
338
+
292
339
  BootstrapTable.prototype.initToolbar = function () {
293
340
  if ((!this.showToolbar) && (this.options.filterControl)) {
294
341
  this.showToolbar = this.options.filterControl;
@@ -302,9 +349,9 @@
302
349
 
303
350
  if (!$btnClear.length) {
304
351
  $btnClear = $([
305
- '<button class="btn btn-default " ' +
306
- 'type="button">',
307
- '<i class="glyphicon glyphicon-trash icon-share"></i> ',
352
+ '<button class="btn btn-default" ',
353
+ sprintf('type="button" title="%s">', this.options.formatClearFilters()),
354
+ sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.clear),
308
355
  '</button>',
309
356
  '</ul>'].join('')).appendTo($btnGroup);
310
357
 
@@ -361,6 +408,10 @@
361
408
  BootstrapTable.prototype.initSearch = function () {
362
409
  _initSearch.apply(this, Array.prototype.slice.apply(arguments));
363
410
 
411
+ if (!this.options.sidePagination === 'server') {
412
+ return;
413
+ }
414
+
364
415
  var that = this;
365
416
  var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;
366
417
 
@@ -370,24 +421,28 @@
370
421
  var thisColumn = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, key)];
371
422
  var fval = fp[key].toLowerCase();
372
423
  var value = item[key];
373
- value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header,
424
+
425
+ // Fix #142: search use formated data
426
+ if (thisColumn && thisColumn.searchFormatter) {
427
+ value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header,
374
428
  that.header.formatters[$.inArray(key, that.header.fields)],
375
429
  [value, item, i], value);
430
+ }
376
431
 
377
- if(thisColumn.filterStrictSearch){
432
+ if (thisColumn.filterStrictSearch) {
378
433
  if (!($.inArray(key, that.header.fields) !== -1 &&
379
434
  (typeof value === 'string' || typeof value === 'number') &&
380
435
  value.toString().toLowerCase() === fval.toString().toLowerCase())) {
381
436
  return false;
382
437
  }
383
438
  }
384
- else{
439
+ else {
385
440
  if (!($.inArray(key, that.header.fields) !== -1 &&
386
441
  (typeof value === 'string' || typeof value === 'number') &&
387
442
  (value + '').toLowerCase().indexOf(fval) !== -1)) {
388
443
  return false;
389
444
  }
390
- };
445
+ }
391
446
  }
392
447
  return true;
393
448
  }) : this.data;
@@ -396,7 +451,7 @@
396
451
  BootstrapTable.prototype.onColumnSearch = function (event) {
397
452
  copyValues(this);
398
453
  var text = $.trim($(event.currentTarget).val());
399
- var $field = $(event.currentTarget).parent().parent().parent().data('field')
454
+ var $field = $(event.currentTarget).closest('[data-field]').data('field');
400
455
 
401
456
  if ($.isEmptyObject(this.filterColumnsPartial)) {
402
457
  this.filterColumnsPartial = {};
@@ -415,22 +470,48 @@
415
470
 
416
471
  BootstrapTable.prototype.clearFilterControl = function () {
417
472
  if (this.options.filterControl && this.options.filterShowClear) {
418
- $.each(this.options.values, function (i, item) {
473
+ var that = this,
474
+ cookies = collectBootstrapCookies(),
475
+ header = getCurrentHeader(that),
476
+ table = header.closest('table'),
477
+ controls = header.find(getCurrentSearchControls(that)),
478
+ search = that.$toolbar.find('.search input'),
479
+ timeoutId = 0;
480
+
481
+ $.each(that.options.valuesFilterControl, function (i, item) {
419
482
  item.value = '';
420
483
  });
421
484
 
422
- setValues(this);
423
-
424
- var controls = getCurrentHeader(this).find(getCurrentSearchControls(this)),
425
- timeoutId = 0;
485
+ setValues(that);
426
486
 
487
+ // Clear each type of filter if it exists.
488
+ // Requires the body to reload each time a type of filter is found because we never know
489
+ // which ones are going to be present.
427
490
  if (controls.length > 0) {
428
491
  this.filterColumnsPartial = {};
429
- clearTimeout(timeoutId);
430
- timeoutId = setTimeout(function () {
431
- $(controls[0]).trigger(controls[0].tagName === 'INPUT' ? 'keyup' : 'change');
432
- }, this.options.searchTimeOut);
492
+ $(controls[0]).trigger(controls[0].tagName === 'INPUT' ? 'keyup' : 'change');
493
+ }
494
+
495
+ if (search.length > 0) {
496
+ that.resetSearch();
433
497
  }
498
+
499
+ // use the default sort order if it exists. do nothing if it does not
500
+ if (that.options.sortName !== table.data('sortName') || that.options.sortOrder !== table.data('sortOrder')) {
501
+ var sorter = sprintf(header.find('[data-field="%s"]', $(controls[0]).closest('table').data('sortName')));
502
+ that.onSort(table.data('sortName'), table.data('sortName'));
503
+ $(sorter).find('.sortable').trigger('click');
504
+ }
505
+
506
+ // clear cookies once the filters are clean
507
+ clearTimeout(timeoutId);
508
+ timeoutId = setTimeout(function () {
509
+ if (cookies && cookies.length > 0) {
510
+ $.each(cookies, function (i, item) {
511
+ that.deleteCookie(item);
512
+ });
513
+ }
514
+ }, that.options.searchTimeOut);
434
515
  }
435
516
  };
436
517
  }(jQuery);
@@ -0,0 +1,226 @@
1
+ /**
2
+ * @author: Yura Knoxville
3
+ * @version: v1.0.0
4
+ */
5
+
6
+ !function ($) {
7
+
8
+ 'use strict';
9
+
10
+ var initBodyCaller,
11
+ tableGroups;
12
+
13
+ // it only does '%s', and return '' when arguments are undefined
14
+ var sprintf = function (str) {
15
+ var args = arguments,
16
+ flag = true,
17
+ i = 1;
18
+
19
+ str = str.replace(/%s/g, function () {
20
+ var arg = args[i++];
21
+
22
+ if (typeof arg === 'undefined') {
23
+ flag = false;
24
+ return '';
25
+ }
26
+ return arg;
27
+ });
28
+ return flag ? str : '';
29
+ };
30
+
31
+ var groupBy = function (array , f) {
32
+ var groups = {};
33
+ array.forEach(function(o) {
34
+ var group = f(o);
35
+ groups[group] = groups[group] || [];
36
+ groups[group].push(o);
37
+ });
38
+
39
+ return groups;
40
+ };
41
+
42
+ $.extend($.fn.bootstrapTable.defaults, {
43
+ groupBy: false,
44
+ groupByField: ''
45
+ });
46
+
47
+ var BootstrapTable = $.fn.bootstrapTable.Constructor,
48
+ _initSort = BootstrapTable.prototype.initSort,
49
+ _initBody = BootstrapTable.prototype.initBody,
50
+ _updateSelected = BootstrapTable.prototype.updateSelected;
51
+
52
+ BootstrapTable.prototype.initSort = function () {
53
+ _initSort.apply(this, Array.prototype.slice.apply(arguments));
54
+
55
+ var that = this;
56
+ tableGroups = [];
57
+
58
+ if ((this.options.groupBy) && (this.options.groupByField !== '')) {
59
+
60
+ if ((this.options.sortName != this.options.groupByField)) {
61
+ this.data.sort(function(a, b) {
62
+ return a[that.options.groupByField].localeCompare(b[that.options.groupByField]);
63
+ });
64
+ }
65
+
66
+ var that = this;
67
+ var groups = groupBy(that.data, function (item) {
68
+ return [item[that.options.groupByField]];
69
+ });
70
+
71
+ var index = 0;
72
+ $.each(groups, function(key, value) {
73
+ tableGroups.push({
74
+ id: index,
75
+ name: key
76
+ });
77
+
78
+ value.forEach(function(item) {
79
+ if (!item._data) {
80
+ item._data = {};
81
+ }
82
+
83
+ item._data['parent-index'] = index;
84
+ });
85
+
86
+ index++;
87
+ });
88
+ }
89
+ }
90
+
91
+ BootstrapTable.prototype.initBody = function () {
92
+ initBodyCaller = true;
93
+
94
+ _initBody.apply(this, Array.prototype.slice.apply(arguments));
95
+
96
+ if ((this.options.groupBy) && (this.options.groupByField !== '')) {
97
+ var that = this,
98
+ checkBox = false,
99
+ visibleColumns = 0;
100
+
101
+ this.columns.forEach(function(column) {
102
+ if (column.checkbox) {
103
+ checkBox = true;
104
+ } else {
105
+ if (column.visible) {
106
+ visibleColumns += 1;
107
+ }
108
+ }
109
+ });
110
+
111
+ if (this.options.detailView && !this.options.cardView) {
112
+ visibleColumns += 1;
113
+ }
114
+
115
+ tableGroups.forEach(function(item){
116
+ var html = [];
117
+
118
+ html.push(sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id));
119
+
120
+ if (that.options.detailView && !that.options.cardView) {
121
+ html.push('<td class="detail"></td>');
122
+ }
123
+
124
+ if (checkBox) {
125
+ html.push('<td class="bs-checkbox">',
126
+ '<input name="btSelectGroup" type="checkbox" />',
127
+ '</td>'
128
+ );
129
+ }
130
+
131
+ html.push('<td',
132
+ sprintf(' colspan="%s"', visibleColumns),
133
+ '>', item.name, '</td>'
134
+ );
135
+
136
+ html.push('</tr>');
137
+
138
+ that.$body.find('tr[data-parent-index='+item.id+']:first').before($(html.join('')));
139
+ });
140
+
141
+ this.$selectGroup = [];
142
+ this.$body.find('[name="btSelectGroup"]').each(function() {
143
+ var self = $(this);
144
+
145
+ that.$selectGroup.push({
146
+ group: self,
147
+ item: that.$selectItem.filter(function () {
148
+ return ($(this).closest('tr').data('parent-index') ===
149
+ self.closest('tr').data('group-index'));
150
+ })
151
+ });
152
+ });
153
+
154
+ this.$container.off('click', '.groupBy')
155
+ .on('click', '.groupBy', function() {
156
+ $(this).toggleClass('expanded');
157
+ that.$body.find('tr[data-parent-index='+$(this).closest('tr').data('group-index')+']').toggleClass('hidden');
158
+ });
159
+
160
+ this.$container.off('click', '[name="btSelectGroup"]')
161
+ .on('click', '[name="btSelectGroup"]', function (event) {
162
+ event.stopImmediatePropagation();
163
+
164
+ var self = $(this);
165
+ var checked = self.prop('checked');
166
+ that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'));
167
+ });
168
+ }
169
+
170
+ initBodyCaller = false;
171
+ this.updateSelected();
172
+ };
173
+
174
+ BootstrapTable.prototype.updateSelected = function () {
175
+ if (!initBodyCaller) {
176
+ _updateSelected.apply(this, Array.prototype.slice.apply(arguments));
177
+
178
+ if ((this.options.groupBy) && (this.options.groupByField !== '')) {
179
+ this.$selectGroup.forEach(function (item) {
180
+ var checkGroup = item.item.filter(':enabled').length ===
181
+ item.item.filter(':enabled').filter(':checked').length;
182
+
183
+ item.group.prop('checked', checkGroup);
184
+ });
185
+ }
186
+ }
187
+ };
188
+
189
+ BootstrapTable.prototype.getGroupSelections = function (index) {
190
+ var that = this;
191
+
192
+ return $.grep(this.data, function (row) {
193
+ return (row[that.header.stateField] && (row._data['parent-index'] === index));
194
+ });
195
+ };
196
+
197
+ BootstrapTable.prototype.checkGroup = function (index) {
198
+ this.checkGroup_(index, true);
199
+ };
200
+
201
+ BootstrapTable.prototype.uncheckGroup = function (index) {
202
+ this.checkGroup_(index, false);
203
+ };
204
+
205
+ BootstrapTable.prototype.checkGroup_ = function (index, checked) {
206
+ var rows;
207
+ var filter = function() {
208
+ return ($(this).closest('tr').data('parent-index') === index);
209
+ };
210
+
211
+ if (!checked) {
212
+ rows = this.getGroupSelections(index);
213
+ }
214
+
215
+ this.$selectItem.filter(filter).prop('checked', checked);
216
+
217
+
218
+ this.updateRows();
219
+ this.updateSelected();
220
+ if (checked) {
221
+ rows = this.getGroupSelections(index);
222
+ }
223
+ this.trigger(checked ? 'check-all' : 'uncheck-all', rows);
224
+ };
225
+
226
+ }(jQuery);