1/** 2 * @author zhixin wen <[email protected]> 3 * version: 1.12.1 4 * https://github.com/wenzhixin/bootstrap-table/ 5 */ 6 7(function ($) { 8 'use strict'; 9 10 // TOOLS DEFINITION 11 // ====================== 12 13 var bootstrapVersion = 3; 14 try { 15 bootstrapVersion = parseInt($.fn.dropdown.Constructor.VERSION, 10); 16 } catch (e) {} 17 var bs = { 18 3: { 19 buttonsClass: 'default', 20 iconsPrefix: 'glyphicon', 21 icons: { 22 paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down', 23 paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', 24 refresh: 'glyphicon-refresh icon-refresh', 25 toggleOff: 'glyphicon-list-alt icon-list-alt', 26 toggleOn: 'glyphicon-list-alt icon-list-alt', 27 columns: 'glyphicon-th icon-th', 28 detailOpen: 'glyphicon-plus icon-plus', 29 detailClose: 'glyphicon-minus icon-minus', 30 fullscreen: 'glyphicon-fullscreen' 31 }, 32 pullClass: 'pull', 33 toobarDropdowHtml: ['<ul class="dropdown-menu" role="menu">', '</ul>'], 34 toobarDropdowItemHtml: '<li role="menuitem"><label>%s</label></li>', 35 pageDropdownHtml: ['<ul class="dropdown-menu" role="menu">', '</ul>'], 36 pageDropdownItemHtml: '<li role="menuitem" class="%s"><a href="#">%s</a></li>' 37 }, 38 4: { 39 buttonsClass: 'secondary', 40 iconsPrefix: 'fa', 41 icons: { 42 paginationSwitchDown: 'fa-toggle-down', 43 paginationSwitchUp: 'fa-toggle-up', 44 refresh: 'fa-refresh', 45 toggleOff: 'fa-toggle-off', 46 toggleOn: 'fa-toggle-on', 47 columns: 'fa-th-list', 48 detailOpen: 'fa-plus', 49 detailClose: 'fa-minus', 50 fullscreen: 'fa-arrows-alt' 51 }, 52 pullClass: 'float', 53 toobarDropdowHtml: ['<div class="dropdown-menu dropdown-menu-right">', '</div>'], 54 toobarDropdowItemHtml: '<label class="dropdown-item">%s</label>', 55 pageDropdownHtml: ['<div class="dropdown-menu">', '</div>'], 56 pageDropdownItemHtml: '<a class="dropdown-item %s" href="#">%s</a>' 57 } 58 }[bootstrapVersion]; 59 60 var cachedWidth = null; 61 62 // it only does '%s', and return '' when arguments are undefined 63 var sprintf = function (str) { 64 var args = arguments, 65 flag = true, 66 i = 1; 67 68 str = str.replace(/%s/g, function () { 69 var arg = args[i++]; 70 71 if (typeof arg === 'undefined') { 72 flag = false; 73 return ''; 74 } 75 return arg; 76 }); 77 return flag ? str : ''; 78 }; 79 80 var getPropertyFromOther = function (list, from, to, value) { 81 var result = ''; 82 $.each(list, function (i, item) { 83 if (item[from] === value) { 84 result = item[to]; 85 return false; 86 } 87 return true; 88 }); 89 return result; 90 }; 91 92 // http://jsfiddle.net/wenyi/47nz7ez9/3/ 93 var setFieldIndex = function (columns) { 94 var i, j, k, 95 totalCol = 0, 96 flag = []; 97 98 for (i = 0; i < columns[0].length; i++) { 99 totalCol += columns[0][i].colspan || 1; 100 } 101 102 for (i = 0; i < columns.length; i++) { 103 flag[i] = []; 104 for (j = 0; j < totalCol; j++) { 105 flag[i][j] = false; 106 } 107 } 108 109 for (i = 0; i < columns.length; i++) { 110 for (j = 0; j < columns[i].length; j++) { 111 var r = columns[i][j], 112 rowspan = r.rowspan || 1, 113 colspan = r.colspan || 1, 114 index = $.inArray(false, flag[i]); 115 116 if (colspan === 1) { 117 r.fieldIndex = index; 118 // when field is undefined, use index instead 119 if (typeof r.field === 'undefined') { 120 r.field = index; 121 } 122 } 123 124 for (k = 0; k < rowspan; k++) { 125 flag[i + k][index] = true; 126 } 127 for (k = 0; k < colspan; k++) { 128 flag[i][index + k] = true; 129 } 130 } 131 } 132 }; 133 134 var getScrollBarWidth = function () { 135 if (cachedWidth === null) { 136 var inner = $('<p/>').addClass('fixed-table-scroll-inner'),
137 outer = $('<div/>').addClass('fixed-table-scroll-outer'), 138 w1, w2; 139 140 outer.append(inner); 141 $('body').append(outer); 142 143 w1 = inner[0].offsetWidth; 144 outer.css('overflow', 'scroll'); 145 w2 = inner[0].offsetWidth; 146 147 if (w1 === w2) { 148 w2 = outer[0].clientWidth; 149 } 150 151 outer.remove(); 152 cachedWidth = w1 - w2; 153 } 154 return cachedWidth; 155 }; 156 157 var calculateObjectValue = function (self, name, args, defaultValue) { 158 var func = name; 159 160 if (typeof name === 'string') { 161 // support obj.func1.func2 162 var names = name.split('.'); 163 164 if (names.length > 1) { 165 func = window; 166 $.each(names, function (i, f) { 167 func = func[f]; 168 }); 169 } else { 170 func = window[name]; 171 } 172 } 173 if (typeof func === 'object') { 174 return func; 175 } 176 if (typeof func === 'function') { 177 return func.apply(self, args || []); 178 } 179 if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) { 180 return sprintf.apply(this, [name].concat(args)); 181 } 182 return defaultValue; 183 }; 184 185 var compareObjects = function (objectA, objectB, compareLength) { 186 // Create arrays of property names 187 var getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) { 188 var arr = []; 189 for (var k in obj) { 190 if (obj.hasOwnProperty(k)) { 191 arr.push(k); 192 } 193 } 194 return arr; 195 }; 196 var objectAProperties = getOwnPropertyNames(objectA), 197 objectBProperties = getOwnPropertyNames(objectB), 198 propName = ''; 199 200 if (compareLength) { 201 // If number of properties is different, objects are not equivalent 202 if (objectAProperties.length !== objectBProperties.length) { 203 return false; 204 } 205 } 206 207 for (var i = 0; i < objectAProperties.length; i++) { 208 propName = objectAProperties[i]; 209 210 // If the property is not in the object B properties, continue with the next property 211 if ($.inArray(propName, objectBProperties) > -1) { 212 // If values of same property are not equal, objects are not equivalent 213 if (objectA[propName] !== objectB[propName]) { 214 return false; 215 } 216 } 217 } 218 219 // If we made it this far, objects are considered equivalent 220 return true; 221 }; 222 223 var escapeHTML = function (text) { 224 if (typeof text === 'string') { 225 return text 226 .replace(/&/g, '&') 227 .replace(/</g, '<') 228 .replace(/>/g, '>') 229 .replace(/"/g, '"') 230 .replace(/'/g, ''') 231 .replace(/`/g, '`'); 232 } 233 return text; 234 }; 235 236 var getRealDataAttr = function (dataAttr) { 237 for (var attr in dataAttr) { 238 var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase(); 239 if (auxAttr !== attr) { 240 dataAttr[auxAttr] = dataAttr[attr]; 241 delete dataAttr[attr]; 242 } 243 } 244 245 return dataAttr; 246 }; 247 248 var getItemField = function (item, field, escape) { 249 var value = item; 250 251 if (typeof field !== 'string' || item.hasOwnProperty(field)) { 252 return escape ? escapeHTML(item[field]) : item[field]; 253 } 254 var props = field.split('.'); 255 for (var p in props) { 256 if (props.hasOwnProperty(p)) { 257 value = value && value[props[p]]; 258 } 259 } 260 return escape ? escapeHTML(value) : value; 261 }; 262 263 var isIEBrowser = function () { 264 return !!(navigator.userAgent.indexOf("MSIE ") > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)); 265 }; 266 267 var objectKeys = function () { 268 // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys 269 if (!Object.keys) { 270 Object.keys = (function() { 271 var hasOwnProperty = Object.prototype.hasOwnProperty, 272 hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), 273 dontEnums = [ 274 'toString',
275 'toLocaleString', 276 'valueOf', 277 'hasOwnProperty', 278 'isPrototypeOf', 279 'propertyIsEnumerable', 280 'constructor' 281 ], 282 dontEnumsLength = dontEnums.length; 283 284 return function(obj) { 285 if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { 286 throw new TypeError('Object.keys called on non-object'); 287 } 288 289 var result = [], prop, i; 290 291 for (prop in obj) { 292 if (hasOwnProperty.call(obj, prop)) { 293 result.push(prop); 294 } 295 } 296 297 if (hasDontEnumBug) { 298 for (i = 0; i < dontEnumsLength; i++) { 299 if (hasOwnProperty.call(obj, dontEnums[i])) { 300 result.push(dontEnums[i]); 301 } 302 } 303 } 304 return result; 305 }; 306 }()); 307 } 308 }; 309 310 // BOOTSTRAP TABLE CLASS DEFINITION 311 // ====================== 312 313 var BootstrapTable = function (el, options) { 314 this.options = options; 315 this.$el = $(el); 316 this.$el_ = this.$el.clone(); 317 this.timeoutId_ = 0; 318 this.timeoutFooter_ = 0; 319 320 this.init(); 321 }; 322 323 BootstrapTable.DEFAULTS = { 324 classes: 'table table-hover', 325 sortClass: undefined, 326 locale: undefined, 327 height: undefined, 328 undefinedText: '-', 329 sortName: undefined, 330 sortOrder: 'asc', 331 sortStable: false, 332 rememberOrder: false, 333 striped: false, 334 columns: [[]], 335 data: [], 336 totalField: 'total', 337 dataField: 'rows', 338 method: 'get', 339 url: undefined, 340 ajax: undefined, 341 cache: true, 342 contentType: 'application/json', 343 dataType: 'json', 344 ajaxOptions: {}, 345 queryParams: function (params) { 346 return params; 347 }, 348 queryParamsType: 'limit', // undefined 349 responseHandler: function (res) { 350 return res; 351 }, 352 pagination: false, 353 onlyInfoPagination: false, 354 paginationLoop: true, 355 sidePagination: 'client', // client or server 356 totalRows: 0, // server side need to set 357 pageNumber: 1, 358 pageSize: 10, 359 pageList: [10, 25, 50, 100], 360 paginationHAlign: 'right', //right, left 361 paginationVAlign: 'bottom', //bottom, top, both 362 paginationDetailHAlign: 'left', //right, left 363 paginationPreText: '‹', 364 paginationNextText: '›', 365 search: false, 366 searchOnEnterKey: false, 367 strictSearch: false, 368 searchAlign: 'right', 369 selectItemName: 'btSelectItem', 370 showHeader: true, 371 showFooter: false, 372 showColumns: false, 373 showPaginationSwitch: false, 374 showRefresh: false, 375 showToggle: false, 376 showFullscreen: false, 377 smartDisplay: true, 378 escape: false, 379 minimumCountColumns: 1, 380 idField: undefined, 381 uniqueId: undefined, 382 cardView: false, 383 detailView: false, 384 detailFormatter: function (index, row) { 385 return ''; 386 }, 387 detailFilter: function (index, row) { 388 return true; 389 }, 390 trimOnSearch: true, 391 clickToSelect: false, 392 singleSelect: false, 393 toolbar: undefined, 394 toolbarAlign: 'left', 395 buttonsToolbar: undefined, 396 buttonsAlign: 'right', 397 checkboxHeader: true, 398 sortable: true, 399 silentSort: true, 400 maintainSelected: false, 401 searchTimeOut: 500, 402 searchText: '', 403 iconSize: undefined, 404 buttonsClass: bs.buttonsClass, 405 iconsPrefix: bs.iconsPrefix, // glyphicon or fa (font awesome) 406 icons: bs.icons, 407 408 customSearch: $.noop, 409
410 customSort: $.noop, 411 412 ignoreClickToSelectOn: function (element) { 413 return $.inArray(element.tagName, ['A', 'BUTTON']); 414 }, 415 416 rowStyle: function (row, index) { 417 return {}; 418 }, 419 420 rowAttributes: function (row, index) { 421 return {}; 422 }, 423 424 footerStyle: function (row, index) { 425 return {}; 426 }, 427 428 onAll: function (name, args) { 429 return false; 430 }, 431 onClickCell: function (field, value, row, $element) { 432 return false; 433 }, 434 onDblClickCell: function (field, value, row, $element) { 435 return false; 436 }, 437 onClickRow: function (item, $element) { 438 return false; 439 }, 440 onDblClickRow: function (item, $element) { 441 return false; 442 }, 443 onSort: function (name, order) { 444 return false; 445 }, 446 onCheck: function (row) { 447 return false; 448 }, 449 onUncheck: function (row) { 450 return false; 451 }, 452 onCheckAll: function (rows) { 453 return false; 454 }, 455 onUncheckAll: function (rows) { 456 return false; 457 }, 458 onCheckSome: function (rows) { 459 return false; 460 }, 461 onUncheckSome: function (rows) { 462 return false; 463 }, 464 onLoadSuccess: function (data) { 465 return false; 466 }, 467 onLoadError: function (status) { 468 return false; 469 }, 470 onColumnSwitch: function (field, checked) { 471 return false; 472 }, 473 onPageChange: function (number, size) { 474 return false; 475 }, 476 onSearch: function (text) { 477 return false; 478 }, 479 onToggle: function (cardView) { 480 return false; 481 }, 482 onPreBody: function (data) { 483 return false; 484 }, 485 onPostBody: function () { 486 return false; 487 }, 488 onPostHeader: function () { 489 return false; 490 }, 491 onExpandRow: function (index, row, $detail) { 492 return false; 493 }, 494 onCollapseRow: function (index, row) { 495 return false; 496 }, 497 onRefreshOptions: function (options) { 498 return false; 499 }, 500 onRefresh: function (params) { 501 return false; 502 }, 503 onResetView: function () { 504 return false; 505 }, 506 onScrollBody: function () { 507 return false; 508 } 509 }; 510 511 BootstrapTable.LOCALES = {}; 512 513 BootstrapTable.LOCALES['en-US'] = BootstrapTable.LOCALES.en = { 514 formatLoadingMessage: function () { 515 return 'Loading, please wait...'; 516 }, 517 formatRecordsPerPage: function (pageNumber) { 518 return sprintf('%s rows per page', pageNumber); 519 }, 520 formatShowingRows: function (pageFrom, pageTo, totalRows) { 521 return sprintf('Showing %s to %s of %s rows', pageFrom, pageTo, totalRows); 522 }, 523 formatDetailPagination: function (totalRows) { 524 return sprintf('Showing %s rows', totalRows); 525 }, 526 formatSearch: function () { 527 return 'Search'; 528 }, 529 formatNoMatches: function () { 530 return 'No matching records found'; 531 }, 532 formatPaginationSwitch: function () { 533 return 'Hide/Show pagination'; 534 }, 535 formatRefresh: function () { 536 return 'Refresh'; 537 }, 538 formatToggle: function () { 539 return 'Toggle'; 540 }, 541 formatFullscreen: function () { 542 return 'Fullscreen'; 543 }, 544 formatColumns: function () { 545 return 'Columns'; 546 }, 547 formatAllRows: function () { 548 return 'All'; 549 } 550 }; 551 552 $.extend(BootstrapTable.DEFAULTS, BootstrapTable.LOCALES['en-US']); 553 554 BootstrapTable.COLUMN_DEFAULTS = { 555 radio: false, 556 checkbox: false, 557 checkboxEnabled: true, 558 field: undefined, 559 title: undefined, 560 titleTooltip: undefined, 561 'class': undefined, 562 align: undefined, // left, right, center 563 halign: undefined, // left, right, center 564 falign: undefined, // left, right, center 565 valign: undefined, // top, middle, bottom 566 width: undefined, 567 sortable: false, 568 order: 'asc', // asc, desc 569 visible: true, 570 switchable: true, 571 clickToSelect: true, 572 formatter: undefined, 573 footerFormatter: undefined, 574 events: undefined, 575 sorter: undefined, 576 sortName: undefined, 577 cellStyle: undefined, 578 searchable: true, 579 searchFormatter: true, 580 cardVisible: true, 581 escape: false, 582 showSelectTitle: false 583 }; 584 585 BootstrapTable.EVENTS = { 586 'all.bs.table': 'onAll', 587 'click-cell.bs.table': 'onClickCell', 588 'dbl-click-cell.bs.table': 'onDblClickCell', 589 'click-row.bs.table': 'onClickRow', 590 'dbl-click-row.bs.table': 'onDblClickRow', 591 'sort.bs.table': 'onSort', 592 'check.bs.table': 'onCheck', 593 'uncheck.bs.table': 'onUncheck', 594 'check-all.bs.table': 'onCheckAll', 595 'uncheck-all.bs.table': 'onUncheckAll', 596 'check-some.bs.table': 'onCheckSome', 597 'uncheck-some.bs.table': 'onUncheckSome', 598 'load-success.bs.table': 'onLoadSuccess', 599 'load-error.bs.table': 'onLoadError', 600 'column-switch.bs.table': 'onColumnSwitch', 601 'page-change.bs.table': 'onPageChange', 602 'search.bs.table': 'onSearch', 603 'toggle.bs.table': 'onToggle', 604 'pre-body.bs.table': 'onPreBody', 605 'post-body.bs.table': 'onPostBody', 606 'post-header.bs.table': 'onPostHeader', 607 'expand-row.bs.table': 'onExpandRow', 608 'collapse-row.bs.table': 'onCollapseRow', 609 'refresh-options.bs.table': 'onRefreshOptions', 610 'reset-view.bs.table': 'onResetView', 611 'refresh.bs.table': 'onRefresh', 612 'scroll-body.bs.table': 'onScrollBody' 613 }; 614 615 BootstrapTable.prototype.init = function () { 616 this.initLocale(); 617 this.initContainer(); 618 this.initTable(); 619 this.initHeader(); 620 this.initData(); 621 this.initHiddenRows(); 622 this.initFooter(); 623 this.initToolbar(); 624 this.initPagination(); 625 this.initBody(); 626 this.initSearchText(); 627 this.initServer(); 628 }; 629 630 BootstrapTable.prototype.initLocale = function () { 631 if (this.options.locale) { 632 var parts = this.options.locale.split(/-|_/); 633 parts[0].toLowerCase(); 634 if (parts[1]) { 635 parts[1].toUpperCase(); 636 } 637 if ($.fn.bootstrapTable.locales[this.options.locale]) { 638 // locale as requested 639 $.extend(this.options, $.fn.bootstrapTable.locales[this.options.locale]); 640 } else if ($.fn.bootstrapTable.locales[parts.join('-')]) { 641 // locale with sep set to - (in case original was specified with _) 642 $.extend(this.options, $.fn.bootstrapTable.locales[parts.join('-')]); 643 } else if ($.fn.bootstrapTable.locales[parts[0]]) { 644 // short locale language code (i.e. 'en') 645 $.extend(this.options, $.fn.bootstrapTable.locales[parts[0]]); 646 } 647 } 648 }; 649 650 BootstrapTable.prototype.initContainer = function () { 651 this.$container = $([ 652 '<div class="bootstrap-table">', 653 '<div class="fixed-table-toolbar"></div>', 654 this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? 655 '<div class="fixed-table-pagination" style="clear: both;"></div>' : 656 '', 657 '<div class="fixed-table-container">', 658 '<div class="fixed-table-header"><table></table></div>', 659 '<div class="fixed-table-body">', 660 '<div class="fixed-table-loading">', 661 this.options.formatLoadingMessage(), 662 '</div>', 663 '</div>', 664 '<div class="fixed-table-footer"><table><tr></tr></table></div>', 665 '</div>', 666 this.options.paginationVAlign === 'bottom' || this.options.paginationVAlign === 'both' ? 667 '<div class="fixed-table-pagination"></div>' : 668 '', 669 '</div>' 670 ].join(''));
671 672 this.$container.insertAfter(this.$el); 673 this.$tableContainer = this.$container.find('.fixed-table-container'); 674 this.$tableHeader = this.$container.find('.fixed-table-header'); 675 this.$tableBody = this.$container.find('.fixed-table-body'); 676 this.$tableLoading = this.$container.find('.fixed-table-loading'); 677 this.$tableFooter = this.$container.find('.fixed-table-footer'); 678 // checking if custom table-toolbar exists or not 679 if (this.options.buttonsToolbar) { 680 this.$toolbar = $('body').find(this.options.buttonsToolbar); 681 } else { 682 this.$toolbar = this.$container.find('.fixed-table-toolbar'); 683 } 684 this.$pagination = this.$container.find('.fixed-table-pagination'); 685 686 this.$tableBody.append(this.$el); 687 this.$container.after('<div class="clearfix"></div>'); 688 689 this.$el.addClass(this.options.classes); 690 if (this.options.striped) { 691 this.$el.addClass('table-striped'); 692 } 693 if ($.inArray('table-no-bordered', this.options.classes.split(' ')) !== -1) { 694 this.$tableContainer.addClass('table-no-bordered'); 695 } 696 }; 697 698 BootstrapTable.prototype.initTable = function () { 699 var that = this, 700 columns = [], 701 data = []; 702 703 this.$header = this.$el.find('>thead'); 704 if (!this.$header.length) { 705 this.$header = $('<thead></thead>').appendTo(this.$el); 706 } 707 this.$header.find('tr').each(function () { 708 var column = []; 709 710 $(this).find('th').each(function () { 711 // Fix #2014 - getFieldIndex and elsewhere assume this is string, causes issues if not 712 if (typeof $(this).data('field') !== 'undefined') { 713 $(this).data('field', $(this).data('field') + ''); 714 } 715 column.push($.extend({}, { 716 title: $(this).html(), 717 'class': $(this).attr('class'), 718 titleTooltip: $(this).attr('title'), 719 rowspan: $(this).attr('rowspan') ? +$(this).attr('rowspan') : undefined, 720 colspan: $(this).attr('colspan') ? +$(this).attr('colspan') : undefined 721 }, $(this).data())); 722 }); 723 columns.push(column); 724 }); 725 if (!$.isArray(this.options.columns[0])) { 726 this.options.columns = [this.options.columns]; 727 } 728 this.options.columns = $.extend(true, [], columns, this.options.columns); 729 this.columns = []; 730 this.fieldsColumnsIndex = []; 731 732 setFieldIndex(this.options.columns); 733 $.each(this.options.columns, function (i, columns) { 734 $.each(columns, function (j, column) { 735 column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, column); 736 737 if (typeof column.fieldIndex !== 'undefined') { 738 that.columns[column.fieldIndex] = column; 739 that.fieldsColumnsIndex[column.field] = column.fieldIndex; 740 } 741 742 that.options.columns[i][j] = column; 743 }); 744 }); 745 746 // if options.data is setting, do not process tbody data 747 if (this.options.data.length) { 748 return; 749 } 750 751 var m = []; 752 this.$el.find('>tbody>tr').each(function (y) { 753 var row = {}; 754 755 // save tr's id, class and data-* attributes 756 row._id = $(this).attr('id'); 757 row._class = $(this).attr('class'); 758 row._data = getRealDataAttr($(this).data()); 759 760 $(this).find('>td').each(function (x) { 761 var $this = $(this), 762 cspan = +$this.attr('colspan') || 1, 763 rspan = +$this.attr('rowspan') || 1, 764 tx, 765 ty; 766 767 // skip already occupied cells in current row 768 for (; m[y] && m[y][x]; x++); 769 770 for (tx = x; tx < x + cspan; tx++) { //mark matrix elements occupied by current cell with true 771 for (ty = y; ty < y + rspan; ty++) { 772 if (!m[ty]) { //fill missing rows 773 m[ty] = []; 774 } 775 m[ty][tx] = true; 776 } 777 } 778 779 var field = that.columns[x].field; 780 781 row[field] = $(this).html(); 782 // save td's id, class and data-* attributes 783 row['_' + field + '_id'] = $(this).attr('id'); 784 row['_' + field + '_class'] = $(this).attr('class'); 785 row['_' + field + '_rowspan'] = $(this).attr('rowspan'); 786 row['_' + field + '_colspan'] = $(this).attr('colspan'); 787 row['_' + field + '_title'] = $(this).attr('title'); 788 row['_' + field + '_data'] = getRealDataAttr($(this).data()); 789 }); 790 data.push(row); 791 }); 792 this.options.data = data; 793 if (data.length) this.fromHtml = true; 794 }; 795 796 BootstrapTable.prototype.initHeader = function () { 797 var that = this, 798 visibleColumns = {}, 799 html = []; 800 801 this.header = { 802 fields: [], 803 styles: [], 804 classes: [], 805 formatters: [], 806 events: [], 807 sorters: [], 808 sortNames: [], 809 cellStyles: [], 810 searchables: [] 811 }; 812 813 $.each(this.options.columns, function (i, columns) { 814 html.push('<tr>'); 815 816 if (i === 0 && !that.options.cardView && that.options.detailVie
816w) { 817 html.push(sprintf('<th class="detail" rowspan="%s"><div class="fht-cell"></div></th>', 818 that.options.columns.length)); 819 } 820 821 $.each(columns, function (j, column) { 822 var text = '', 823 halign = '', // header align style 824 align = '', // body align style 825 style = '', 826 class_ = sprintf(' class="%s"', column['class']), 827 order = that.options.sortOrder || column.order, 828 unitWidth = 'px', 829 width = column.width; 830 831 if (column.width !== undefined && (!that.options.cardView)) { 832 if (typeof column.width === 'string') { 833 if (column.width.indexOf('%') !== -1) { 834 unitWidth = '%'; 835 } 836 } 837 } 838 if (column.width && typeof column.width === 'string') { 839 width = column.width.replace('%', '').replace('px', ''); 840 } 841 842 halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); 843 align = sprintf('text-align: %s; ', column.align); 844 style = sprintf('vertical-align: %s; ', column.valign); 845 style += sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? 846 (!column.showSelectTitle ? '36px' : undefined) : 847 (width ? width + unitWidth : undefined)); 848 849 if (typeof column.fieldIndex !== 'undefined') { 850 that.header.fields[column.fieldIndex] = column.field; 851 that.header.styles[column.fieldIndex] = align + style; 852 that.header.classes[column.fieldIndex] = class_; 853 that.header.formatters[column.fieldIndex] = column.formatter; 854 that.header.events[column.fieldIndex] = column.events; 855 that.header.sorters[column.fieldIndex] = column.sorter; 856 that.header.sortNames[column.fieldIndex] = column.sortName; 857 that.header.cellStyles[column.fieldIndex] = column.cellStyle; 858 that.header.searchables[column.fieldIndex] = column.searchable; 859 860 if (!column.visible) { 861 return; 862 } 863 864 if (that.options.cardView && (!column.cardVisible)) { 865 return; 866 } 867 868 visibleColumns[column.field] = column; 869 } 870 871 html.push('<th' + sprintf(' title="%s"', column.titleTooltip), 872 column.checkbox || column.radio ? 873 sprintf(' class="bs-checkbox %s"', column['class'] || '') : 874 class_, 875 sprintf(' style="%s"', halign + style), 876 sprintf(' rowspan="%s"', column.rowspan), 877 sprintf(' colspan="%s"', column.colspan), 878 sprintf(' data-field="%s"', column.field), 879 j === 0 && column.fieldIndex ? ' data-not-first-th' : '', 880 '>'); 881 882 html.push(sprintf('<div class="th-inner %s">', that.options.sortable && column.sortable ? 883 'sortable both' : '')); 884 885 text = that.options.escape ? escapeHTML(column.title) : column.title; 886 887 var title = text; 888 if (column.checkbox) { 889 text = ''; 890 if (!that.options.singleSelect && that.options.checkboxHeader) { 891 text = '<input name="btSelectAll" type="checkbox" />'; 892 } 893 that.header.stateField = column.field; 894 } 895 if (column.radio) { 896 text = ''; 897 that.header.stateField = column.field; 898 that.options.singleSelect = true; 899 } 900 if (!text && column.showSelectTitle) { 901 text += title; 902 } 903 904 html.push(text); 905 html.push('</div>'); 906 html.push('<div class="fht-cell"></div>'); 907 html.push('</div>'); 908 html.push('</th>'); 909 }); 910 html.push('</tr>'); 911 }); 912 913 this.$header.html(html.join(''));
914 this.$header.find('th[data-field]').each(function (i) { 915 $(this).data(visibleColumns[$(this).data('field')]); 916 }); 917 this.$container.off('click', '.th-inner').on('click', '.th-inner', function (event) { 918 var $this = $(this); 919 920 if (that.options.detailView && !$this.parent().hasClass('bs-checkbox')) { 921 if ($this.closest('.bootstrap-table')[0] !== that.$container[0]) { 922 return false; 923 } 924 } 925 926 if (that.options.sortable && $this.parent().data().sortable) { 927 that.onSort(event); 928 } 929 }); 930 931 this.$header.children().children().off('keypress').on('keypress', function (event) { 932 if (that.options.sortable && $(this).data().sortable) { 933 var code = event.keyCode || event.which; 934 if (code == 13) { //Enter keycode 935 that.onSort(event); 936 } 937 } 938 }); 939 940 $(window).off('resize.bootstrap-table'); 941 if (!this.options.showHeader || this.options.cardView) { 942 this.$header.hide(); 943 this.$tableHeader.hide(); 944 this.$tableLoading.css('top', 0); 945 } else { 946 this.$header.show(); 947 this.$tableHeader.show(); 948 this.$tableLoading.css('top', this.$header.outerHeight() + 1); 949 // Assign the correct sortable arrow 950 this.getCaret(); 951 $(window).on('resize.bootstrap-table', $.proxy(this.resetWidth, this)); 952 } 953 954 this.$selectAll = this.$header.find('[name="btSelectAll"]'); 955 this.$selectAll.off('click').on('click', function () { 956 var checked = $(this).prop('checked'); 957 that[checked ? 'checkAll' : 'uncheckAll'](); 958 that.updateSelected(); 959 }); 960 }; 961 962 BootstrapTable.prototype.initFooter = function () { 963 if (!this.options.showFooter || this.options.cardView) { 964 this.$tableFooter.hide(); 965 } else { 966 this.$tableFooter.show(); 967 } 968 }; 969 970 /** 971 * @param data
972 * @param type: append / prepend 973 */ 974 BootstrapTable.prototype.initData = function (data, type) { 975 if (type === 'append') { 976 this.options.data = this.options.data.concat(data); 977 } else if (type === 'prepend') { 978 this.options.data = [].concat(data).concat(this.options.data); 979 } else { 980 this.options.data = data || this.options.data; 981 } 982 983 this.data = this.options.data; 984 985 if (this.options.sidePagination === 'server') { 986 return; 987 } 988 this.initSort(); 989 }; 990 991 BootstrapTable.prototype.initSort = function () { 992 var that = this, 993 name = this.options.sortName, 994 order = this.options.sortOrder === 'desc' ? -1 : 1, 995 index = $.inArray(this.options.sortName, this.header.fields), 996 timeoutId = 0; 997 998 if (this.options.customSort !== $.noop) { 999 this.options.customSort.apply(this, [this.options.sortName, this.options.sortOrder]); 1000 return; 1001 } 1002 1003 if (index !== -1) { 1004 if (this.options.sortStable) { 1005 $.each(this.data, function (i, row) { 1006 row._position = i; 1007 }); 1008 } 1009 1010 this.data.sort(function (a, b) { 1011 if (that.header.sortNames[index]) { 1012 name = that.header.sortNames[index]; 1013 } 1014 var aa = getItemField(a, name, that.options.escape), 1015 bb = getItemField(b, name, that.options.escape), 1016 value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb, a, b]); 1017 1018 if (value !== undefined) { 1019 if (that.options.sortStable && value === 0) { 1020 return a._position - b._position; 1021 } 1022 return order * value; 1023 } 1024 1025 // Fix #161: undefined or null string sort bug. 1026 if (aa === undefined || aa === null) { 1027 aa = ''; 1028 } 1029 if (bb === undefined || bb === null) { 1030 bb = ''; 1031 } 1032 1033 if (that.options.sortStable && aa === bb) { 1034 aa = a._position; 1035 bb = b._position; 1036 return a._position - b._position; 1037 } 1038 1039 // IF both values are numeric, do a numeric comparison 1040 if ($.isNumeric(aa) && $.isNumeric(bb)) { 1041 // Convert numerical values form string to float. 1042 aa = parseFloat(aa); 1043 bb = parseFloat(bb); 1044 if (aa < bb) { 1045 return order * -1; 1046 } 1047 return order; 1048 } 1049 1050 if (aa === bb) { 1051 return 0; 1052 } 1053 1054 // If value is not a string, convert to string 1055 if (typeof aa !== 'string') { 1056 aa = aa.toString(); 1057 } 1058 1059 if (aa.localeCompare(bb) === -1) { 1060 return order * -1; 1061 } 1062 1063 return order; 1064 }); 1065 1066 if (this.options.sortClass !== undefined) { 1067 clearTimeout(timeoutId); 1068 timeoutId = setTimeout(function () { 1069 that.$el.removeClass(that.options.sortClass); 1070 var index = that.$header.find(sprintf('[data-field="%s"]', 1071 that.options.sortName).index() + 1); 1072 that.$el.find(sprintf('tr td:nth-child(%s)', index)) 1073 .addClass(that.options.sortClass); 1074 }, 250); 1075 } 1076 } 1077 }; 1078 1079 BootstrapTable.prototype.onSort = function (event) { 1080 var $this = event.type === "keypress" ? $(event.currentTarget) : $(event.currentTarget).parent(), 1081 $this_ = this.$header.find('th').eq($this.index()); 1082 1083 this.$header.add(this.$header_).find('span.order').remove(); 1084 1085 if (this.options.sortName === $this.data('field')) { 1086 this.options.sortOrder = this.options.sortOrder === 'asc' ? 'desc' : 'asc'; 1087 } else { 1088 this.options.sortName = $this.data('field'); 1089 if (this.options.rememberOrder) { 1090 this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc'; 1091 } else { 1092 this.options.sortOrder = this.columns[this.fieldsColumnsIndex[$this.data('field')]].order; 1093 } 1094 } 1095 this.trigger('sort', this.options.sortName, this.options.sortOrder); 1096 1097 $this.add($this_).data('order', this.options.sortOrder); 1098 1099 // Assign the correct sortable arrow 1100 this.getCaret(); 1101 1102 if (this.options.sidePagination === 'server') { 1103 this.initServer(this.options.silentSort); 1104 return; 1105 } 1106 1107 this.initSort(); 1108 this.initBody(); 1109 }; 1110 1111 BootstrapTable.prototype.initToolbar = function () { 1112 var that = this, 1113 html = [], 1114 timeoutId = 0, 1115 $keepOpen, 1116 $search, 1117 switchableCount = 0; 1118 1119 if (this.$toolbar.find('.bs-bars').children().length) { 1120 $('body').append($(this.options.toolbar)); 1121 } 1122 this.$toolbar.html(''); 1123 1124 if (typeof this.options.toolbar === 'string' || typeof this.options.toolbar === 'object') { 1125 $(sprintf('<div class="bs-bars %s-%s"></div>', bs.pullClass, this.options.toolbarAlign)) 1126 .appendTo(this.$toolbar) 1127 .append($(this.options.toolbar)); 1128 } 1129 1130 // showColumns, showToggle, showRefresh 1131 html = [sprintf('<div class="columns columns-%s btn-group %s-%s">', 1132 this.options.buttonsAlign, bs.pullClass, this.options.buttonsAlign)]; 1133 1134 if (typeof this.options.icons === 'string') { 1135 this.options.icons = calculateObjectValue(null, this.options.icons); 1136 } 1137 1138 if (this.options.showPaginationSwitch) { 1139 html.push(sprintf('<button class="btn' +
1140 sprintf(' btn-%s', this.options.buttonsClass) + 1141 sprintf(' btn-%s', this.options.iconSize) + 1142 '" type="button" name="paginationSwitch" aria-label="pagination Switch" title="%s">', 1143 this.options.formatPaginationSwitch()), 1144 sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.paginationSwitchDown), 1145 '</button>'); 1146 } 1147 1148 if (this.options.showFullscreen) { 1149 this.$toolbar.find('button[name="fullscreen"]') 1150 .off('click').on('click', $.proxy(this.toggleFullscreen, this)); 1151 } 1152 1153 if (this.options.showRefresh) { 1154 html.push(sprintf('<button class="btn' + 1155 sprintf(' btn-%s', this.options.buttonsClass) + 1156 sprintf(' btn-%s', this.options.iconSize) + 1157 '" type="button" name="refresh" aria-label="refresh" title="%s">', 1158 this.options.formatRefresh()), 1159 sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.refresh), 1160 '</button>'); 1161 } 1162 1163 if (this.options.showToggle) { 1164 html.push(sprintf('<button class="btn' + 1165 sprintf(' btn-%s', this.options.buttonsClass) + 1166 sprintf(' btn-%s', this.options.iconSize) + 1167 '" type="button" name="toggle" aria-label="toggle" title="%s">', 1168 this.options.formatToggle()), 1169 sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.toggleOff), 1170 '</button>'); 1171 } 1172 1173 if (this.options.showFullscreen) { 1174 html.push(sprintf('<button class="btn' + 1175 sprintf(' btn-%s', this.options.buttonsClass) + 1176 sprintf(' btn-%s', this.options.iconSize) + 1177 '" type="button" name="fullscreen" aria-label="fullscreen" title="%s">', 1178 this.options.formatFullscreen()), 1179 sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.fullscreen), 1180 '</button>'); 1181 } 1182 1183 if (this.options.showColumns) { 1184 html.push(sprintf('<div class="keep-open btn-group" title="%s">', 1185 this.options.formatColumns()), 1186 '<button type="button" aria-label="columns" class="btn' + 1187 sprintf(' btn-%s', this.options.buttonsClass) + 1188 sprintf(' btn-%s', this.options.iconSize) + 1189 ' dropdown-toggle" data-toggle="dropdown">', 1190 sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.columns), 1191 ' <span class="caret"></span>', 1192 '</button>', 1193 bs.toobarDropdowHtml[0]); 1194 1195 $.each(this.columns, function (i, column) { 1196 if (column.radio || column.checkbox) { 1197 return; 1198 } 1199 1200 if (that.options.cardView && !column.cardVisible) { 1201 return; 1202 } 1203 1204 var checked = column.visible ? ' checked="checked"' : ''; 1205 1206 if (column.switchable) { 1207 html.push(sprintf(bs.toobarDropdowItemHtml, 1208 sprintf('<input type="checkbox" data-field="%s" value="%s"%s> %s', 1209 column.field, i, checked, column.title))); 1210 switchableCount++; 1211 } 1212 }); 1213 html.push(bs.toobarDropdowHtml[1], '</div>'); 1214 } 1215 1216 html.push('</div>'); 1217 1218 // Fix #188: this.showToolbar is for extensions 1219 if (this.showToolbar || html.length > 2) { 1220 this.$toolbar.append(html.join('')); 1221 } 1222 1223 if (this.options.showPaginationSwitch) { 1224 this.$toolbar.find('button[name="paginationSwitch"]') 1225 .off('click').on('click', $.proxy(this.togglePagination, this)); 1226 } 1227 1228 if (this.options.showRefresh) { 1229 this.$toolbar.find('button[name="refresh"]') 1230 .off('click').on('click', $.proxy(this.refresh, this)); 1231 } 1232 1233 if (this.options.showToggle) { 1234 this.$toolbar.find('button[name="toggle"]') 1235 .off('click').on('click', function () { 1236 that.toggleView(); 1237 }); 1238 } 1239 1240 if (this.options.showColumns) { 1241 $keepOpen = this.$toolbar.find('.keep-open'); 1242 1243 if (switchableCount <= this.options.minimumCountColumns) { 1244 $keepOpen.find('input').prop('disabled', true); 1245 } 1246 1247 $keepOpen.find('li').off('click').on('click', function (event) { 1248 event.stopImmediatePropagation(); 1249 }); 1250 $keepOpen.find('input').off('click').on('click', function () { 1251 var $this = $(this); 1252 1253 that.toggleColumn($(this).val(), $this.prop('checked'), false); 1254 that.trigger('column-switch', $(this).data('field'), $this.prop('checked')); 1255 }); 1256 } 1257 1258 if (this.options.search) { 1259 html = []; 1260 html.push( 1261 sprintf('<div class="%s-%s search">', bs.pullClass, this.options.searchAlign), 1262 sprintf('<input class="form-control' + 1263 sprintf(' input-%s', this.options.iconSize) + 1264 '" type="text" placeholder="%s">', 1265 this.options.formatSearch()), 1266 '</div>'); 1267 1268 this.$toolbar.append(html.join(''));
1269 $search = this.$toolbar.find('.search input'); 1270 $search.off('keyup drop blur').on('keyup drop blur', function (event) { 1271 if (that.options.searchOnEnterKey && event.keyCode !== 13) { 1272 return; 1273 } 1274 1275 if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) { 1276 return; 1277 } 1278 1279 clearTimeout(timeoutId); // doesn't matter if it's 0 1280 timeoutId = setTimeout(function () { 1281 that.onSearch(event); 1282 }, that.options.searchTimeOut); 1283 }); 1284 1285 if (isIEBrowser()) { 1286 $search.off('mouseup').on('mouseup', function (event) { 1287 clearTimeout(timeoutId); // doesn't matter if it's 0 1288 timeoutId = setTimeout(function () { 1289 that.onSearch(event); 1290 }, that.options.searchTimeOut); 1291 }); 1292 } 1293 } 1294 }; 1295 1296 BootstrapTable.prototype.onSearch = function (event) { 1297 var text = $.trim($(event.currentTarget).val()); 1298 1299 // trim search input 1300 if (this.options.trimOnSearch && $(event.currentTarget).val() !== text) { 1301 $(event.currentTarget).val(text); 1302 } 1303 1304 if (text === this.searchText) { 1305 return; 1306 } 1307 this.searchText = text; 1308 this.options.searchText = text; 1309 1310 this.options.pageNumber = 1; 1311 this.initSearch(); 1312 if (event.firedByInitSearchText) { 1313 if (this.options.sidePagination === 'client') { 1314 this.updatePagination(); 1315 } 1316 } else { 1317 this.updatePagination(); 1318 } 1319 this.trigger('search', text); 1320 }; 1321 1322 BootstrapTable.prototype.initSearch = function () { 1323 var that = this; 1324 1325 if (this.options.sidePagination !== 'server') { 1326 if (this.options.customSearch !== $.noop) { 1327 window[this.options.customSearch].apply(this, [this.searchText]); 1328 return; 1329 } 1330 1331 var s = this.searchText && (this.options.escape ? 1332 escapeHTML(this.searchText) : this.searchText).toLowerCase(); 1333 var f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns; 1334 1335 // Check filter 1336 this.data = f ? $.grep(this.options.data, function (item, i) { 1337 for (var key in f) { 1338 if ($.isArray(f[key]) && $.inArray(item[key], f[key]) === -1 || 1339 !$.isArray(f[key]) && item[key] !== f[key]) { 1340 return false; 1341 } 1342 } 1343 return true; 1344 }) : this.options.data; 1345 1346 this.data = s ? $.grep(this.data, function (item, i) { 1347 for (var j = 0; j < that.header.fields.length; j++) { 1348 1349 if (!that.header.searchables[j]) { 1350 continue; 1351 } 1352 1353 var key = $.isNumeric(that.header.fields[j]) ? parseInt(that.header.fields[j], 10) : that.header.fields[j]; 1354 var column = that.columns[that.fieldsColumnsIndex[key]]; 1355 var value; 1356 1357 if (typeof key === 'string') { 1358 value = item; 1359 var props = key.split('.'); 1360 for (var prop_index = 0; prop_index < props.length; prop_index++) { 1361 if (value[props[prop_index]] != null) { 1362 value = value[props[prop_index]]; 1363 } 1364 } 1365 1366 // Fix #142: respect searchForamtter boolean 1367 if (column && column.searchFormatter) { 1368 value = calculateObjectValue(column, 1369 that.header.formatters[j], [value, item, i], value); 1370 } 1371 } else { 1372 value = item[key]; 1373 } 1374 1375 if (typeof value === 'string' || typeof value === 'number') { 1376 if (that.options.strictSearch) { 1377 if ((value + '').toLowerCase() === s) { 1378 return true; 1379 } 1380 } else { 1381 if ((value + '').toLowerCase().indexOf(s) !== -1) { 1382 return true; 1383 } 1384 } 1385 } 1386 } 1387 return false; 1388 }) : this.data; 1389 } 1390 }; 1391 1392 BootstrapTable.prototype.initPagination = function () { 1393 if (!this.options.pagination) { 1394 this.$pagination.hide(); 1395 return; 1396 } else { 1397 this.$pagination.show(); 1398 } 1399 1400 var that = this, 1401 html = [], 1402 $allSelected = false, 1403 i, from, to, 1404 $pageList, 1405 $pre, 1406 $next, 1407 $number, 1408 data = this.getData(), 1409 pageList = this.options.pageList; 1410 1411 if (this.options.sidePagination !== 'server') { 1412 this.options.totalRows = data.length; 1413 } 1414 1415 this.totalPages = 0; 1416 if (this.options.totalRows) { 1417 if (this.options.pageSize === this.options.formatAllRows()) { 1418 this.options.pageSize = this.options.totalRows; 1419 $allSelected = true; 1420 } else if (this.options.pageSize === this.options.totalRows) { 1421 // Fix #667 Table with pagination, 1422 // multiple pages and a search that matches to one page throws exception 1423 var pageLst = typeof this.options.pageList === 'string' ? 1424 this.options.pageList.replace('[', '').replace(']', '') 1425 .replace(/ /g, '').toLowerCase().split(',') : this.options.pageList; 1426 if ($.inArray(this.options.formatAllRows().toLowerCase(), pageLst) > -1) { 1427 $allSelected = true; 1428 } 1429 } 1430 1431 this.totalPages = ~~((this.options.totalRows - 1) / this.options.pageSize) + 1; 1432 1433 this.options.totalPages = this.totalPages; 1434 } 1435 if (this.totalPages > 0 && this.options.pageNumber > this.totalPages) { 1436 this.options.pageNumber = this.totalPages; 1437 } 1438 1439 this.pageFrom = (this.options.pageNumber - 1) * this.options.pageSize + 1; 1440 this.pageTo = this.options.pageNumber * this.options.pageSize; 1441 if (this.pageTo > this.options.totalRows) { 1442 this.pageTo = this.options.totalRows; 1443 } 1444 1445 html.push( 1446 sprintf('<div class="%s-%s pagination-detail">', bs.pullClass, this.options.paginationDetailHAlign), 1447 '<span class="pagination-info">', 1448 this.options.onlyInfoPagination ? this.options.formatDetailPagination(this.options.totalRows) : 1449 this.options.formatShowingRows(this.pageFrom, this.pageTo, this.options.totalRows), 1450 '</span>'); 1451 1452 if (!this.options.onlyInfoPagination) { 1453 html.push('<span class="page-list">'); 1454 1455 var pageNumber = [ 1456 sprintf('<span class="btn-group %s">', 1457 this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? 1458 'dropdown' : 'dropup'), 1459 '<button type="button" class="btn' +
1460 sprintf(' btn-%s', this.options.buttonsClass) + 1461 sprintf(' btn-%s', this.options.iconSize) + 1462 ' dropdown-toggle" data-toggle="dropdown">', 1463 '<span class="page-size">', 1464 $allSelected ? this.options.formatAllRows() : this.options.pageSize, 1465 '</span>', 1466 ' <span class="caret"></span>', 1467 '</button>', 1468 bs.pageDropdownHtml[0] 1469 ]; 1470 1471 if (typeof this.options.pageList === 'string') { 1472 var list = this.options.pageList.replace('[', '').replace(']', '') 1473 .replace(/ /g, '').split(','); 1474 1475 pageList = []; 1476 $.each(list, function (i, value) { 1477 pageList.push((value.toUpperCase() === that.options.formatAllRows().toUpperCase() || value.toUpperCase() === "UNLIMITED") ? 1478 that.options.formatAllRows() : +value); 1479 }); 1480 } 1481 1482 $.each(pageList, function (i, page) { 1483 if (!that.options.smartDisplay || i === 0 || pageList[i - 1] < that.options.totalRows) { 1484 var active; 1485 if ($allSelected) { 1486 active = page === that.options.formatAllRows() ? 'active' : ''; 1487 } else { 1488 active = page === that.options.pageSize ? 'active' : ''; 1489 } 1490 pageNumber.push(sprintf(bs.pageDropdownItemHtml, active, page)); 1491 } 1492 }); 1493 pageNumber.push(bs.pageDropdownHtml[1] + '</span>'); 1494 1495 html.push(this.options.formatRecordsPerPage(pageNumber.join(''))); 1496 html.push('</span>'); 1497 1498 html.push('</div>', 1499 sprintf('<div class="%s-%s pagination">', bs.pullClass, this.options.paginationHAlign), 1500 '<ul class="pagination' + sprintf(' pagination-%s', this.options.iconSize) + '">', 1501 sprintf('<li class="page-item page-pre"><a class="page-link" href="#">%s</a></li>', 1502 this.options.paginationPreText)); 1503 1504 if (this.totalPages < 5) { 1505 from = 1; 1506 to = this.totalPages; 1507 } else { 1508 from = this.options.pageNumber - 2; 1509 to = from + 4; 1510 if (from < 1) { 1511 from = 1; 1512 to = 5; 1513 } 1514 if (to > this.totalPages) { 1515 to = this.totalPages; 1516 from = to - 4; 1517 } 1518 } 1519 1520 if (this.totalPages >= 6) { 1521 if (this.options.pageNumber >= 3) { 1522 html.push( 1523 sprintf('<li class="page-item page-first%s">', 1524 1 === this.options.pageNumber ? ' active' : ''), 1525 '<a class="page-link" href="#">', 1, '</a>', 1526 '</li>'); 1527 1528 from++; 1529 } 1530 1531 if (this.options.pageNumber >= 4) { 1532 if (this.options.pageNumber == 4 || this.totalPages == 6 || this.totalPages == 7) { 1533 from--; 1534 } else { 1535 html.push('<li class="page-item page-first-separator disabled">', 1536 '<a class="page-link" href="#">...</a>', 1537 '</li>'); 1538 } 1539 1540 to--; 1541 } 1542 } 1543 1544 if (this.totalPages >= 7) { 1545 if (this.options.pageNumber >= (this.totalPages - 2)) { 1546 from--; 1547 } 1548 } 1549 1550 if (this.totalPages == 6) { 1551 if (this.options.pageNumber >= (this.totalPages - 2)) { 1552 to++; 1553 } 1554 } else if (this.totalPages >= 7) { 1555 if (this.totalPages == 7 || this.options.pageNumber >= (this.totalPages - 3)) { 1556 to++; 1557 } 1558 } 1559 1560 for (i = from; i <= to; i++) { 1561 html.push(sprintf('<li class="page-item%s">', 1562 i === this.options.pageNumber ? ' active' : ''), 1563 '<a class="page-link" href="#">', i, '</a>', 1564 '</li>'); 1565 } 1566 1567 if (this.totalPages >= 8) { 1568 if (this.options.pageNumber <= (this.totalPages - 4)) { 1569 html.push('<li class="page-item page-last-separator disabled">', 1570 '<a class="page-link" href="#">...</a>', 1571 '</li>'); 1572 } 1573 } 1574 1575 if (this.totalPages >= 6) { 1576 if (this.options.pageNumber <= (this.totalPages - 3)) { 1577 html.push(sprintf('<li class="page-item page-last%s">', 1578 this.totalPages === this.options.pageNumber ? ' active' : ''), 1579 '<a class="page-link" href="#">
1579', this.totalPages, '</a>', 1580 '</li>'); 1581 } 1582 } 1583 1584 html.push( 1585 sprintf('<li class="page-item page-next"><a class="page-link" href="#">%s</a></li>', 1586 this.options.paginationNextText), 1587 '</ul>', 1588 '</div>'); 1589 } 1590 this.$pagination.html(html.join('')); 1591 1592 if (!this.options.onlyInfoPagination) { 1593 $pageList = this.$pagination.find('.page-list a'); 1594 $pre = this.$pagination.find('.page-pre'); 1595 $next = this.$pagination.find('.page-next'); 1596 $number = this.$pagination.find('.page-item').not('.page-next, .page-pre'); 1597 1598 if (this.options.smartDisplay) { 1599 if (this.totalPages <= 1) { 1600 this.$pagination.find('div.pagination').hide(); 1601 } 1602 if (pageList.length < 2 || this.options.totalRows <= pageList[0]) { 1603 this.$pagination.find('span.page-list').hide(); 1604 } 1605 1606 // when data is empty, hide the pagination 1607 this.$pagination[this.getData().length ? 'show' : 'hide'](); 1608 } 1609 1610 if (!this.options.paginationLoop) { 1611 if (this.options.pageNumber === 1) { 1612 $pre.addClass('disabled'); 1613 } 1614 if (this.options.pageNumber === this.totalPages) { 1615 $next.addClass('disabled'); 1616 } 1617 } 1618 1619 if ($allSelected) { 1620 this.options.pageSize = this.options.formatAllRows(); 1621 } 1622 // removed the events for last and first, onPageNumber executeds the same logic 1623 $pageList.off('click').on('click', $.proxy(this.onPageListChange, this)); 1624 $pre.off('click').on('click', $.proxy(this.onPagePre, this)); 1625 $next.off('click').on('click', $.proxy(this.onPageNext, this)); 1626 $number.off('click').on('click', $.proxy(this.onPageNumber, this)); 1627 } 1628 }; 1629 1630 BootstrapTable.prototype.updatePagination = function (event) { 1631 // Fix #171: IE disabled button can be clicked bug. 1632 if (event && $(event.currentTarget).hasClass('disabled')) { 1633 return; 1634 } 1635 1636 if (!this.options.maintainSelected) { 1637 this.resetRows(); 1638 } 1639 1640 this.initPagination(); 1641 if (this.options.sidePagination === 'server') { 1642 this.initServer(); 1643 } else { 1644 this.initBody(); 1645 } 1646 1647 this.trigger('page-change', this.options.pageNumber, this.options.pageSize); 1648 }; 1649 1650 BootstrapTable.prototype.onPageListChange = function (event) { 1651 event.preventDefault(); 1652 var $this = $(event.currentTarget); 1653 1654 $this.parent().addClass('active').siblings().removeClass('active'); 1655 this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? 1656 this.options.formatAllRows() : +$this.text(); 1657 this.$toolbar.find('.page-size').text(this.options.pageSize); 1658 1659 this.updatePagination(event); 1660 return false; 1661 }; 1662 1663 BootstrapTable.prototype.onPagePre = function (event) { 1664 event.preventDefault(); 1665 if ((this.options.pageNumber - 1) === 0) { 1666 this.options.pageNumber = this.options.totalPages; 1667 } else { 1668 this.options.pageNumber--; 1669 } 1670 this.updatePagination(event); 1671 return false; 1672 }; 1673 1674 BootstrapTable.prototype.onPageNext = function (event) { 1675 event.preventDefault(); 1676 if ((this.options.pageNumber + 1) > this.options.totalPages) { 1677 this.options.pageNumber = 1; 1678 } else { 1679 this.options.pageNumber++; 1680 } 1681 this.updatePagination(event); 1682 return false; 1683 }; 1684 1685 BootstrapTable.prototype.onPageNumber = function (event) { 1686 event.preventDefault(); 1687 if (this.options.pageNumber === +$(event.currentTarget).text()) { 1688 return; 1689 } 1690 this.options.pageNumber = +$(event.currentTarget).text(); 1691 this.updatePagination(event); 1692 return false; 1693 }; 1694 1695 BootstrapTable.prototype.initRow = function(item, i, data, parentDom) { 1696 var that=this, 1697 key, 1698 html = [], 1699 style = {}, 1700 csses = [], 1701 data_ = '', 1702 attributes = {}, 1703 htmlAttributes = []; 1704 1705 if ($.inArray(item, this.hiddenRows) > -1) { 1706 return; 1707 } 1708 1709 style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style); 1710 1711 if (style && style.css) { 1712 for (key in style.css) { 1713 csses.push(key + ': ' + style.css[key]); 1714 } 1715 } 1716 1717 attributes = calculateObjectValue(this.options, 1718 this.options.rowAttributes, [item, i], attributes); 1719 1720 if (attributes) { 1721 for (key in attributes) { 1722 htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key]))); 1723 } 1724 } 1725 1726 if (item._data && !$.isEmptyObject(item._data)) { 1727 $.each(item._data, function(k, v) { 1728 // ignore data-index 1729 if (k === 'index') { 1730 return; 1731 } 1732 data_ += sprintf(' data-%s="%s"', k, v); 1733 }); 1734 } 1735 1736 html.push('<tr', 1737 sprintf(' %s', htmlAttributes.join(' ')), 1738 sprintf(' id="%s"', $.isArray(item) ? undefined : item._id), 1739 sprintf(' class="%s"', style.classes || ($.isArray(item) ? undefined : item._class)), 1740 sprintf(' data-index="%s"', i), 1741 sprintf(' data-uniqueid="%s"', item[this.options.uniqueId]), 1742 sprintf('%s', data_), 1743 '>' 1744 ); 1745 1746 if (this.options.cardView) { 1747 html.push(sprintf('<td colspan="%s"><div class="card-views">', this.header.fields.length)); 1748 } 1749
1750 if (!this.options.cardView && this.options.detailView) { 1751 html.push('<td>'); 1752 1753 if (calculateObjectValue(null, this.options.detailFilter, [i, item])) { 1754 html.push('<a class="detail-icon" href="#">', 1755 sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.detailOpen), 1756 '</a>'); 1757 } 1758 1759 html.push('</td>'); 1760 } 1761 1762 $.each(this.header.fields, function(j, field) { 1763 var text = '', 1764 value_ = getItemField(item, field, that.options.escape), 1765 value = '', 1766 type = '', 1767 cellStyle = {}, 1768 id_ = '', 1769 class_ = that.header.classes[j], 1770 data_ = '', 1771 rowspan_ = '', 1772 colspan_ = '', 1773 title_ = '', 1774 column = that.columns[j]; 1775 1776 if (that.fromHtml && typeof value_ === 'undefined') { 1777 if((!column.checkbox) && (!column.radio)) { 1778 return; 1779 } 1780 } 1781 1782 if (!column.visible) { 1783 return; 1784 } 1785 1786 if (that.options.cardView && (!column.cardVisible)) { 1787 return; 1788 } 1789 1790 if (column.escape) { 1791 value_ = escapeHTML(value_); 1792 } 1793 1794 style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; ')); 1795 1796 // handle td's id and class 1797 if (item['_' + field + '_id']) { 1798 id_ = sprintf(' id="%s"', item['_' + field + '_id']); 1799 } 1800 if (item['_' + field + '_class']) { 1801 class_ = sprintf(' class="%s"', item['_' + field + '_class']); 1802 } 1803 if (item['_' + field + '_rowspan']) { 1804 rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']); 1805 } 1806 if (item['_' + field + '_colspan']) { 1807 colspan_ = sprintf(' colspan="%s"', item['_' + field + '_colspan']); 1808 } 1809 if (item['_' + field + '_title']) { 1810 title_ = sprintf(' title="%s"', item['_' + field + '_title']); 1811 } 1812 cellStyle = calculateObjectValue(that.header, 1813 that.header.cellStyles[j], [value_, item, i, field], cellStyle); 1814 if (cellStyle.classes) { 1815 class_ = sprintf(' class="%s"', cellStyle.classes); 1816 } 1817 if (cellStyle.css) { 1818 var csses_ = []; 1819 for (var key in cellStyle.css) { 1820 csses_.push(key + ': ' + cellStyle.css[key]); 1821 } 1822 style = sprintf('style="%s"', csses_.concat(that.header.styles[j]).join('; ')); 1823 } 1824 1825 value = calculateObjectValue(column, 1826 that.header.formatters[j], [value_, item, i, field], value_); 1827 1828 if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) { 1829 $.each(item['_' + field + '_data'], function(k, v) { 1830 // ignore data-index 1831 if (k === 'index') { 1832 return; 1833 } 1834 data_ += sprintf(' data-%s="%s"', k, v); 1835 }); 1836 } 1837 1838 if (column.checkbox || column.radio) { 1839 type = column.checkbox ? 'checkbox' : type; 1840 type = column.radio ? 'radio' : type; 1841 1842 text = [sprintf(that.options.cardView ? 1843 '<div class="card-view %s">' : '<td class="bs-checkbox %s">', column['class'] || ''), 1844 '<input' + 1845 sprintf(' data-index="%s"', i) + 1846 sprintf(' name="%s"', that.options.selectItemName) + 1847 sprintf(' type="%s"', type) + 1848 sprintf(' value="%s"', item[that.options.idField]) + 1849 sprintf(' checked="%s"', value === true || 1850 (value_ || value && value.checked) ? 'checked' : undefined) + 1851 sprintf(' disabled="%s"', !column.checkboxEnabled || 1852 (value && value.disabled) ? 'disabled' : undefined) + 1853 ' />', 1854 that.header.formatters[j] && typeof value === 'string' ? value : '', 1855 that.options.cardView ? '</div>' : '</td>' 1856 ].join(''); 1857 1858 item[that.header.stateField] = value === true || (!!value_ || value && value.checked); 1859 } else { 1860 value = typeof value === 'undefined' || value === null ? 1861 that.options.undefinedText : value; 1862 1863 text = that.options.cardView ? ['<div class="card-view">', 1864 that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style, 1865 getPropertyFromOther(that.columns, 'field', 'title', field)) : '', 1866 sprintf('<span class="value">%s</span>', value), 1867 '</div>' 1868 ].join('') : [sprintf('<td%s %s %s %s %s %s %s>', 1869 id_, class_, style, data_, rowspan_, colspan_, title_), 1870 value, 1871 '</td>' 1872 ].join(''); 1873 1874 // Hide empty data on Card view when smartDisplay is set to true. 1875 if (that.options.cardView && that.options.smartDisplay && value === '') { 1876 // Should set a placeholder for event binding correct fieldIndex 1877 text = '<div class="card-view"></div>'; 1878 } 1879 } 1880 1881 html.push(text); 1882 }); 1883 1884 if (this.options.cardView) { 1885 html.push('</div></td>'); 1886 } 1887 html.push('</tr>'); 1888 1889 return html.join(' '); 1890 }; 1891 1892 BootstrapTable.prototype.initBody = function (fixedScroll) { 1893 var that = this, 1894 html = [], 1895 data = this.getData(); 1896 1897 this.trigger('pre-body', data); 1898 1899 this.$body = this.$el.find('>tbody'); 1900 if (!this.$body.length) { 1901 this.$body = $('<tbody></tbody>').appendTo(this.$el); 1902 } 1903 1904 //Fix #389 Bootstrap-table-flatJSON is not working 1905 1906 if (!this.options.pagination || this.options.sidePagination === 'server') { 1907 this.pageFrom = 1; 1908 this.pageTo = data.length; 1909 } 1910 1911 var trFragments = $(document.createDocumentFragment()); 1912 var hasTr; 1913 1914 for (var i = this.pageFrom - 1; i < this.pageTo; i++) { 1915 var item = data[i]; 1916 var tr = this.initRow(item, i, data, trFragments); 1917 hasTr = hasTr || !!tr; 1918 if (tr&&tr!==true) { 1919 trFragments.append(tr); 1920 } 1921 } 1922 1923 // show no records 1924 if (!hasTr) { 1925 trFragments.append('<tr class="no-records-found">' + 1926 sprintf('<td colspan="%s">%s</td>', 1927 this.$header.find('th').length, 1928 this.options.formatNoMatches()) + 1929 '</tr>'); 1930 } 1931 1932 this.$body.html(trFragments); 1933 1934 if (!fixedScroll) { 1935 this.scrollTo(0); 1936 } 1937 1938 // click to select by column 1939 this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) { 1940 var $td = $(this), 1941 $tr = $td.parent(), 1942 item = that.data[$tr.data('index')], 1943 index = $td[0].cellIndex, 1944 fields = that.getVisibleFields(),
1945 field = fields[that.options.detailView && !that.options.cardView ? index - 1 : index], 1946 column = that.columns[that.fieldsColumnsIndex[field]], 1947 value = getItemField(item, field, that.options.escape); 1948 1949 if ($td.find('.detail-icon').length) { 1950 return; 1951 } 1952 1953 that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td); 1954 that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr, field); 1955 1956 // if click to select - then trigger the checkbox/radio click 1957 if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect && that.options.ignoreClickToSelectOn(e.target)) { 1958 var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName)); 1959 if ($selectItem.length) { 1960 $selectItem[0].click(); // #144: .trigger('click') bug 1961 } 1962 } 1963 }); 1964 1965 this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function (e) { 1966 e.preventDefault(); 1967 1968 var $this = $(this), 1969 $tr = $this.parent().parent(), 1970 index = $tr.data('index'), 1971 row = data[index]; // Fix #980 Detail view, when searching, returns wrong row 1972 1973 // remove and update 1974 if ($tr.next().is('tr.detail-view')) { 1975 $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen)); 1976 that.trigger('collapse-row', index, row, $tr.next()); 1977 $tr.next().remove(); 1978 } else { 1979 $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailClose)); 1980 $tr.after(sprintf('<tr class="detail-view"><td colspan="%s"></td></tr>', $tr.find('td').length)); 1981 var $element = $tr.next().find('td'); 1982 var content = calculateObjectValue(that.options, that.options.detailFormatter, [index, row, $element], ''); 1983 if ($element.length === 1) { 1984 $element.append(content); 1985 } 1986 that.trigger('expand-row', index, row, $element); 1987 } 1988 that.resetView(); 1989 return false; 1990 }); 1991 1992 this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName)); 1993 this.$selectItem.off('click').on('click', function (event) { 1994 event.stopImmediatePropagation(); 1995 1996 var $this = $(this), 1997 checked = $this.prop('checked'), 1998 row = that.data[$this.data('index')]; 1999 2000 if ($(this).is(':radio') || that.options.singleSelect) { 2001 $.each(that.options.data, function (i, row) { 2002 row[that.header.stateField] = false; 2003 }); 2004 } 2005 2006 row[that.header.stateField] = checked; 2007 2008 if (that.options.singleSelect) { 2009 that.$selectItem.not(this).each(function () { 2010 that.data[$(this).data('index')][that.header.stateField] = false; 2011 }); 2012 that.$selectItem.filter(':checked').not(this).prop('checked', false); 2013 } 2014 2015 that.updateSelected(); 2016 that.trigger(checked ? 'check' : 'uncheck', row, $this); 2017 }); 2018 2019 $.each(this.header.events, function (i, events) { 2020 if (!events) { 2021 return; 2022 } 2023 // fix bug, if events is defined with namespace 2024 if (typeof events === 'string') { 2025 events = calculateObjectValue(null, events); 2026 } 2027 2028 var field = that.header.fields[i], 2029 fieldIndex = $.inArray(field, that.getVisibleFields()); 2030 2031 if (fieldIndex === -1) { 2032 return; 2033 } 2034 2035 if (that.options.detailView && !that.options.cardView) { 2036 fieldIndex += 1;
2037 } 2038 2039 for (var key in events) { 2040 that.$body.find('>tr:not(.no-records-found)').each(function () { 2041 var $tr = $(this), 2042 $td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex), 2043 index = key.indexOf(' '), 2044 name = key.substring(0, index), 2045 el = key.substring(index + 1), 2046 func = events[key]; 2047 2048 $td.find(el).off(name).on(name, function (e) { 2049 var index = $tr.data('index'), 2050 row = that.data[index], 2051 value = row[field]; 2052 2053 func.apply(this, [e, value, row, index]); 2054 }); 2055 }); 2056 } 2057 }); 2058 2059 this.updateSelected(); 2060 this.resetView(); 2061 2062 this.trigger('post-body', data); 2063 }; 2064 2065 BootstrapTable.prototype.initServer = function (silent, query, url) { 2066 var that = this, 2067 data = {}, 2068 index = $.inArray(this.options.sortName, this.header.fields), 2069 params = { 2070 searchText: this.searchText, 2071 sortName: this.options.sortName, 2072 sortOrder: this.options.sortOrder 2073 }, 2074 request; 2075 2076 if (this.header.sortNames[index]) { 2077 params.sortName = this.header.sortNames[index]; 2078 } 2079 2080 if (this.options.pagination && this.options.sidePagination === 'server') { 2081 params.pageSize = this.options.pageSize === this.options.formatAllRows() ? 2082 this.options.totalRows : this.options.pageSize; 2083 params.pageNumber = this.options.pageNumber; 2084 } 2085 2086 if (!(url || this.options.url) && !this.options.ajax) { 2087 return; 2088 } 2089 2090 if (this.options.queryParamsType === 'limit') { 2091 params = { 2092 search: params.searchText, 2093 sort: params.sortName, 2094 order: params.sortOrder 2095 }; 2096 2097 if (this.options.pagination && this.options.sidePagination === 'server') { 2098 params.offset = this.options.pageSize === this.options.formatAllRows() ? 2099 0 : this.options.pageSize * (this.options.pageNumber - 1); 2100 params.limit = this.options.pageSize === this.options.formatAllRows() ? 2101 this.options.totalRows : this.options.pageSize; 2102 if (params.limit === 0) { 2103 delete params.limit; 2104 } 2105 } 2106 } 2107 2108 if (!($.isEmptyObject(this.filterColumnsPartial))) { 2109 params.filter = JSON.stringify(this.filterColumnsPartial, null); 2110 } 2111 2112 data = calculateObjectValue(this.options, this.options.queryParams, [params], data); 2113 2114 $.extend(data, query || {}); 2115 2116 // false to stop request 2117 if (data === false) { 2118 return; 2119 } 2120 2121 if (!silent) { 2122 this.$tableLoading.show(); 2123 } 2124 request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), { 2125 type: this.options.method, 2126 url: url || this.options.url, 2127 data: this.options.contentType === 'application/json' && this.options.method === 'post' ? 2128 JSON.stringify(data) : data, 2129 cache: this.options.cache, 2130 contentType: this.options.contentType, 2131 dataType: this.options.dataType, 2132 success: function (res) { 2133 res = calculateObjectValue(that.options, that.options.responseHandler, [res], res); 2134 2135 that.load(res); 2136 that.trigger('load-success', res); 2137 if (!silent) that.$tableLoading.hide(); 2138 }, 2139 error: function (res) { 2140 var data = []; 2141 if (that.options.sidePagination === 'server') { 2142 data = {}; 2143 data[that.options.totalField] = 0; 2144 data[that.options.dataField] = []; 2145 } 2146 that.load(data); 2147 that.trigger('load-error', res.status, res); 2148 if (!silent) that.$tableLoading.hide(); 2149 } 2150 }); 2151 2152 if (this.options.ajax) { 2153 calculateObjectValue(this, this.options.ajax, [request], null); 2154 } else { 2155 if (this._xhr && this._xhr.readyState !== 4) { 2156 this._xhr.abort(); 2157 } 2158 this._xhr = $.ajax(request); 2159 } 2160 }; 2161 2162 BootstrapTable.prototype.initSearchText = function () { 2163 if (this.options.search) { 2164 this.searchText = ''; 2165 if (this.options.searchText !== '') { 2166 var $search = this.$toolbar.find('.search input'); 2167 $search.val(this.options.searchText); 2168 this.onSearch({currentTarget: $search, firedByInitSearchText: true}); 2169 } 2170 } 2171 }; 2172 2173 BootstrapTable.prototype.getCaret = function () { 2174 var that = this; 2175 2176 $.each(this.$header.find('th'), function (i, th) { 2177 $(th).find('.sortable').removeClass('desc asc').addClass($(th).data('field') === that.options.sortName ? that.options.sortOrder : 'both'); 2178 }); 2179 }; 2180 2181 BootstrapTable.prototype.updateSelected = function () { 2182 var checkAll = this.$selectItem.filter(':enabled').length && 2183 this.$selectItem.filter(':enabled').length === 2184 this.$selectItem.filter(':enabled').filter(':checked').length; 2185 2186 this.$selectAll.add(this.$selectAll_).prop('checked', checkAll); 2187 2188 this.$selectItem.each(function () { 2189 $(this).closest('tr')[$(this).prop('checked') ? 'addClass' : 'removeClass']('selected'); 2190 }); 2191 }; 2192 2193 BootstrapTable.prototype.updateRows = function () { 2194 var that = this; 2195 2196 this.$selectItem.each(function () { 2197 that.data[$(this).data('index')][that.header.stateField] = $(this).prop('checked'); 2198 }); 2199 }; 2200 2201 BootstrapTable.prototype.resetRows = function () { 2202 var that = this; 2203 2204 $.each(this.data, function (i, row) { 2205 that.$selectAll.prop('checked', false); 2206 that.$selectItem.prop('checked', false); 2207 if (that.header.stateField) { 2208 row[that.header.stateField] = false; 2209 } 2210 }); 2211 this.initHiddenRows(); 2212 }; 2213 2214 BootstrapTable.prototype.trigger = function (name) { 2215 var args = Array.prototype.slice.call(arguments, 1); 2216 2217 name += '.bs.table'; 2218 this.options[BootstrapTable.EVENTS[name]].apply(this.options, args); 2219 this.$el.trigger($.Event(name), args); 2220 2221 this.options.onAll(name, args); 2222 this.$el.trigger($.Event('all.bs.table'), [name, args]); 2223 }; 2224 2225 BootstrapTable.prototype.resetHeader = function () { 2226 // fix #61: the hidden table reset header bug. 2227 // fix bug: get $el.css('width') error sometime (height = 500) 2228 clearTimeout(this.timeoutId_); 2229 this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), this.$el.is(':hidden') ? 100 : 0); 2230 }; 2231 2232 BootstrapTable.prototype.fitHeader = function () { 2233 var that = this, 2234 fixedBody, 2235 scrollWidth, 2236 focused, 2237 focusedTemp; 2238 2239 if (that.$el.is(':hidden')) { 2240 that.timeoutId_ = setTimeout($.proxy(that.fitHeader, that), 100); 2241 return; 2242 } 2243 fixedBody = this.$tableBody.get(0); 2244 2245 scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && 2246 fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? 2247 getScrollBarWidth() : 0; 2248 2249 this.$el.css('margin-top', -this.$header.outerHeight()); 2250 2251 focused = $(':focus'); 2252 if (focused.length > 0) { 2253 var $th = focused.parents('th'); 2254 if ($th.length > 0) { 2255 var dataField = $th.attr('data-field'); 2256 if (dataField !== undefined) { 2257 var $headerTh = this.$header.find("[data-field='" + dataField + "']"); 2258 if ($headerTh.length > 0) { 2259 $headerTh.find(":input").addClass("focus-temp"); 2260 } 2261 } 2262 } 2263 } 2264 2265 this.$header_ = this.$header.clone(true, true); 2266 this.$selectAll_ = this.$header_.find('[name="btSelectAll"]'); 2267 this.$tableHeader.css({ 2268 'margin-right': scrollWidth 2269 }).find('table').css('width', this.$el.outerWidth()) 2270 .html('').attr('class', this.$el.attr('class')) 2271 .append(this.$header_); 2272 2273 focusedTemp = $('.focus-temp:visible:eq(0)'); 2274 if (focusedTemp.length > 0) { 2275 focusedTemp.focus(); 2276 this.$header.find('.focus-temp').removeClass('focus-temp'); 2277 } 2278 2279 // fix bug: $.data() is not working as expected after $.append() 2280 this.$header.find('th[data-field]').each(function (i) { 2281 that.$header_.find(sprintf('th[data-field="%s"]', $(this).data('field'))).data($(this).data()); 2282 }); 2283 2284 var visibleFields = this.getVisibleFields(), 2285 $ths = this.$header_.find('th'); 2286 2287 this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { 2288 var $this = $(this), 2289 index = i; 2290
2291 if (that.options.detailView && !that.options.cardView) { 2292 if (i === 0) { 2293 that.$header_.find('th.detail').find('.fht-cell').width($this.innerWidth()); 2294 } 2295 index = i - 1; 2296 } 2297 2298 if (index === -1) { 2299 return; 2300 } 2301 2302 var $th = that.$header_.find(sprintf('th[data-field="%s"]', visibleFields[index])); 2303 if ($th.length > 1) { 2304 $th = $($ths[$this[0].cellIndex]); 2305 } 2306 2307 var zoomWidth = $th.width() - $th.find('.fht-cell').width(); 2308 $th.find('.fht-cell').width($this.innerWidth() - zoomWidth); 2309 }); 2310 2311 this.horizontalScroll(); 2312 this.trigger('post-header'); 2313 }; 2314 2315 BootstrapTable.prototype.resetFooter = function () { 2316 var that = this, 2317 data = that.getData(), 2318 html = []; 2319 2320 if (!this.options.showFooter || this.options.cardView) { //do nothing 2321 return; 2322 } 2323 2324 if (!this.options.cardView && this.options.detailView) { 2325 html.push('<td><div class="th-inner"> </div><div class="fht-cell"></div></td>'); 2326 } 2327 2328 $.each(this.columns, function (i, column) { 2329 var key, 2330 falign = '', // footer align style 2331 valign = '', 2332 csses = [], 2333 style = {}, 2334 class_ = sprintf(' class="%s"', column['class']); 2335 2336 if (!column.visible) { 2337 return; 2338 } 2339 2340 if (that.options.cardView && (!column.cardVisible)) { 2341 return; 2342 } 2343 2344 falign = sprintf('text-align: %s; ', column.falign ? column.falign : column.align); 2345 valign = sprintf('vertical-align: %s; ', column.valign); 2346 2347 style = calculateObjectValue(null, that.options.footerStyle); 2348 2349 if (style && style.css) { 2350 for (key in style.css) { 2351 csses.push(key + ': ' + style.css[key]); 2352 } 2353 } 2354 2355 html.push('<td', class_, sprintf(' style="%s"', falign + valign + csses.concat().join('; ')), '>'); 2356 html.push('<div class="th-inner">'); 2357 2358 html.push(calculateObjectValue(column, column.footerFormatter, [data], ' ') || ' '); 2359 2360 html.push('</div>'); 2361 html.push('<div class="fht-cell"></div>'); 2362 html.push('</div>'); 2363 html.push('</td>'); 2364 }); 2365 2366 this.$tableFooter.find('tr').html(html.join('')); 2367 this.$tableFooter.show(); 2368 clearTimeout(this.timeoutFooter_); 2369 this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), 2370 this.$el.is(':hidden') ? 100 : 0); 2371 }; 2372 2373 BootstrapTable.prototype.fitFooter = function () { 2374 var that = this, 2375 $footerTd, 2376 elWidth, 2377 scrollWidth; 2378 2379 clearTimeout(this.timeoutFooter_); 2380 if (this.$el.is(':hidden')) { 2381 this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), 100); 2382 return; 2383 } 2384 2385 elWidth = this.$el.css('width'); 2386 scrollWidth = elWidth > this.$tableBody.width() ? getScrollBarWidth() : 0; 2387 2388 this.$tableFooter.css({ 2389 'margin-right': scrollWidth 2390 }).find('table').css('width', elWidth) 2391 .attr('class', this.$el.attr('class')); 2392 2393 $footerTd = this.$tableFooter.find('td'); 2394 2395 this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { 2396 var $this = $(this); 2397 2398 $footerTd.eq(i).find('.fht-cell').width($this.innerWidth()); 2399 }); 2400 2401 this.horizontalScroll(); 2402 }; 2403 2404 BootstrapTable.prototype.horizontalScroll = function () { 2405 var that = this; 2406 // horizontal scroll event 2407 // TODO: it's probably better improving the layout than binding to scroll event 2408 2409 that.trigger('scroll-body'); 2410 this.$tableBody.off('scroll').on('scroll', function () { 2411 if (that.options.showHeader && that.options.height) { 2412 that.$tableHeader.scrollLeft($(this).scrollLeft()); 2413 } 2414 2415 if (that.options.showFooter && !that.options.cardView) { 2416 that.$tableFooter.scrollLeft($(this).scrollLeft()); 2417 } 2418 }); 2419 }; 2420 2421 BootstrapTable.prototype.toggleColumn = function (index, checked, needUpdate) { 2422 if (index === -1) { 2423 return; 2424 } 2425 this.columns[index].visible = checked; 2426 this.initHeader(); 2427 this.initSearch(); 2428 this.initPagination(); 2429 this.initBody(); 2430 2431 if (this.options.showColumns) { 2432 var $items = this.$toolbar.find('.keep-open input').prop('disabled', false); 2433 2434 if (needUpdate) { 2435 $items.filter(sprintf('[value="%s"]', index)).prop('checked', checked); 2436 } 2437 2438 if ($items.filter(':checked').length <= this.options.minimumCountColumns) { 2439 $items.filter(':checked').prop('disabled', true); 2440 } 2441 } 2442 }; 2443 2444 BootstrapTable.prototype.getVisibleFields = function () { 2445 var that = this, 2446 visibleFields = []; 2447 2448 $.each(this.header.fields, function (j, field) { 2449 var column = that.columns[that.fieldsColumnsIndex[field]]; 2450 2451 if (!column.visible) { 2452 return; 2453 } 2454 visibleFields.push(field); 2455 }); 2456 return visibleFields; 2457 }; 2458 2459 // PUBLIC FUNCTION DEFINITION 2460 // ======================= 2461 2462 BootstrapTable.prototype.resetView = function (params) { 2463 var padding = 0; 2464 2465 if (params && params.height) { 2466 this.options.height = params.height; 2467 } 2468 2469 this.$selectAll.prop('checked', this.$selectItem.length > 0 && 2470 this.$selectItem.length === this.$selectItem.filter(':checked').length); 2471 2472 if (this.options.height) { 2473 var toolbarHeight = this.$toolbar.outerHeight(true), 2474 paginationHeight = this.$pagination.outerHeight(true), 2475 height = this.options.height - toolbarHeight - paginationHeight; 2476 2477 this.$tableContainer.css('height', height + 'px'); 2478 } 2479 2480 if (this.options.cardView) { 2481 // remove the element css 2482 this.$el.css('margin-top', '0'); 2483 this.$tableContainer.css('padding-bottom', '0'); 2484 this.$tableFooter.hide(); 2485 return; 2486 } 2487 2488 if (this.options.showHeader && this.options.height) { 2489 this.$tableHeader.show(); 2490 this.resetHeader(); 2491 padding += this.$header.outerHeight(); 2492 } else { 2493 this.$tableHeader.hide(); 2494 this.trigger('post-header'); 2495 } 2496 2497 if (this.options.showFooter) { 2498 this.resetFooter(); 2499 if (this.options.height) { 2500 padding += this.$tableFooter.outerHeight() + 1; 2501 } 2502 } 2503 2504 // Assign the correct sortable arrow 2505 this.getCaret(); 2506 this.$tableContainer.css('padding-bottom', padding + 'px'); 2507 this.trigger('reset-view'); 2508 }; 2509 2510 BootstrapTable.prototype.getData = function (useCurrentPage) { 2511 var data = this.options.data; 2512 if (this.searchText || this.options.sortName || !$.isEmptyObject(this.filterColumns) || !$.isEmptyObject(this.filterColumnsPartial)) { 2513 data = this.data; 2514 } 2515 2516 if (useCurrentPage) { 2517 return data.slice(this.pageFrom - 1, this.pageTo); 2518 } 2519 2520 return data; 2521 }; 2522 2523 BootstrapTable.prototype.load = function (data) { 2524 var fixedScroll = false; 2525
2526 // #431: support pagination 2527 if (this.options.pagination && this.options.sidePagination === 'server') { 2528 this.options.totalRows = data[this.options.totalField]; 2529 fixedScroll = data.fixedScroll; 2530 data = data[this.options.dataField]; 2531 } else if (!$.isArray(data)) { // support fixedScroll 2532 fixedScroll = data.fixedScroll; 2533 data = data.data; 2534 } 2535 2536 this.initData(data); 2537 this.initSearch(); 2538 this.initPagination(); 2539 this.initBody(fixedScroll); 2540 }; 2541 2542 BootstrapTable.prototype.append = function (data) { 2543 this.initData(data, 'append'); 2544 this.initSearch(); 2545 this.initPagination(); 2546 this.initSort(); 2547 this.initBody(true); 2548 }; 2549 2550 BootstrapTable.prototype.prepend = function (data) { 2551 this.initData(data, 'prepend'); 2552 this.initSearch(); 2553 this.initPagination(); 2554 this.initSort(); 2555 this.initBody(true); 2556 }; 2557 2558 BootstrapTable.prototype.remove = function (params) { 2559 var len = this.options.data.length, 2560 i, row; 2561 2562 if (!params.hasOwnProperty('field') || !params.hasOwnProperty('values')) { 2563 return; 2564 } 2565 2566 for (i = len - 1; i >= 0; i--) { 2567 row = this.options.data[i]; 2568 2569 if (!row.hasOwnProperty(params.field)) { 2570 continue; 2571 } 2572 if ($.inArray(row[params.field], params.values) !== -1) { 2573 this.options.data.splice(i, 1); 2574 if (this.options.sidePagination === 'server') { 2575 this.options.totalRows -= 1; 2576 } 2577 } 2578 } 2579 2580 if (len === this.options.data.length) { 2581 return; 2582 } 2583 2584 this.initSearch(); 2585 this.initPagination(); 2586 this.initSort(); 2587 this.initBody(true); 2588 }; 2589 2590 BootstrapTable.prototype.removeAll = function () { 2591 if (this.options.data.length > 0) { 2592 this.options.data.splice(0, this.options.data.length); 2593 this.initSearch(); 2594 this.initPagination(); 2595 this.initBody(true); 2596 } 2597 }; 2598 2599 BootstrapTable.prototype.getRowByUniqueId = function (id) { 2600 var uniqueId = this.options.uniqueId, 2601 len = this.options.data.length, 2602 dataRow = null, 2603 i, row, rowUniqueId; 2604 2605 for (i = len - 1; i >= 0; i--) { 2606 row = this.options.data[i]; 2607 2608 if (row.hasOwnProperty(uniqueId)) { // uniqueId is a column 2609 rowUniqueId = row[uniqueId]; 2610 } else if(row._data.hasOwnProperty(uniqueId)) { // uniqueId is a row data property 2611 rowUniqueId = row._data[uniqueId]; 2612 } else { 2613 continue; 2614 } 2615 2616 if (typeof rowUniqueId === 'string') { 2617 id = id.toString(); 2618 } else if (typeof rowUniqueId === 'number') { 2619 if ((Number(rowUniqueId) === rowUniqueId) && (rowUniqueId % 1 === 0)) { 2620 id = parseInt(id); 2621 } else if ((rowUniqueId === Number(rowUniqueId)) && (rowUniqueId !== 0)) { 2622 id = parseFloat(id); 2623 } 2624 } 2625 2626 if (rowUniqueId === id) { 2627 dataRow = row; 2628 break; 2629 } 2630 } 2631 2632 return dataRow; 2633 }; 2634 2635 BootstrapTable.prototype.removeByUniqueId = function (id) { 2636 var len = this.options.data.length, 2637 row = this.getRowByUniqueId(id); 2638 2639 if (row) { 2640 this.options.data.splice(this.options.data.indexOf(row), 1); 2641 } 2642 2643 if (len === this.options.data.length) { 2644 return; 2645 } 2646 2647 this.initSearch(); 2648 this.initPagination(); 2649 this.initBody(true); 2650 }; 2651 2652 BootstrapTable.prototype.updateByUniqueId = function (params) { 2653 var that = this; 2654 var allParams = $.isArray(params) ? params : [ params ]; 2655 2656 $.each(allParams, function(i, params) { 2657 var rowId; 2658 2659 if (!params.hasOwnProperty('id') || !params.hasOwnProperty('row')) { 2660 return; 2661 } 2662 2663 rowId = $.inArray(that.getRowByUniqueId(params.id), that.options.data); 2664 2665 if (rowId === -1) { 2666 return; 2667 } 2668 $.extend(that.options.data[rowId], params.row); 2669 }); 2670 2671 this.initSearch(); 2672 this.initPagination(); 2673 this.initSort(); 2674 this.initBody(true); 2675 }; 2676 2677 BootstrapTable.prototype.refreshColumnTitle = function (params) { 2678 if (!params.hasOwnProperty('field') || !params.hasOwnProperty('title')) { 2679 return; 2680 } 2681 2682 this.columns[this.fieldsColumnsIndex[params.field]].title = 2683 this.options.escape ? escapeHTML(params.title) : params.title; 2684 2685 if (this.columns[this.fieldsColumnsIndex[params.field]].visible) { 2686 var header = this.options.height !== undefined ? this.$tableHeader : this.$header; 2687 header.find('th[data-field]').each(function (i) { 2688 if ($(this).data('field') === params.field) { 2689 $($(this).find(".th-inner")[0]).text(params.title); 2690 return false; 2691 } 2692 }); 2693 } 2694 }; 2695 2696 BootstrapTable.prototype.insertRow = function (params) { 2697 if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { 2698 return; 2699 } 2700 this.options.data.splice(params.index, 0, params.row); 2701 this.initSearch(); 2702 this.initPagination(); 2703 this.initSort(); 2704 this.initBody(true); 2705 }; 2706 2707 BootstrapTable.prototype.updateRow = function (params) { 2708 var that = this;
2709 var allParams = $.isArray(params) ? params : [ params ]; 2710 2711 $.each(allParams, function(i, params) { 2712 if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { 2713 return; 2714 } 2715 $.extend(that.options.data[params.index], params.row); 2716 }); 2717 2718 this.initSearch(); 2719 this.initPagination(); 2720 this.initSort(); 2721 this.initBody(true); 2722 }; 2723 2724 BootstrapTable.prototype.initHiddenRows = function () { 2725 this.hiddenRows = []; 2726 }; 2727 2728 BootstrapTable.prototype.showRow = function (params) { 2729 this.toggleRow(params, true); 2730 }; 2731 2732 BootstrapTable.prototype.hideRow = function (params) { 2733 this.toggleRow(params, false); 2734 }; 2735 2736 BootstrapTable.prototype.toggleRow = function (params, visible) { 2737 var row, index; 2738 2739 if (params.hasOwnProperty('index')) { 2740 row = this.getData()[params.index]; 2741 } else if (params.hasOwnProperty('uniqueId')) { 2742 row = this.getRowByUniqueId(params.uniqueId); 2743 } 2744 2745 if (!row) { 2746 return; 2747 } 2748 2749 index = $.inArray(row, this.hiddenRows); 2750 2751 if (!visible && index === -1) { 2752 this.hiddenRows.push(row); 2753 } else if (visible && index > -1) { 2754 this.hiddenRows.splice(index, 1); 2755 } 2756 this.initBody(true); 2757 }; 2758 2759 BootstrapTable.prototype.getHiddenRows = function (show) { 2760 var that = this, 2761 data = this.getData(), 2762 rows = []; 2763 2764 $.each(data, function (i, row) { 2765 if ($.inArray(row, that.hiddenRows) > -1) { 2766 rows.push(row); 2767 } 2768 }); 2769 this.hiddenRows = rows; 2770 return rows; 2771 }; 2772 2773 BootstrapTable.prototype.mergeCells = function (options) { 2774 var row = options.index, 2775 col = $.inArray(options.field, this.getVisibleFields()), 2776 rowspan = options.rowspan || 1, 2777 colspan = options.colspan || 1, 2778 i, j, 2779 $tr = this.$body.find('>tr'), 2780 $td; 2781 2782 if (this.options.detailView && !this.options.cardView) { 2783 col += 1; 2784 } 2785 2786 $td = $tr.eq(row).find('>td').eq(col); 2787 2788 if (row < 0 || col < 0 || row >= this.data.length) { 2789 return; 2790 } 2791 2792 for (i = row; i < row + rowspan; i++) { 2793 for (j = col; j < col + colspan; j++) { 2794 $tr.eq(i).find('>td').eq(j).hide(); 2795 } 2796 } 2797 2798 $td.attr('rowspan', rowspan).attr('colspan', colspan).show(); 2799 }; 2800 2801 BootstrapTable.prototype.updateCell = function (params) { 2802 if (!params.hasOwnProperty('index') || 2803 !params.hasOwnProperty('field') || 2804 !params.hasOwnProperty('value')) { 2805 return; 2806 } 2807 this.data[params.index][params.field] = params.value; 2808 2809 if (params.reinit === false) { 2810 return; 2811 } 2812 this.initSort(); 2813 this.initBody(true); 2814 }; 2815 2816 BootstrapTable.prototype.updateCellById = function (params) { 2817 var that = this; 2818 if (!params.hasOwnProperty('id') || 2819 !params.hasOwnProperty('field') || 2820 !params.hasOwnProperty('value')) { 2821 return; 2822 } 2823 var allParams = $.isArray(params) ? params : [ params ]; 2824 2825 $.each(allParams, function(i, params) { 2826 var rowId; 2827 2828 rowId = $.inArray(that.getRowByUniqueId(params.id), that.options.data); 2829 2830 if (rowId === -1) { 2831 return; 2832 } 2833 that.data[rowId][params.field] = params.value; 2834 }); 2835 2836 if (params.reinit === false) { 2837 return; 2838 } 2839 this.initSort(); 2840 this.initBody(true); 2841 }; 2842 2843 BootstrapTable.prototype.getOptions = function () { 2844 //Deep copy 2845 return $.extend(true, {}, this.options); 2846 }; 2847 2848 BootstrapTable.prototype.getSelections = function () { 2849 var that = this; 2850 2851 return $.grep(this.options.data, function (row) { 2852 // fix #2424: from html with checkbox 2853 return row[that.header.stateField] === true; 2854 }); 2855 }; 2856 2857 BootstrapTable.prototype.getAllSelections = function () { 2858 var that = this; 2859 2860 return $.grep(this.options.data, function (row) { 2861 return row[that.header.stateField]; 2862 }); 2863 }; 2864 2865 BootstrapTable.prototype.checkAll = function () { 2866 this.checkAll_(true); 2867 }; 2868 2869 BootstrapTable.prototype.uncheckAll = function () { 2870 this.checkAll_(false); 2871 }; 2872 2873 BootstrapTable.prototype.checkInvert = function () { 2874 var that = this; 2875 var rows = that.$selectItem.filter(':enabled'); 2876 var checked = rows.filter(':checked'); 2877 rows.each(function() { 2878 $(this).prop('checked', !$(this).prop('checked')); 2879 }); 2880 that.updateRows(); 2881 that.updateSelected(); 2882 that.trigger('uncheck-some', checked); 2883 checked = that.getSelections(); 2884 that.trigger('check-some', checked); 2885 }; 2886 2887 BootstrapTable.prototype.checkAll_ = function (checked) { 2888 var rows; 2889 if (!checked) {
2890 rows = this.getSelections(); 2891 } 2892 this.$selectAll.add(this.$selectAll_).prop('checked', checked); 2893 this.$selectItem.filter(':enabled').prop('checked', checked); 2894 this.updateRows(); 2895 if (checked) { 2896 rows = this.getSelections(); 2897 } 2898 this.trigger(checked ? 'check-all' : 'uncheck-all', rows); 2899 }; 2900 2901 BootstrapTable.prototype.check = function (index) { 2902 this.check_(true, index); 2903 }; 2904 2905 BootstrapTable.prototype.uncheck = function (index) { 2906 this.check_(false, index); 2907 }; 2908 2909 BootstrapTable.prototype.check_ = function (checked, index) { 2910 var $el = this.$selectItem.filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); 2911 this.data[index][this.header.stateField] = checked; 2912 this.updateSelected(); 2913 this.trigger(checked ? 'check' : 'uncheck', this.data[index], $el); 2914 }; 2915 2916 BootstrapTable.prototype.checkBy = function (obj) { 2917 this.checkBy_(true, obj); 2918 }; 2919 2920 BootstrapTable.prototype.uncheckBy = function (obj) { 2921 this.checkBy_(false, obj); 2922 }; 2923 2924 BootstrapTable.prototype.checkBy_ = function (checked, obj) { 2925 if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) { 2926 return; 2927 } 2928 2929 var that = this, 2930 rows = []; 2931 $.each(this.options.data, function (index, row) { 2932 if (!row.hasOwnProperty(obj.field)) { 2933 return false; 2934 } 2935 if ($.inArray(row[obj.field], obj.values) !== -1) { 2936 var $el = that.$selectItem.filter(':enabled') 2937 .filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); 2938 row[that.header.stateField] = checked; 2939 rows.push(row); 2940 that.trigger(checked ? 'check' : 'uncheck', row, $el); 2941 } 2942 }); 2943 this.updateSelected(); 2944 this.trigger(checked ? 'check-some' : 'uncheck-some', rows); 2945 }; 2946 2947 BootstrapTable.prototype.destroy = function () { 2948 this.$el.insertBefore(this.$container); 2949 $(this.options.toolbar).insertBefore(this.$el); 2950 this.$container.next().remove(); 2951 this.$container.remove(); 2952 this.$el.html(this.$el_.html()) 2953 .css('margin-top', '0') 2954 .attr('class', this.$el_.attr('class') || ''); // reset the class 2955 }; 2956 2957 BootstrapTable.prototype.showLoading = function () { 2958 this.$tableLoading.show(); 2959 }; 2960 2961 BootstrapTable.prototype.hideLoading = function () { 2962 this.$tableLoading.hide(); 2963 }; 2964 2965 BootstrapTable.prototype.togglePagination = function () { 2966 this.options.pagination = !this.options.pagination; 2967 var button = this.$toolbar.find('button[name="paginationSwitch"] i'); 2968 if (this.options.pagination) { 2969 button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchDown); 2970 } else { 2971 button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchUp); 2972 } 2973 this.updatePagination(); 2974 }; 2975 2976 BootstrapTable.prototype.toggleFullscreen = function () { 2977 this.$el.closest('.bootstrap-table').toggleClass('fullscreen'); 2978 }; 2979 2980 BootstrapTable.prototype.refresh = function (params) { 2981 if (params && params.url) { 2982 this.options.url = params.url; 2983 } 2984 if (params && params.pageNumber) { 2985 this.options.pageNumber = params.pageNumber; 2986 } 2987 if (params && params.pageSize) { 2988 this.options.pageSize = params.pageSize; 2989 } 2990 this.initServer(params && params.silent, 2991 params && params.query, params && params.url); 2992 this.trigger('refresh', params); 2993 }; 2994 2995 BootstrapTable.prototype.resetWidth = function () { 2996 if (this.options.showHeader && this.options.height) { 2997 this.fitHeader(); 2998 } 2999 if (this.options.showFooter && !this.options.cardView) { 3000 this.fitFooter(); 3001 } 3002 }; 3003 3004 BootstrapTable.prototype.showColumn = function (field) { 3005 this.toggleColumn(this.fieldsColumnsIndex[field], true, true); 3006 }; 3007 3008 BootstrapTable.prototype.hideColumn = function (field) { 3009 this.toggleColumn(this.fieldsColumnsIndex[field], false, true); 3010 }; 3011 3012 BootstrapTable.prototype.getHiddenColumns = function () { 3013 return $.grep(this.columns, function (column) { 3014 return !column.visible; 3015 }); 3016 }; 3017 3018 BootstrapTable.prototype.getVisibleColumns = function () { 3019 return $.grep(this.columns, function (column) { 3020 return column.visible; 3021 }); 3022 }; 3023 3024 BootstrapTable.prototype.toggleAllColumns = function (visible) { 3025 var that = this; 3026 $.each(this.columns, function (i, column) { 3027 that.columns[i].visible = visible; 3028 }); 3029 3030 this.initHeader(); 3031 this.initSearch(); 3032 this.initPagination(); 3033 this.initBody(); 3034 if (this.options.showColumns) { 3035 var $items = this.$toolbar.find('.keep-open input').prop('disabled', false); 3036 3037 if ($items.filter(':checked').length <= this.options.minimumCountColumns) { 3038 $items.filter(':checked').prop('disabled', true); 3039 } 3040 } 3041 }; 3042 3043 BootstrapTable.prototype.showAllColumns = function () { 3044 this.toggleAllColumns(true); 3045 }; 3046 3047 BootstrapTable.prototype.hideAllColumns = function () { 3048 this.toggleAllColumns(false); 3049 }; 3050 3051 BootstrapTable.prototype.filterBy = function (columns) { 3052 this.filterColumns = $.isEmptyObject(columns) ? {}
3052 : columns; 3053 this.options.pageNumber = 1; 3054 this.initSearch(); 3055 this.updatePagination(); 3056 }; 3057 3058 BootstrapTable.prototype.scrollTo = function (value) { 3059 if (typeof value === 'string') { 3060 value = value === 'bottom' ? this.$tableBody[0].scrollHeight : 0; 3061 } 3062 if (typeof value === 'number') { 3063 this.$tableBody.scrollTop(value); 3064 } 3065 if (typeof value === 'undefined') { 3066 return this.$tableBody.scrollTop(); 3067 } 3068 }; 3069 3070 BootstrapTable.prototype.getScrollPosition = function () { 3071 return this.scrollTo(); 3072 }; 3073 3074 BootstrapTable.prototype.selectPage = function (page) { 3075 if (page > 0 && page <= this.options.totalPages) { 3076 this.options.pageNumber = page; 3077 this.updatePagination(); 3078 } 3079 }; 3080 3081 BootstrapTable.prototype.prevPage = function () { 3082 if (this.options.pageNumber > 1) { 3083 this.options.pageNumber--; 3084 this.updatePagination(); 3085 } 3086 }; 3087 3088 BootstrapTable.prototype.nextPage = function () { 3089 if (this.options.pageNumber < this.options.totalPages) { 3090 this.options.pageNumber++; 3091 this.updatePagination(); 3092 } 3093 }; 3094 3095 BootstrapTable.prototype.toggleView = function () { 3096 this.options.cardView = !this.options.cardView; 3097 this.initHeader(); 3098 // Fixed remove toolbar when click cardView button. 3099 //that.initToolbar(); 3100 var $icon = this.$toolbar.find('button[name="toggle"] i'); 3101 if (this.options.cardView) { 3102 $icon.removeClass(this.options.icons.toggleOff); 3103 $icon.addClass(this.options.icons.toggleOn); 3104 } else { 3105 $icon.removeClass(this.options.icons.toggleOn); 3106 $icon.addClass(this.options.icons.toggleOff); 3107 } 3108 this.initBody(); 3109 this.trigger('toggle', this.options.cardView); 3110 }; 3111 3112 BootstrapTable.prototype.refreshOptions = function (options) { 3113 //If the objects are equivalent then avoid the call of destroy / init methods 3114 if (compareObjects(this.options, options, true)) { 3115 return; 3116 } 3117 this.options = $.extend(this.options, options); 3118 this.trigger('refresh-options', this.options); 3119 this.destroy(); 3120 this.init(); 3121 }; 3122 3123 BootstrapTable.prototype.resetSearch = function (text) { 3124 var $search = this.$toolbar.find('.search input'); 3125 $search.val(text || ''); 3126 this.onSearch({currentTarget: $search}); 3127 }; 3128 3129 BootstrapTable.prototype.expandRow_ = function (expand, index) { 3130 var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', index)); 3131 if ($tr.next().is('tr.detail-view') === (expand ? false : true)) { 3132 $tr.find('> td > .detail-icon').click(); 3133 } 3134 }; 3135 3136 BootstrapTable.prototype.expandRow = function (index) { 3137 this.expandRow_(true, index); 3138 }; 3139 3140 BootstrapTable.prototype.collapseRow = function (index) { 3141 this.expandRow_(false, index); 3142 }; 3143 3144 BootstrapTable.prototype.expandAllRows = function (isSubTable) { 3145 if (isSubTable) { 3146 var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', 0)), 3147 that = this, 3148 detailIcon = null, 3149 executeInterval = false, 3150 idInterval = -1; 3151 3152 if (!$tr.next().is('tr.detail-view')) { 3153 $tr.find('> td > .detail-icon').click(); 3154 executeInterval = true; 3155 } else if (!$tr.next().next().is('tr.detail-view')) { 3156 $tr.next().find(".detail-icon").click(); 3157 executeInterval = true; 3158 } 3159 3160 if (executeInterval) { 3161 try { 3162 idInterval = setInterval(function () { 3163 detailIcon = that.$body.find("tr.detail-view").last().find(".detail-icon"); 3164 if (detailIcon.length > 0) { 3165 detailIcon.click(); 3166 } else { 3167 clearInterval(idInterval); 3168 } 3169 }, 1); 3170 } catch (ex) { 3171 clearInterval(idInterval); 3172 } 3173 } 3174 } else { 3175 var trs = this.$body.children();
3176 for (var i = 0; i < trs.length; i++) { 3177 this.expandRow_(true, $(trs[i]).data("index")); 3178 } 3179 } 3180 }; 3181 3182 BootstrapTable.prototype.collapseAllRows = function (isSubTable) { 3183 if (isSubTable) { 3184 this.expandRow_(false, 0); 3185 } else { 3186 var trs = this.$body.children(); 3187 for (var i = 0; i < trs.length; i++) { 3188 this.expandRow_(false, $(trs[i]).data("index")); 3189 } 3190 } 3191 }; 3192 3193 BootstrapTable.prototype.updateFormatText = function (name, text) { 3194 if (this.options[sprintf('format%s', name)]) { 3195 if (typeof text === 'string') { 3196 this.options[sprintf('format%s', name)] = function () { 3197 return text; 3198 }; 3199 } else if (typeof text === 'function') { 3200 this.options[sprintf('format%s', name)] = text; 3201 } 3202 } 3203 this.initToolbar(); 3204 this.initPagination(); 3205 this.initBody(); 3206 }; 3207 3208 // BOOTSTRAP TABLE PLUGIN DEFINITION 3209 // ======================= 3210 3211 var allowedMethods = [ 3212 'getOptions', 3213 'getSelections', 'getAllSelections', 'getData', 3214 'load', 'append', 'prepend', 'remove', 'removeAll', 3215 'insertRow', 'updateRow', 'updateCell', 'updateByUniqueId', 'removeByUniqueId', 3216 'getRowByUniqueId', 'showRow', 'hideRow', 'getHiddenRows', 3217 'mergeCells', 'refreshColumnTitle', 3218 'checkAll', 'uncheckAll', 'checkInvert', 3219 'check', 'uncheck', 3220 'checkBy', 'uncheckBy', 3221 'refresh', 3222 'resetView', 3223 'resetWidth', 3224 'destroy', 3225 'showLoading', 'hideLoading', 3226 'showColumn', 'hideColumn', 'getHiddenColumns', 'getVisibleColumns', 3227 'showAllColumns', 'hideAllColumns', 3228 'filterBy', 3229 'scrollTo', 3230 'getScrollPosition', 3231 'selectPage', 'prevPage', 'nextPage', 3232 'togglePagination', 3233 'toggleView', 3234 'refreshOptions', 3235 'resetSearch', 3236 'expandRow', 'collapseRow', 'expandAllRows', 'collapseAllRows', 3237 'updateFormatText', 'updateCellById' 3238 ]; 3239 3240 $.fn.bootstrapTable = function (option) { 3241 var value, 3242 args = Array.prototype.slice.call(arguments, 1); 3243 3244 this.each(function () { 3245 var $this = $(this), 3246 data = $this.data('bootstrap.table'), 3247 options = $.extend({}, BootstrapTable.DEFAULTS, $this.data(), 3248 typeof option === 'object' && option); 3249 3250 if (typeof option === 'string') { 3251 if ($.inArray(option, allowedMethods) < 0) { 3252 throw new Error("Unknown method: " + option); 3253 } 3254 3255 if (!data) { 3256 return; 3257 } 3258 3259 value = data[option].apply(data, args); 3260 3261 if (option === 'destroy') { 3262 $this.removeData('bootstrap.table'); 3263 } 3264 } 3265 3266 if (!data) { 3267 $this.data('bootstrap.table', (data = new BootstrapTable(this, options))); 3268 } 3269 }); 3270 3271 return typeof value === 'undefined' ? this : value; 3272 }; 3273 3274 $.fn.bootstrapTable.Constructor = BootstrapTable; 3275 $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS; 3276 $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS; 3277 $.fn.bootstrapTable.locales = BootstrapTable.LOCALES; 3278 $.fn.bootstrapTable.methods = allowedMethods; 3279 $.fn.bootstrapTable.utils = { 3280 bootstrapVersion: bootstrapVersion, 3281 sprintf: sprintf, 3282 compareObjects: compareObjects, 3283 calculateObjectValue: calculateObjectValue, 3284 getItemField: getItemField, 3285 objectKeys: objectKeys, 3286 isIEBrowser: isIEBrowser 3287 }; 3288 3289 // BOOTSTRAP TABLE INIT 3290 // ======================= 3291 3292 $(function () { 3293 $('[data-toggle="table"]').bootstrapTable(); 3294 }); 3295})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.