bootstrap-table.js 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /**
  2. * @author zhixin wen <wenzhixin2010@gmail.com>
  3. * version: 1.1.2
  4. * https://github.com/wenzhixin/bootstrap-table/
  5. */
  6. !function ($) {
  7. 'use strict';
  8. // TOOLS DEFINITION
  9. // ======================
  10. // it only does '%s', and return '' when arguments are undefined
  11. var sprintf = function(str) {
  12. var args = arguments,
  13. flag = true,
  14. i = 1;
  15. str = str.replace(/%s/g, function() {
  16. var arg = args[i++];
  17. if (typeof arg === 'undefined') {
  18. flag = false;
  19. return '';
  20. }
  21. return arg;
  22. });
  23. if (flag) {
  24. return str;
  25. }
  26. return '';
  27. };
  28. var getPropertyFromOther = function(list, from, to, value) {
  29. var result = '';
  30. $.each(list, function(i, item) {
  31. if (item[from] === value) {
  32. result = item[to];
  33. return false;
  34. }
  35. return true;
  36. });
  37. return result;
  38. };
  39. // BOOTSTRAP TABLE CLASS DEFINITION
  40. // ======================
  41. var BootstrapTable = function(el, options) {
  42. this.options = options;
  43. this.$el = $(el);
  44. this.$el_ = this.$el.clone();
  45. this.init();
  46. };
  47. BootstrapTable.DEFAULTS = {
  48. classes: 'table table-hover',
  49. height: undefined,
  50. undefinedText: '-',
  51. sortName: undefined,
  52. sortOrder: 'asc',
  53. striped: false,
  54. columns: [],
  55. data: [],
  56. method: 'get',
  57. url: undefined,
  58. contentType: 'application/json',
  59. queryParams: function(params) {return {};},
  60. responseHandler: function(res) {return res;},
  61. pagination: false,
  62. sidePagination: 'client', // client or server
  63. totalRows: 0, // server side need to set
  64. pageNumber: 1,
  65. pageSize: 10,
  66. pageList: [10, 25, 50, 100],
  67. search: false,
  68. selectItemName: 'btSelectItem',
  69. showHeader: true,
  70. showColumns: false,
  71. minimunCountColumns: 1,
  72. idField: undefined,
  73. cardView: false,
  74. clickToSelect: false,
  75. singleSelect: false,
  76. toolbar: undefined,
  77. checkBoxHeader: false, //True will display check-all checkbox in header row vs. text
  78. rowStyle: function(row, index) {return {};},
  79. formatLoadingMessage: function() {
  80. return 'Loading, please wait…';
  81. },
  82. formatRecordsPerPage: function(pageNumber) {
  83. return sprintf('%s records per page', pageNumber);
  84. },
  85. formatShowingRows: function(pageFrom, pageTo, totalRows) {
  86. return sprintf('Showing %s to %s of %s rows', pageFrom, pageTo, totalRows);
  87. },
  88. formatSearch: function() {
  89. return 'Search';
  90. },
  91. formatNoMatches: function() {
  92. return 'No matching records found';
  93. },
  94. onAll: function(name, args) {return false;},
  95. onClickRow: function(item, $element) {return false;},
  96. onDblClickRow: function(item, $element) {return false;},
  97. onSort: function(name, order) {return false;},
  98. onCheck: function(row) {return false;},
  99. onUncheck: function(row) {return false;},
  100. onCheckAll: function() {return false;},
  101. onUncheckAll: function() {return false;},
  102. onLoadSuccess: function(data) {return false;},
  103. onLoadError: function(status) {return false;}
  104. };
  105. BootstrapTable.COLUMN_DEFAULTS = {
  106. radio: false,
  107. checkbox: false,
  108. field: undefined,
  109. title: undefined,
  110. class: undefined,
  111. align: undefined, // left, right, center
  112. valign: undefined, // top, middle, bottom
  113. width: undefined,
  114. sortable: false,
  115. order: 'asc', // asc, desc
  116. visible: true,
  117. switchable: true,
  118. formatter: undefined,
  119. sorter: undefined
  120. };
  121. BootstrapTable.EVENTS = {
  122. 'all.bs.table': 'onAll',
  123. 'click-row.bs.table': 'onClickRow',
  124. 'dbl-click-row.bs.table': 'onDblClickRow',
  125. 'sort.bs.table': 'onSort',
  126. 'check.bs.table': 'onCheck',
  127. 'uncheck.bs.table': 'onUncheck',
  128. 'check-all.bs.table': 'onCheckAll',
  129. 'uncheck-all.bs.table': 'onUncheckAll',
  130. 'load-success.bs.table': 'onLoadSuccess',
  131. 'load-error.bs.table': 'onLoadError'
  132. };
  133. BootstrapTable.prototype.init = function() {
  134. this.initContainer();
  135. this.initHeader();
  136. this.initData();
  137. this.initToolbar();
  138. this.initPagination();
  139. this.initBody();
  140. this.initServer();
  141. };
  142. BootstrapTable.prototype.initContainer = function() {
  143. this.$container = $([
  144. '<div class="bootstrap-table">',
  145. '<div class="fixed-table-toolbar"></div>',
  146. '<div class="fixed-table-container">',
  147. '<div class="fixed-table-header"><table></table></div>',
  148. '<div class="fixed-table-body">',
  149. '<div class="fixed-table-loading">',
  150. this.options.formatLoadingMessage(),
  151. '</div>',
  152. '</div>',
  153. '<div class="fixed-table-pagination"></div>',
  154. '</div>',
  155. '</div>'].join(''));
  156. this.$container.insertAfter(this.$el);
  157. this.$container.find('.fixed-table-body').append(this.$el);
  158. this.$container.after('<div class="clearfix"></div>');
  159. this.$loading = this.$container.find('.fixed-table-loading');
  160. this.$el.addClass(this.options.classes);
  161. if (this.options.striped) {
  162. this.$el.addClass('table-striped');
  163. }
  164. };
  165. BootstrapTable.prototype.initHeader = function() {
  166. var that = this,
  167. columns = [],
  168. visibleColumns = [],
  169. html = [];
  170. this.$header = this.$el.find('thead');
  171. if (!this.$header.length) {
  172. this.$header = $('<thead></thead>').appendTo(this.$el);
  173. }
  174. if (!this.$header.find('tr').length) {
  175. this.$header.append('<tr></tr>');
  176. }
  177. this.$header.find('th').each(function() {
  178. var column = $.extend({}, {
  179. title: $(this).html(),
  180. class: $(this).attr('class')
  181. }, $(this).data());
  182. columns.push(column);
  183. });
  184. this.options.columns = $.extend({}, columns, this.options.columns);
  185. $.each(this.options.columns, function(i, column) {
  186. that.options.columns[i] = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, column);
  187. });
  188. this.header = {
  189. fields: [],
  190. styles: [],
  191. formatters: [],
  192. sorters: []
  193. };
  194. $.each(this.options.columns, function(i, column) {
  195. var text = '',
  196. style = sprintf('text-align: %s; ', column.align) +
  197. sprintf('vertical-align: %s; ', column.valign),
  198. order = that.options.sortOrder || column.order;
  199. if (!column.visible) {
  200. return;
  201. }
  202. visibleColumns.push(column);
  203. that.header.fields.push(column.field);
  204. that.header.styles.push(style);
  205. that.header.formatters.push(column.formatter);
  206. that.header.sorters.push(column.sorter);
  207. style += sprintf('width: %spx; ', column.checkbox || column.radio ? 36 : column.width);
  208. style += column.sortable ? 'cursor: pointer; ' : '';
  209. html.push('<th',
  210. column.checkbox || column.radio ? ' class="bs-checkbox"' :
  211. sprintf(' class="%s"', column.class),
  212. sprintf(' style="%s"', style),
  213. '>');
  214. html.push('<div class="th-inner">');
  215. text = column.title;
  216. if (that.options.sortName === column.field && column.sortable) {
  217. text += that.getCaretHtml();
  218. }
  219. if (column.checkbox) {
  220. if (!that.options.singleSelect && that.options.checkBoxHeader) {
  221. text = '<input name="btSelectAll" type="checkbox" />';
  222. }
  223. that.header.stateField = column.field;
  224. }
  225. if (column.radio) {
  226. text = '';
  227. that.header.stateField = column.field;
  228. that.options.singleSelect = true;
  229. }
  230. html.push(text);
  231. html.push('</div>');
  232. html.push('</th>');
  233. });
  234. this.$header.find('tr').html(html.join(''));
  235. this.$header.find('th').each(function (i) {
  236. $(this).data(visibleColumns[i]);
  237. if (visibleColumns[i].sortable) {
  238. $(this).off('click').on('click', $.proxy(that.onSort, that));
  239. }
  240. });
  241. if (!this.options.showHeader || this.options.cardView) {
  242. this.$header.hide();
  243. this.$container.find('.fixed-table-header').hide();
  244. this.$loading.css('top', 0);
  245. }
  246. this.$selectAll = this.$header.find('[name="btSelectAll"]');
  247. this.$selectAll.off('click').on('click', function () {
  248. var checked = $(this).prop('checked');
  249. that[checked ? 'checkAll' : 'uncheckAll']();
  250. });
  251. };
  252. BootstrapTable.prototype.initData = function (data, append) {
  253. if (append) {
  254. this.data = this.data.concat(data);
  255. } else {
  256. this.data = data || this.options.data;
  257. }
  258. this.options.data = this.data;
  259. this.initSort();
  260. };
  261. BootstrapTable.prototype.initSort = function () {
  262. var name = this.options.sortName,
  263. order = this.options.sortOrder === 'desc' ? -1 : 1,
  264. index = $.inArray(this.options.sortName, this.header.fields);
  265. if (index !== -1) {
  266. var sorter = this.header.sorters[index];
  267. this.data.sort(function (a, b) {
  268. if (typeof sorter === 'function') {
  269. return order * sorter(a[name], b[name]);
  270. }
  271. if (typeof sorter === 'string') {
  272. return order * eval(sorter + '(a[name], b[name])'); // eval ?
  273. }
  274. if (a[name] === b[name]) {
  275. return 0;
  276. }
  277. if (a[name] < b[name]) {
  278. return order * -1;
  279. }
  280. return order;
  281. });
  282. }
  283. };
  284. BootstrapTable.prototype.onSort = function (event) {
  285. var $this = $(event.currentTarget),
  286. $this_ = this.$header.find('th').eq($this.index());
  287. this.$header.add(this.$header_).find('span.order').remove();
  288. this.options.sortName = $this.data('field');
  289. this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc';
  290. this.trigger('sort', this.options.sortName, this.options.sortOrder);
  291. $this.add($this_).data('order', this.options.sortOrder)
  292. .find('.th-inner').append(this.getCaretHtml());
  293. if (this.options.sidePagination === 'server') {
  294. this.initServer();
  295. return;
  296. }
  297. this.initSort();
  298. this.initBody();
  299. };
  300. BootstrapTable.prototype.initToolbar = function () {
  301. var that = this,
  302. html = [],
  303. timeoutId = 0,
  304. $keepOpen,
  305. $search;
  306. this.$toolbar = this.$container.find('.fixed-table-toolbar').html('');
  307. if (typeof this.options.toolbar === 'string') {
  308. $('<div class="bars pull-left"></div>')
  309. .appendTo(this.$toolbar)
  310. .append($(this.options.toolbar));
  311. }
  312. if (this.options.showColumns) {
  313. html = [];
  314. html.push('<div class="columns pull-right keep-open">',
  315. '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',
  316. '<i class="glyphicon glyphicon-th icon-th"></i>',
  317. ' <span class="caret"></span>',
  318. '</button>',
  319. '<ul class="dropdown-menu" role="menu">');
  320. $.each(this.options.columns, function (i, column) {
  321. if (column.radio || column.checkbox) {
  322. return;
  323. }
  324. var checked = column.visible ? ' checked="checked"' : '';
  325. if (column.switchable) {
  326. html.push(sprintf('<li>' +
  327. '<label><input type="checkbox" value="%s"%s> %s</label>' +
  328. '</li>', i, checked, column.title));
  329. }
  330. });
  331. html.push('</ul>',
  332. '</div>');
  333. this.$toolbar.append(html.join(''));
  334. $keepOpen = this.$toolbar.find('.keep-open');
  335. $keepOpen.find('li').off('click').on('click', function (event) {
  336. event.stopImmediatePropagation();
  337. });
  338. $keepOpen.find('input').off('click').on('click', function () {
  339. var $this = $(this),
  340. $items = $keepOpen.find('input').prop('disabled', false);
  341. that.options.columns[$this.val()].visible = $this.prop('checked');
  342. that.initHeader();
  343. that.initBody();
  344. if ($items.filter(':checked').length <= that.options.minimunCountColumns) {
  345. $items.filter(':checked').prop('disabled', true);
  346. }
  347. });
  348. }
  349. if (this.options.search) {
  350. html = [];
  351. html.push(
  352. '<div class="pull-right search">',
  353. sprintf('<input class="form-control" type="text" placeholder="%s">',
  354. this.options.formatSearch()),
  355. '</div>');
  356. this.$toolbar.append(html.join(''));
  357. $search = this.$toolbar.find('.search input');
  358. $search.off('keyup').on('keyup', function (event) {
  359. clearTimeout(timeoutId); // doesn't matter if it's 0
  360. timeoutId = setTimeout($.proxy(that.onSearch, that), 500, event); // 500ms
  361. });
  362. }
  363. };
  364. BootstrapTable.prototype.onSearch = function (event) {
  365. var that = this,
  366. text = $.trim($(event.currentTarget).val());
  367. if (text === this.searchText) {
  368. return;
  369. }
  370. this.searchText = text;
  371. if (this.options.sidePagination !== 'server') {
  372. var s = that.searchText.toLowerCase();
  373. this.data = $.grep(this.options.data, function (item) {
  374. for (var key in item) {
  375. if ((typeof item[key] === 'string' ||
  376. typeof item[key] === 'number') &&
  377. (item[key] + '').toLowerCase().indexOf(s) !== -1) {
  378. return true;
  379. }
  380. }
  381. return false;
  382. });
  383. }
  384. this.options.pageNumber = 1;
  385. this.updatePagination();
  386. };
  387. BootstrapTable.prototype.initPagination = function () {
  388. this.$pagination = this.$container.find('.fixed-table-pagination');
  389. if (!this.options.pagination) {
  390. return;
  391. }
  392. var that = this,
  393. html = [],
  394. i, from, to,
  395. $pageList,
  396. $first, $pre,
  397. $next, $last,
  398. $number,
  399. data = this.searchText ? this.data : this.options.data;
  400. if (this.options.sidePagination !== 'server') {
  401. this.options.totalRows = data.length;
  402. }
  403. this.totalPages = 0;
  404. if (this.options.totalRows) {
  405. this.totalPages = ~~((this.options.totalRows - 1) / this.options.pageSize) + 1;
  406. }
  407. if (this.totalPages > 0 && this.options.pageNumber > this.totalPages) {
  408. this.options.pageNumber = this.totalPages;
  409. }
  410. this.pageFrom = (this.options.pageNumber - 1) * this.options.pageSize + 1;
  411. this.pageTo = this.options.pageNumber * this.options.pageSize;
  412. if (this.pageTo > this.options.totalRows) {
  413. this.pageTo = this.options.totalRows;
  414. }
  415. html.push(
  416. '<div class="pull-left pagination-detail">',
  417. '<span class="pagination-info">',
  418. this.options.formatShowingRows(this.pageFrom, this.pageTo, this.options.totalRows),
  419. '</span>');
  420. html.push('<span class="page-list">');
  421. var pageNumber = [
  422. '<span class="btn-group dropup">',
  423. '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',
  424. '<span class="page-size">',
  425. this.options.pageSize,
  426. '</span>',
  427. ' <span class="caret"></span>',
  428. '</button>',
  429. '<ul class="dropdown-menu" role="menu">'],
  430. pageList = this.options.pageList;
  431. if (typeof this.options.pageList === 'string') {
  432. pageList = eval(this.options.pageList);
  433. }
  434. $.each(pageList, function (i, page) {
  435. var active = page === that.options.pageSize ? ' class="active"' : '';
  436. pageNumber.push(sprintf('<li%s><a href="javascript:void(0)">%s</a></li>', active, page));
  437. });
  438. pageNumber.push('</ul></span>');
  439. html.push(this.options.formatRecordsPerPage(pageNumber.join('')));
  440. html.push('</span>');
  441. html.push('</div>',
  442. '<div class="pull-right">',
  443. '<ul class="pagination">',
  444. '<li class="page-first"><a href="javascript:void(0)">&lt;&lt;</a></li>',
  445. '<li class="page-pre"><a href="javascript:void(0)">&lt;</a></li>');
  446. if (this.totalPages < 5) {
  447. from = 1;
  448. to = this.totalPages;
  449. } else {
  450. from = this.options.pageNumber - 2;
  451. to = from + 4;
  452. if (from < 1) {
  453. from = 1;
  454. to = 5;
  455. }
  456. if (to > this.totalPages) {
  457. to = this.totalPages;
  458. from = to - 4;
  459. }
  460. }
  461. for (i = from; i <= to; i++) {
  462. html.push('<li class="page-number' + (i === this.options.pageNumber ? ' active' : '') + '">',
  463. '<a href="javascript:void(0)">', i ,'</a>',
  464. '</li>');
  465. }
  466. html.push(
  467. '<li class="page-next"><a href="javascript:void(0)">&gt;</a></li>',
  468. '<li class="page-last"><a href="javascript:void(0)">&gt;&gt;</a></li>',
  469. '</ul>',
  470. '</div>');
  471. this.$pagination.html(html.join(''));
  472. $pageList = this.$pagination.find('.page-list a');
  473. $first = this.$pagination.find('.page-first');
  474. $pre = this.$pagination.find('.page-pre');
  475. $next = this.$pagination.find('.page-next');
  476. $last = this.$pagination.find('.page-last');
  477. $number = this.$pagination.find('.page-number');
  478. if (this.options.pageNumber <= 1) {
  479. $first.addClass('disabled');
  480. $pre.addClass('disabled');
  481. }
  482. if (this.options.pageNumber >= this.totalPages) {
  483. $next.addClass('disabled');
  484. $last.addClass('disabled');
  485. }
  486. $pageList.off('click').on('click', $.proxy(this.onPageListChange, this));
  487. $first.off('click').on('click', $.proxy(this.onPageFirst, this));
  488. $pre.off('click').on('click', $.proxy(this.onPagePre, this));
  489. $next.off('click').on('click', $.proxy(this.onPageNext, this));
  490. $last.off('click').on('click', $.proxy(this.onPageLast, this));
  491. $number.off('click').on('click', $.proxy(this.onPageNumber, this));
  492. };
  493. BootstrapTable.prototype.updatePagination = function () {
  494. this.resetRows();
  495. this.initPagination();
  496. if (this.options.sidePagination === 'server') {
  497. this.initServer();
  498. } else {
  499. this.initBody();
  500. }
  501. };
  502. BootstrapTable.prototype.onPageListChange = function (event) {
  503. var $this = $(event.currentTarget);
  504. $this.parent().addClass('active').siblings().removeClass('active');
  505. this.options.pageSize = +$this.text();
  506. this.$toolbar.find('.page-size').text(this.options.pageSize);
  507. this.updatePagination();
  508. };
  509. BootstrapTable.prototype.onPageFirst = function () {
  510. this.options.pageNumber = 1;
  511. this.updatePagination();
  512. };
  513. BootstrapTable.prototype.onPagePre = function () {
  514. this.options.pageNumber--;
  515. this.updatePagination();
  516. };
  517. BootstrapTable.prototype.onPageNext = function () {
  518. this.options.pageNumber++;
  519. this.updatePagination();
  520. };
  521. BootstrapTable.prototype.onPageLast = function () {
  522. this.options.pageNumber = this.totalPages;
  523. this.updatePagination();
  524. };
  525. BootstrapTable.prototype.onPageNumber = function (event) {
  526. if (this.options.pageNumber === +$(event.currentTarget).text()) {
  527. return;
  528. }
  529. this.options.pageNumber = +$(event.currentTarget).text();
  530. this.updatePagination();
  531. };
  532. BootstrapTable.prototype.initBody = function () {
  533. var that = this,
  534. html = [],
  535. data = this.searchText ? this.data : this.options.data;
  536. this.$body = this.$el.find('tbody');
  537. if (!this.$body.length) {
  538. this.$body = $('<tbody></tbody>').appendTo(this.$el);
  539. }
  540. if (this.options.sidePagination === 'server') {
  541. data = this.data;
  542. }
  543. if (!this.options.pagination || this.options.sidePagination === 'server') {
  544. this.pageFrom = 1;
  545. this.pageTo = data.length;
  546. }
  547. for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
  548. var item = data[i],
  549. style = {},
  550. csses = [];
  551. if (typeof this.options.rowStyle === 'function') {
  552. style = this.options.rowStyle(item, i);
  553. } else if (typeof this.options.rowStyle === 'string') {
  554. style = eval(this.options.rowStyle + '(item, i)');
  555. }
  556. if (style && style.css) {
  557. for (var key in style.css) {
  558. csses.push(key + ': ' + style.css[key]);
  559. }
  560. }
  561. html.push('<tr',
  562. sprintf(' class="%s"', style.classes),
  563. sprintf(' data-index="%s"', i),
  564. '>'
  565. );
  566. if (this.options.cardView) {
  567. html.push(sprintf('<td colspan="%s">', this.header.fields.length));
  568. }
  569. $.each(this.header.fields, function (j, field) {
  570. var text = '',
  571. value = item[field],
  572. type = '',
  573. style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; '));
  574. if (typeof that.header.formatters[j] === 'function') {
  575. value = that.header.formatters[j](value, item, i);
  576. } else if (typeof that.header.formatters[j] === 'string') {
  577. value = eval(that.header.formatters[j] + '(value, item, i)'); // eval ?
  578. }
  579. if (that.options.columns[j].checkbox || that.options.columns[j].radio) {
  580. type = that.options.columns[j].checkbox ? 'checkbox' : type;
  581. type = that.options.columns[j].radio ? 'radio' : type;
  582. text = ['<td class="bs-checkbox">',
  583. '<input' +
  584. sprintf(' data-index="%s"', i) +
  585. sprintf(' name="%s"', that.options.selectItemName) +
  586. sprintf(' type="%s"', type) +
  587. sprintf(' value="%s"', item[that.options.idField]) +
  588. sprintf(' checked="%s"', value ? 'checked' : undefined) + ' />',
  589. '</td>'].join('');
  590. } else {
  591. value = typeof value === 'undefined' ? that.options.undefinedText : value;
  592. text = that.options.cardView ?
  593. ['<div class="card-view">',
  594. sprintf('<span class="title" %s>%s</span>', style,
  595. getPropertyFromOther(that.options.columns, 'field', 'title', field)),
  596. sprintf('<span class="value">%s</span>', value),
  597. '</div>'].join('') :
  598. [sprintf('<td %s>', style),
  599. value,
  600. '</td>'].join('');
  601. }
  602. html.push(text);
  603. });
  604. if (this.options.cardView) {
  605. html.push('</td>');
  606. }
  607. html.push('</tr>');
  608. }
  609. // show no records
  610. if (!html.length) {
  611. html.push('<tr class="no-records-found">',
  612. sprintf('<td colspan="%s">%s</td>', this.header.fields.length, this.options.formatNoMatches()),
  613. '</tr>');
  614. }
  615. this.$body.html(html.join(''));
  616. this.$container.find('.fixed-table-body').scrollTop(0);
  617. this.$body.find('tr').off('click').on('click', function () {
  618. that.trigger('click-row', that.data[$(this).data('index')], $(this));
  619. if (that.options.clickToSelect) {
  620. $(this).find(sprintf('[name="%s"]', that.options.selectItemName)).trigger('click');
  621. }
  622. });
  623. this.$body.find('tr').off('dblclick').on('dblclick', function () {
  624. that.trigger('dbl-click-row', that.data[$(this).data('index')], $(this));
  625. });
  626. this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName));
  627. this.$selectItem.off('click').on('click', function (event) {
  628. event.stopImmediatePropagation();
  629. var checkAll = that.$selectItem.length === that.$selectItem.filter(':checked').length,
  630. checked = $(this).prop('checked') || $(this).is(':radio'),
  631. row = that.data[$(this).data('index')];
  632. that.$selectAll.add(that.$selectAll_).prop('checked', checkAll);
  633. row[that.header.stateField] = checked;
  634. that.trigger(checked ? 'check' : 'uncheck', row);
  635. if (that.options.singleSelect) {
  636. that.$selectItem.not(this).each(function () {
  637. that.data[$(this).data('index')][that.header.stateField] = false;
  638. });
  639. that.$selectItem.filter(':checked').not(this).prop('checked', false);
  640. }
  641. // $(this).parents('tr')[checked ? 'addClass' : 'removeClass']('selected');
  642. });
  643. this.resetView();
  644. };
  645. BootstrapTable.prototype.initServer = function () {
  646. var that = this,
  647. data = {};
  648. if (!this.options.url) {
  649. return;
  650. }
  651. this.$loading.show();
  652. if (typeof this.options.queryParams === 'function') {
  653. data = this.options.queryParams({
  654. pageSize: this.options.pageSize,
  655. pageNumber: this.options.pageNumber,
  656. searchText: this.searchText,
  657. sortName: this.options.sortName,
  658. sortOrder: this.options.sortOrder
  659. });
  660. } else if (typeof this.options.queryParams === 'string') {
  661. data = eval([this.options.queryParams,
  662. '({',
  663. 'pageSize: this.options.pageSize,',
  664. 'pageNumber: this.options.pageNumber,',
  665. 'searchText: this.searchText,',
  666. 'sortName: this.options.sortName,',
  667. 'sortOrder: this.options.sortOrder',
  668. '})'].join(''));
  669. }
  670. $.ajax({
  671. type: this.options.method,
  672. url: this.options.url,
  673. data: data,
  674. contentType: this.options.contentType,
  675. dataType: 'json',
  676. success: function (res) {
  677. if (typeof that.options.responseHandler === 'function') {
  678. res = that.options.responseHandler(res);
  679. } else if (typeof that.options.responseHandler === 'string') {
  680. res = eval(that.options.responseHandler + '(res)');
  681. }
  682. var data = res;
  683. if (that.options.sidePagination === 'server') {
  684. that.options.totalRows = res.total;
  685. data = res.rows;
  686. }
  687. that.load(data);
  688. that.trigger('load-success', data);
  689. },
  690. error: function (res) {
  691. that.trigger('load-error', res.status);
  692. },
  693. complete: function () {
  694. that.$loading.hide();
  695. }
  696. });
  697. };
  698. BootstrapTable.prototype.getCaretHtml = function () {
  699. return ['<span class="order' + (this.options.sortOrder === 'desc' ? '' : ' dropup') + '">',
  700. '<span class="caret" style="margin: 10px 5px;"></span>',
  701. '</span>'].join('');
  702. };
  703. BootstrapTable.prototype.updateRows = function (checked) {
  704. var that = this;
  705. this.$selectItem.each(function () {
  706. that.data[$(this).data('index')][that.header.stateField] = checked;
  707. });
  708. };
  709. BootstrapTable.prototype.resetRows = function () {
  710. var that = this;
  711. $.each(this.data, function (i, row) {
  712. that.$selectAll.prop('checked', false);
  713. that.$selectItem.prop('checked', false);
  714. row[that.header.stateField] = false;
  715. });
  716. };
  717. BootstrapTable.prototype.trigger = function (name) {
  718. var args = Array.prototype.slice.call(arguments, 1);
  719. name += '.bs.table';
  720. this.options[BootstrapTable.EVENTS[name]].apply(this.options, args);
  721. this.$el.trigger($.Event(name), args);
  722. this.options.onAll(name, args);
  723. this.$el.trigger($.Event('all.bs.table'), [name, args]);
  724. };
  725. // PUBLIC FUNCTION DEFINITION
  726. // =======================
  727. BootstrapTable.prototype.resetView = function (params) {
  728. var that = this,
  729. header = this.header;
  730. if (params && params.height) {
  731. this.options.height = params.height;
  732. }
  733. this.$selectAll.prop('checked', this.$selectItem.length > 0 &&
  734. this.$selectItem.length === this.$selectItem.filter(':checked').length);
  735. if (this.options.height) {
  736. var toolbarHeight = +this.$toolbar.children().outerHeight(true),
  737. paginationHeight = +this.$pagination.children().outerHeight(true),
  738. height = this.options.height - toolbarHeight - paginationHeight;
  739. this.$container.find('.fixed-table-container').css('height', height + 'px');
  740. }
  741. if (this.options.cardView) {
  742. return;
  743. }
  744. if (this.options.showHeader) {
  745. this.$header_ = this.$header.clone(true);
  746. this.$body_ = this.$body.clone(true);
  747. this.$selectAll_ = this.$header_.find('[name="btSelectAll"]');
  748. this.$el.css('margin-top', -(this.$header.height() + 1));
  749. this.$container.find('.fixed-table-header table')
  750. .css('width', this.$el.css('width'))
  751. .html('').attr('class', this.$el.attr('class'))
  752. .append(this.$header_, this.$body_);
  753. }
  754. if (this.options.height && this.options.showHeader) {
  755. this.$container.find('.fixed-table-container').css('padding-bottom', '38px')
  756. }
  757. };
  758. BootstrapTable.prototype.load = function (data) {
  759. this.initData(data);
  760. this.initPagination();
  761. this.initBody();
  762. };
  763. BootstrapTable.prototype.append = function (data) {
  764. this.initData(data, true);
  765. this.initBody();
  766. };
  767. BootstrapTable.prototype.mergeCells = function (options) {
  768. var row = options.index,
  769. col = $.inArray(options.field, this.header.fields),
  770. rowspan = options.rowspan || 1,
  771. colspan = options.colspan || 1,
  772. i, j,
  773. $tr = this.$body.find('tr'),
  774. $td = $tr.eq(row).find('td').eq(col);
  775. if (row < 0 || col < 0 || row >= this.data.length) {
  776. return;
  777. }
  778. for (i = row; i < row + rowspan; i++) {
  779. for (j = col; j < col + colspan; j++) {
  780. $tr.eq(i).find('td').eq(j).hide();
  781. }
  782. }
  783. $td.attr('rowspan', rowspan).attr('colspan', colspan).show();
  784. };
  785. BootstrapTable.prototype.getSelections = function () {
  786. var that = this;
  787. return $.grep(this.data, function (row) {
  788. return row[that.header.stateField];
  789. });
  790. };
  791. BootstrapTable.prototype.checkAll = function () {
  792. this.$selectAll.add(this.$selectAll_).prop('checked', true);
  793. this.$selectItem.prop('checked', true);
  794. this.updateRows(true);
  795. this.trigger('check-all');
  796. };
  797. BootstrapTable.prototype.uncheckAll = function () {
  798. this.$selectAll.add(this.$selectAll_).prop('checked', false);
  799. this.$selectItem.prop('checked', false);
  800. this.updateRows(false);
  801. this.trigger('uncheck-all');
  802. };
  803. BootstrapTable.prototype.destroy = function () {
  804. var $toolbar = $(this.options.toolbar).clone(true, true);
  805. this.$container.next().remove();
  806. this.$container.replaceWith(this.$el_);
  807. $toolbar.insertBefore(this.$el_);
  808. return this.$el_;
  809. };
  810. BootstrapTable.prototype.showLoading = function () {
  811. this.$loading.show();
  812. };
  813. BootstrapTable.prototype.hideLoading = function () {
  814. this.$loading.hide();
  815. };
  816. BootstrapTable.prototype.refresh = function () {
  817. this.initServer();
  818. };
  819. // BOOTSTRAP TABLE PLUGIN DEFINITION
  820. // =======================
  821. $.fn.bootstrapTable = function (option, _relatedTarget) {
  822. var allowedMethods = [
  823. 'getSelections',
  824. 'load', 'append', 'mergeCells',
  825. 'checkAll', 'uncheckAll',
  826. 'destroy', 'resetView',
  827. 'showLoading', 'hideLoading',
  828. 'refresh'
  829. ],
  830. value;
  831. this.each(function () {
  832. var $this = $(this),
  833. data = $this.data('bootstrap.table'),
  834. options = $.extend({}, BootstrapTable.DEFAULTS, $this.data(), typeof option === 'object' && option);
  835. if (!data) {
  836. $this.data('bootstrap.table', (data = new BootstrapTable(this, options)));
  837. }
  838. if (typeof option === 'string') {
  839. if ($.inArray(option, allowedMethods) < 0) {
  840. throw "Unknown method: " + option;
  841. }
  842. value = data[option](_relatedTarget);
  843. }
  844. });
  845. return value ? value : this;
  846. };
  847. $.fn.bootstrapTable.Constructor = BootstrapTable;
  848. $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS;
  849. $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS;
  850. // BOOTSTRAP TABLE INIT
  851. // =======================
  852. $(function () {
  853. $('[data-toggle="table"]').bootstrapTable();
  854. });
  855. }(jQuery);