bootstrap-table.js 34 KB

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