bootstrap-table-rails 1.9.1 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);