ソースを参照

Merge pull request #2 from wenzhixin/master

Sync
murphmar 11 年 前
コミット
42e72eb864

+ 8 - 0
CHANGELOG.md

@@ -1,5 +1,13 @@
 ## ChangeLog
 
+###
+
+- [bug] Fix #672: Column Fixed Width in Percentage bug.
+- [enh] Added state saving for visible columns and the ability to use extension with multiple simultaneous tables.
+- [enh] Added `ajax' option to replace jquery ajax method.
+- [enh] Added `resetWidth` method to reset header and footer width.
+- [enh] Added keyevents extension.
+
 ### 1.7.0
 
 - [enh] Add `showFooter`, `keyEvents`, `searchText` and `uniqueId` options.

+ 22 - 2
docs/_i18n/en/documentation/localizations.md

@@ -57,8 +57,28 @@
     </tr>
     <tr>
         <td>formatAllRows</td>
-        <td>--/td>
+        <td>-</td>
         <td>'All'</td>
     </tr>
 	</tbody>
-</table>
+</table>
+
+---
+
+**PS:**
+
+We can import [all locale files](https://github.com/wenzhixin/bootstrap-table/tree/master/src/locale) what you need:
+
+```html
+<script src="bootstrap-table-en-US.js"></script>
+<script src="bootstrap-table-zh-CN.js"></script>
+...
+```
+
+And then use JavaScript to switch locale:
+
+```js
+$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['en-US']);
+// $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
+// ...
+```

+ 5 - 0
docs/_i18n/en/documentation/methods.md

@@ -169,6 +169,11 @@ The calling method syntax: `$('#table').bootstrapTable('method', parameter);`.
         <td>Reset the bootstrap table view, for example reset the table height.</td>
     </tr>
     <tr>
+        <td>resetWidth</td>
+        <td>none</td>
+        <td>Resizes header and footer to fit current columns width</td>
+    </tr>
+    <tr>
         <td>destroy</td>
         <td>none</td>
         <td>Destroy the bootstrap table.</td>

+ 36 - 12
docs/_i18n/en/documentation/table-options.md

@@ -102,6 +102,13 @@ The table options is defined in `jQuery.fn.bootstrapTable.defaults`.
         <td>The data to be loaded.</td>
     </tr>
     <tr>
+        <td>ajax</td>
+        <td>data-ajax</td>
+        <td>Function</td>
+        <td>undefined</td>
+        <td>A method to replace ajax call. Should implement the same API as jQuery ajax method</td>
+    </tr>
+    <tr>
         <td>method</td>
         <td>data-method</td>
         <td>String</td>
@@ -186,7 +193,7 @@ The table options is defined in `jQuery.fn.bootstrapTable.defaults`.
         <td>data-side-pagination</td>
         <td>String</td>
         <td>'client'</td>
-        <td>Defines the side pagination of table, can only be 'client' or 'server'.</td>
+        <td>Defines the side pagination of table, can only be 'client' or 'server'. Using 'server' side requires either setting the 'url' or 'ajax' option</td>
     </tr>
     <tr>
         <td>pageNumber</td>
@@ -366,6 +373,34 @@ The table options is defined in `jQuery.fn.bootstrapTable.defaults`.
         <td>Indicate how to align the pagination detail. 'left', 'right' can be used.</td>
     </tr>
     <tr>
+        <td>paginationFirstText</td>
+        <td>data-pagination-first-text</td>
+        <td>String</td>
+        <td>'&lt;&lt;'</td>
+        <td>Indicate the icon or text to be shown in the pagination detail, the first button of the pagination detail.</td>
+    </tr>
+    <tr>
+        <td>paginationPreText</td>
+        <td>data-pagination-pre-text</td>
+        <td>String</td>
+        <td>'&lt;'</td>
+        <td>Indicate the icon or text to be shown in the pagination detail, the previous button.</td>
+    </tr>
+    <tr>
+        <td>paginationNextText</td>
+        <td>data-pagination-next-text</td>
+        <td>String</td>
+        <td>'&gt;'</td>
+        <td>Indicate the icon or text to be shown in the pagination detail, the next button.</td>
+    </tr>
+    <tr>
+        <td>paginationLastText</td>
+        <td>data-pagination-last-text</td>
+        <td>String</td>
+        <td>'&gt;&gt;'</td>
+        <td>Indicate the icon or text to be shown in the pagination detail, the last button.</td>
+    </tr>
+    <tr>
         <td>clickToSelect</td>
         <td>data-click-to-select</td>
         <td>Boolean</td>
@@ -410,17 +445,6 @@ The table options is defined in `jQuery.fn.bootstrapTable.defaults`.
         <td>true</td>
         <td>False to disable sortable of all columns.</td>
     </tr>
-	<tr>
-        <td>keyEvents</td>
-        <td>data-key-events</td>
-        <td>Boolean</td>
-        <td>false</td>
-        <td>True to enable the key events. The key event list is:
-        S/s: It will be focused the search textbox if it is enabled
-        R/r: It will refresh the table if the showRefresh option is enabled
-        T/t: It will toggle the table view if the showToggle option is enabled
-        P/p: It will fires the pagination switch if the showPaginationSwitch is enabled.</td>
-    </tr>
     <tr>
         <td>rowStyle</td>
         <td>data-row-style</td>

+ 24 - 0
docs/_i18n/en/extensions/keyevents.md

@@ -0,0 +1,24 @@
+# Table Key Events
+
+Use Plugin: [bootstrap-table-keyevents](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/keyevents)
+
+## Usage
+
+```html
+<script src="extensions/cookie/bootstrap-table-keyevents.js"></script>
+```
+
+## Options
+
+### keyEvents
+
+* type: Boolean
+* description:
+True to enable the key events. The key event list is:
+    * s: It will be focused the search textbox if it is enabled.
+    * r: It will refresh the table if the showRefresh option is enabled.
+    * t: It will toggle the table view if the showToggle option is enabled.
+    * p: It will fires the pagination switch if the showPaginationSwitch is enabled.
+    * left: It will go to prev page if the pagination is true.
+    * right: It will go to next page if the pagination is true.
+* default: `false`

+ 28 - 11
docs/_i18n/es/documentation/table-options.md

@@ -356,6 +356,34 @@ Las opciones de la tabla están definidas en `jQuery.fn.bootstrapTable.defaults`
         <td>Indica cómo alinear el detalle de la paginación. Se puede usar: 'left', 'right'.</td>
     </tr>
     <tr>
+        <td>paginationFirstText</td>
+        <td>data-pagination-first-text</td>
+        <td>String</td>
+        <td>'&lt;&lt;'</td>
+        <td>Indica el icono o el texto a mostrar en la paginación, el botón first del detalle de la paginación.</td>
+    </tr>
+    <tr>
+        <td>paginationPreText</td>
+        <td>data-pagination-pre-text</td>
+        <td>String</td>
+        <td>'&lt;'</td>
+        <td>Indica el icono o el texto a mostrar en la paginación, el botón previous del detalle de la paginación.</td>
+    </tr>
+    <tr>
+        <td>paginationNextText</td>
+        <td>data-pagination-next-text</td>
+        <td>String</td>
+        <td>'&gt;'</td>
+        <td>Indica el icono o el texto a mostrar en la paginación, el botón next del detalle de la paginación.</td>
+    </tr>
+    <tr>
+        <td>paginationLastText</td>
+        <td>data-pagination-last-text</td>
+        <td>String</td>
+        <td>'&gt;&gt;'</td>
+        <td>Indica el icono o el texto a mostrar en la paginación, el botón last del detalle de la paginación.</td>
+    </tr>
+    <tr>
         <td>clickToSelect</td>
         <td>data-click-to-select</td>
         <td>Boolean</td>
@@ -397,17 +425,6 @@ Las opciones de la tabla están definidas en `jQuery.fn.bootstrapTable.defaults`
         <td>true</td>
         <td>False para deshabilitar el ordenamiento en todas las columnas.</td>
     </tr>
-	<tr>
-        <td>keyEvents</td>
-        <td>data-key-events</td>
-        <td>Boolean</td>
-        <td>false</td>
-        <td>True para habilitar los eventos del teclado. La lista es:
-        S/s: El textbox de búsqueda sera enfocado si la opción search está habilitada
-        R/r: Se refrescará la tabla si la opción showRefresh está habilitada
-        T/t: Se cambiará de vista si la opción showToggle está habilitada
-        P/p: Se ocultara/mostrará la paginación si la opción showPaginationSwitch está habilitada.</td>
-    </tr>
     <tr>
         <td>rowStyle</td>
         <td>data-row-style</td>

+ 24 - 0
docs/_i18n/es/extensions/keyevents.md

@@ -0,0 +1,24 @@
+# Table Key Events
+
+Use Plugin: [bootstrap-table-keyevents](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/keyevents)
+
+## Usage
+
+```html
+<script src="extensions/cookie/bootstrap-table-keyevents.js"></script>
+```
+
+## Options
+
+### keyEvents
+
+* type: Boolean
+* description:
+True to enable the key events. The key event list is:
+    * s: It will be focused the search textbox if it is enabled.
+    * r: It will refresh the table if the showRefresh option is enabled.
+    * t: It will toggle the table view if the showToggle option is enabled.
+    * p: It will fires the pagination switch if the showPaginationSwitch is enabled.
+    * left: It will go to prev page if the pagination is true.
+    * right: It will go to next page if the pagination is true.
+* default: `false`

+ 24 - 0
docs/_i18n/zh-cn/extensions/keyevents.md

@@ -0,0 +1,24 @@
+# Table Key Events
+
+Use Plugin: [bootstrap-table-keyevents](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/keyevents)
+
+## Usage
+
+```html
+<script src="extensions/cookie/bootstrap-table-keyevents.js"></script>
+```
+
+## Options
+
+### keyEvents
+
+* type: Boolean
+* description:
+True to enable the key events. The key event list is:
+    * s: It will be focused the search textbox if it is enabled.
+    * r: It will refresh the table if the showRefresh option is enabled.
+    * t: It will toggle the table view if the showToggle option is enabled.
+    * p: It will fires the pagination switch if the showPaginationSwitch is enabled.
+    * left: It will go to prev page if the pagination is true.
+    * right: It will go to next page if the pagination is true.
+* default: `false`

+ 5 - 1
docs/extensions.md

@@ -13,4 +13,8 @@ lead: pages.extensions.lead
 
 {% tf extensions/cookie.md %}
 
-{% tf extensions/resizable.md %}
+{% tf extensions/resizable.md %}
+
+{% tf extensions/filter.md %}
+
+{% tf extensions/keyevents.md %}

+ 5 - 5
src/bootstrap-table.css

@@ -13,11 +13,11 @@
 
 .bootstrap-table
 .table,
-.table>tbody>tr>th,
-.table>tfoot>tr>th,
-.table>thead>tr>td,
-.table>tbody>tr>td,
-.table>tfoot>tr>td {
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
     padding: 8px !important;
 }
 

+ 60 - 100
src/bootstrap-table.js

@@ -137,6 +137,7 @@
         data: [],
         method: 'get',
         url: undefined,
+        ajax: undefined,
         cache: true,
         contentType: 'application/json',
         dataType: 'json',
@@ -157,6 +158,10 @@
         paginationHAlign: 'right', //right, left
         paginationVAlign: 'bottom', //bottom, top, both
         paginationDetailHAlign: 'left', //right, left
+        paginationFirstText: '&lt;&lt;',
+        paginationPreText: '&lt;',
+        paginationNextText: '&gt;',
+        paginationLastText: '&gt;&gt;',
         search: false,
         searchAlign: 'right',
         selectItemName: 'btSelectItem',
@@ -181,7 +186,6 @@
         sortable: true,
         maintainSelected: false,
         searchTimeOut: 500,
-        keyEvents: false,
         searchText: '',
         iconSize: undefined,
         iconsPrefix: 'glyphicon', // glyphicon of fa (font awesome)
@@ -348,7 +352,6 @@
         this.initPagination();
         this.initBody();
         this.initServer();
-        this.initKeyEvents();
     };
 
     BootstrapTable.prototype.initContainer = function () {
@@ -473,19 +476,20 @@
                 return;
             }
 
-            if (column.width !== undefined) {
+            if (column.width !== undefined && (!that.options.cardView)) {
                 if (typeof column.width === 'string') {
-                    if (column.width.indexOf('%') > -1) {
-                        unitWidth = '%'
+                    if (column.width.indexOf('%') !== -1) {
+                        unitWidth = '%';
                     }
-                    column.width = column.width.replace('%', '').replace('px', '');
                 }
             }
 
             halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align);
             align = sprintf('text-align: %s; ', column.align);
             style = sprintf('vertical-align: %s; ', column.valign);
-            style += sprintf('width: %s'+ unitWidth +'; ', column.checkbox || column.radio ? 36 : column.width);
+            style += sprintf('width: %s%s; ', column.checkbox || column.radio ? 36 :
+                (column.width ? column.width.replace('%', '').replace('px', '') : undefined),
+                unitWidth);
 
             visibleColumns.push(column);
             that.header.fields.push(column.field);
@@ -583,14 +587,14 @@
             });
 
         if (addedFilterControl) {
-            this.$header.off('keyup', 'input').on('keyup' , 'input', function (event) {
+            this.$header.off('keyup', 'input').on('keyup', 'input', function (event) {
                 clearTimeout(timeoutId);
                 timeoutId = setTimeout(function () {
                     that.onColumnSearch(event);
                 }, that.options.searchTimeOut);
             });
 
-            this.$header.off('change', 'select').on('change' , 'select', function (event) {
+            this.$header.off('change', 'select').on('change', 'select', function (event) {
                 clearTimeout(timeoutId);
                 timeoutId = setTimeout(function () {
                     that.onColumnSearch(event);
@@ -602,7 +606,7 @@
     };
 
     BootstrapTable.prototype.initFooter = function () {
-        this.$footer =  this.$container.find('.fixed-table-footer');
+        this.$footer = this.$container.find('.fixed-table-footer');
         if (!this.options.showFooter || this.options.cardView) {
             this.$footer.hide();
         } else {
@@ -905,7 +909,7 @@
         if (this.options.sidePagination !== 'server') {
             var s = this.searchText && this.searchText.toLowerCase();
             var f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns;
-            var fp = $.isEmptyObject(this.filterColumnsPartial) ? null: this.filterColumnsPartial;
+            var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;
 
             // Check filter
             this.data = f ? $.grep(this.options.data, function (item, i) {
@@ -926,7 +930,7 @@
                         that.header.formatters[$.inArray(key, that.header.fields)],
                         [value, item, i], value);
 
-                    if (! ($.inArray(key, that.header.fields) !== -1 &&
+                    if (!($.inArray(key, that.header.fields) !== -1 &&
                         (typeof value === 'string' || typeof value === 'number') &&
                         (value + '').toLowerCase().indexOf(fval) !== -1)) {
                         return false;
@@ -1037,7 +1041,7 @@
             pageList = [];
             $.each(list, function (i, value) {
                 pageList.push(value.toUpperCase() === that.options.formatAllRows().toUpperCase() ?
-                                that.options.formatAllRows() : +value);
+                    that.options.formatAllRows() : +value);
             });
         }
 
@@ -1046,7 +1050,7 @@
                 var active;
                 if ($allSelected) {
                     active = page === that.options.formatAllRows() ? ' class="active"' : '';
-                } else{
+                } else {
                     active = page === that.options.pageSize ? ' class="active"' : '';
                 }
                 pageNumber.push(sprintf('<li%s><a href="javascript:void(0)">%s</a></li>', active, page));
@@ -1061,8 +1065,8 @@
         html.push('</div>',
             '<div class="pull-' + this.options.paginationHAlign + '">',
             '<ul class="pagination' + (this.options.iconSize === undefined ? '' : ' pagination-' + this.options.iconSize) + '">',
-            '<li class="page-first"><a href="javascript:void(0)">&lt;&lt;</a></li>',
-            '<li class="page-pre"><a href="javascript:void(0)">&lt;</a></li>');
+            '<li class="page-first"><a href="javascript:void(0)">' + this.options.paginationFirstText + '</a></li>',
+            '<li class="page-pre"><a href="javascript:void(0)">' + this.options.paginationPreText + '</a></li>');
 
         if (this.totalPages < 5) {
             from = 1;
@@ -1086,8 +1090,8 @@
         }
 
         html.push(
-            '<li class="page-next"><a href="javascript:void(0)">&gt;</a></li>',
-            '<li class="page-last"><a href="javascript:void(0)">&gt;&gt;</a></li>',
+            '<li class="page-next"><a href="javascript:void(0)">' + this.options.paginationNextText + '</a></li>',
+            '<li class="page-last"><a href="javascript:void(0)">' + this.options.paginationLastText + '</a></li>',
             '</ul>',
             '</div>');
 
@@ -1155,7 +1159,7 @@
 
         $this.parent().addClass('active').siblings().removeClass('active');
         this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ?
-                                    this.options.formatAllRows() : +$this.text();
+            this.options.formatAllRows() : +$this.text();
         this.$toolbar.find('.page-size').text(this.options.pageSize);
 
         this.updatePagination(event);
@@ -1340,10 +1344,10 @@
                                     .text(''));
 
                                 selectControl.append($("<option></option>")
-                                    .attr("value",value)
+                                    .attr("value", value)
                                     .text(value));
                             } else {
-                                for (; iOpt < options.length; iOpt++ ) {
+                                for (; iOpt < options.length; iOpt++) {
                                     if (options[iOpt].value === value) {
                                         exitsOpt = true;
                                         break;
@@ -1352,7 +1356,7 @@
 
                                 if (!exitsOpt) {
                                     selectControl.append($("<option></option>")
-                                        .attr("value",value)
+                                        .attr("value", value)
                                         .text(value));
                                 }
                             }
@@ -1462,14 +1466,16 @@
         var that = this,
             data = {},
             params = {
-                pageSize: this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize,
+                pageSize: this.options.pageSize === this.options.formatAllRows() ?
+                    this.options.totalRows : this.options.pageSize,
                 pageNumber: this.options.pageNumber,
                 searchText: this.searchText,
                 sortName: this.options.sortName,
                 sortOrder: this.options.sortOrder
-            };
+            },
+            request;
 
-        if (!this.options.url) {
+        if (!this.options.url && !this.options.ajax) {
             return;
         }
 
@@ -1503,8 +1509,7 @@
         if (!silent) {
             this.$loading.show();
         }
-
-        $.ajax($.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {
+        request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {
             type: this.options.method,
             url: this.options.url,
             data: this.options.contentType === 'application/json' && this.options.method === 'post' ?
@@ -1526,68 +1531,13 @@
                     that.$loading.hide();
                 }
             }
-        }));
-    };
-
-    BootstrapTable.prototype.initKeyEvents = function () {
-      if (this.options.keyEvents) {
-          var that = this;
-          $(document).off('keypress').on('keypress', function (e) {
-              var $search = that.$toolbar.find('.search input'),
-                  $refresh = that.$toolbar.find('button[name="refresh"]'),
-                  $toggle= that.$toolbar.find('button[name="toggle"]'),
-                  $paginationSwitch = that.$toolbar.find('button[name="paginationSwitch"]');
-              switch (e.keyCode) {
-                  case 115://s
-                  case 83://S
-                      if (!that.options.search) {
-                          return;
-                      }
-
-                      if(document.activeElement === $search.get(0)){
-                          return true;
-                      }
-                      $search.focus();
-                      return false;
-                  case 114: //r
-                  case 82: //R
-                      if (!that.options.showRefresh) {
-                          return;
-                      }
-
-                      if(document.activeElement === $search.get(0)){
-                          return true;
-                      }
-                      $refresh.click();
-                      return false;
-                  case 116: //t
-                  case 84: //T
-                      if (!that.options.showToggle) {
-                          return;
-                      }
-
-                      if(document.activeElement === $search.get(0)){
-                          return true;
-                      }
-
-                      $toggle.click();
-                      return false;
-                  case 112: //p
-                  case 80: //p
-                      if (!that.options.showPaginationSwitch) {
-                          return;
-                      }
-
-                      if(document.activeElement === $search.get(0)){
-                          return true;
-                      }
-
-                      $paginationSwitch.click();
-                      return false;
-
-              }
-          });
-      }
+        });
+
+        if (this.options.ajax) {
+            calculateObjectValue(this, this.options.ajax, [request], null);
+        } else {
+            $.ajax(request);
+        }
     };
 
     BootstrapTable.prototype.getCaretHtml = function () {
@@ -1656,8 +1606,8 @@
             return;
         }
         $fixedHeader = that.$container.find('.fixed-table-header'),
-        $fixedBody = that.$container.find('.fixed-table-body'),
-        scrollWidth = that.$el.width() > $fixedBody.width() ? getScrollBarWidth() : 0;
+            $fixedBody = that.$container.find('.fixed-table-body'),
+            scrollWidth = that.$el.width() > $fixedBody.width() ? getScrollBarWidth() : 0;
 
         that.$header_ = that.$header.clone(true, true);
         that.$selectAll_ = that.$header_.find('[name="btSelectAll"]');
@@ -1694,7 +1644,7 @@
 
         $.each(this.options.columns, function (i, column) {
             var falign = '', // footer align style
-                style  = '',
+                style = '',
                 class_ = sprintf(' class="%s"', column['class']);
 
             if (!column.visible) {
@@ -1718,7 +1668,7 @@
         this.$footer.find('tr').html(html.join(''));
         clearTimeout(this.timeoutFooter_);
         this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this),
-            this.$el.is(':hidden') ? 100: 0);
+            this.$el.is(':hidden') ? 100 : 0);
     };
 
     BootstrapTable.prototype.fitFooter = function () {
@@ -1734,8 +1684,8 @@
             return;
         }
 
-        $fixedBody  = this.$container.find('.fixed-table-body');
-        elWidth     = this.$el.css('width');
+        $fixedBody = this.$container.find('.fixed-table-body');
+        elWidth = this.$el.css('width');
         scrollWidth = elWidth > $fixedBody.width() ? getScrollBarWidth() : 0;
 
         this.$footer.css({
@@ -1745,7 +1695,7 @@
 
         $footerTd = this.$footer.find('td');
 
-        $fixedBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function(i) {
+        $fixedBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function (i) {
             $footerTd.eq(i).outerWidth($(this).outerWidth());
         });
     };
@@ -1775,12 +1725,12 @@
 
     BootstrapTable.prototype.toggleRow = function (index, isIdField, visible) {
         if (index === -1) {
-           return;
+            return;
         }
 
-        $(this.$body[0]).children().filter(sprintf( isIdField ? '[value="%s"]' : '[data-index="%s"]', index))
+        $(this.$body[0]).children().filter(sprintf(isIdField ? '[value="%s"]' : '[data-index="%s"]', index))
             [visible ? 'show' : 'hide']();
-     };
+    };
 
     // PUBLIC FUNCTION DEFINITION
     // =======================
@@ -2078,6 +2028,15 @@
         this.initServer(params && params.silent, params && params.query);
     };
 
+    BootstrapTable.prototype.resetWidth = function () {
+        if (this.options.showHeader && this.options.height) {
+            this.fitHeader();
+        }
+        if (this.options.showFooter) {
+            this.fitFooter();
+        }
+    };
+
     BootstrapTable.prototype.showColumn = function (field) {
         this.toggleColumn(getFieldIndex(this.options.columns, field), true, true);
     };
@@ -2147,6 +2106,7 @@
         'checkBy', 'uncheckBy',
         'refresh',
         'resetView',
+        'resetWidth',
         'destroy',
         'showLoading', 'hideLoading',
         'showColumn', 'hideColumn',
@@ -2168,7 +2128,7 @@
 
             if (typeof option === 'string') {
                 if ($.inArray(option, allowedMethods) < 0) {
-                    throw "Unknown method: " + option;
+                    throw new Error("Unknown method: " + option);
                 }
 
                 if (!data) {

+ 9 - 1
src/extensions/cookie/README.md

@@ -27,4 +27,12 @@ Use Plugin: [bootstrap-table-cookie](https://github.com/wenzhixin/bootstrap-tabl
 
 * type: String
 * description: You must set this property if stateSave is enable to sets an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier.
-* default: ``
+* default: ``
+
+## This plugin saves
+
+* Sort order
+* Page number
+* Page number from the list
+* Visible columns
+* Search text

+ 83 - 78
src/extensions/cookie/bootstrap-table-cookie.js

@@ -1,64 +1,41 @@
 /**
-* @author: Dennis Hernández
-* @webSite: http://djhvscf.github.io/Blog
-* @version: v1.0.0
-*
-* @update zhixin wen <wenzhixin2010@gmail.com>
-*/
+ * @author: Dennis Hernández
+ * @webSite: http://djhvscf.github.io/Blog
+ * @version: v1.1.0
+ *
+ * @update zhixin wen <wenzhixin2010@gmail.com>
+ */
 
 (function ($) {
     'use strict';
 
     var idsStateSaveList = {
-            sortOrder: 'bs.table.sortOrder',
-            sortName: 'bs.table.sortName',
-            pageNumber: 'bs.table.pageNumber',
-            pageList: 'bs.table.pageList',
-            columns: 'bs.table.columns'
+        sortOrder: 'bs.table.sortOrder',
+        sortName: 'bs.table.sortName',
+        pageNumber: 'bs.table.pageNumber',
+        pageList: 'bs.table.pageList',
+        columns: 'bs.table.columns',
+        searchText: 'bs.table.searchText'
     };
 
     var cookieEnabled = function () {
         return (navigator.cookieEnabled) ? true : false;
     };
 
-    var setCookie = function (tableName, cookieName, sValue, vEnd, sPath, sDomain, bSecure) {
-        cookieName = tableName + '.' + cookieName;
-        if (!cookieName || /^(?:expires|max\-age|path|domain|secure)$/i.test(cookieName)) {
-            return false;
+    var setCookie = function (that, cookieName, sValue, sPath, sDomain, bSecure) {
+        if ((!that.options.stateSave) || (!cookieEnabled()) || (that.options.stateSaveIdTable === '')) {
+            return;
         }
-        var sExpires = '',
-            time = '';
 
-        time = vEnd.replace(/[0-9]/, ''); //s,mi,h,d,m,y
-        vEnd = vEnd.replace(/[A-Za-z]/, ''); //number
+        var tableName = that.options.stateSaveIdTable,
+            vEnd = that.options.stateSaveExpire;
 
-        switch (time.toLowerCase()) {
-            case 's':
-                vEnd = +vEnd;
-                break;
-            case 'mi':
-                vEnd = vEnd * 60;
-                break;
-            case 'h':
-                vEnd = vEnd * 60 * 60;
-                break;
-            case 'd':
-                vEnd = vEnd * 24 * 60 * 60;
-                break;
-            case 'm':
-                vEnd = vEnd * 30 * 24 * 60 * 60;
-                break;
-            case 'y':
-                vEnd = vEnd * 365 * 30 * 24 * 60 * 60;
-                break;
-            default:
-                vEnd = undefined;
-                break;
+        cookieName = tableName + '.' + cookieName;
+        if (!cookieName || /^(?:expires|max\-age|path|domain|secure)$/i.test(cookieName)) {
+            return false;
         }
 
-        sExpires = vEnd === undefined ? '' : '; max-age=' + vEnd;
-
-        document.cookie = encodeURIComponent(cookieName) + '=' + encodeURIComponent(sValue) + sExpires + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : '');
+        document.cookie = encodeURIComponent(cookieName) + '=' + encodeURIComponent(sValue) + calculateExpiration(vEnd) + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : '');
         return true;
     };
 
@@ -86,6 +63,37 @@
         return true;
     };
 
+    var calculateExpiration = function(vEnd) {
+        var time = vEnd.replace(/[0-9]/, ''); //s,mi,h,d,m,y
+        vEnd = vEnd.replace(/[A-Za-z]/, ''); //number
+
+        switch (time.toLowerCase()) {
+            case 's':
+                vEnd = +vEnd;
+                break;
+            case 'mi':
+                vEnd = vEnd * 60;
+                break;
+            case 'h':
+                vEnd = vEnd * 60 * 60;
+                break;
+            case 'd':
+                vEnd = vEnd * 24 * 60 * 60;
+                break;
+            case 'm':
+                vEnd = vEnd * 30 * 24 * 60 * 60;
+                break;
+            case 'y':
+                vEnd = vEnd * 365 * 30 * 24 * 60 * 60;
+                break;
+            default:
+                vEnd = undefined;
+                break;
+        }
+
+        return vEnd === undefined ? '' : '; max-age=' + vEnd;
+    }
+
     $.extend($.fn.bootstrapTable.defaults, {
         stateSave: false,
         stateSaveExpire: '2h',
@@ -95,15 +103,17 @@
     $.fn.bootstrapTable.methods.push('deleteCookie');
 
     var BootstrapTable = $.fn.bootstrapTable.Constructor,
-        _init = BootstrapTable.prototype.init,
+        _initTable = BootstrapTable.prototype.initTable,
         _onSort = BootstrapTable.prototype.onSort,
         _onPageNumber = BootstrapTable.prototype.onPageNumber,
         _onPageListChange = BootstrapTable.prototype.onPageListChange,
-        _toggleColumn = BootstrapTable.prototype.toggleColumn;
+        _toggleColumn = BootstrapTable.prototype.toggleColumn,
+        _onSearch = BootstrapTable.prototype.onSearch;
 
-    BootstrapTable.prototype.init = function () {
+    // init save data after initTable function
+    BootstrapTable.prototype.initTable = function () {
+        _initTable.apply(this, Array.prototype.slice.apply(arguments));
         this.initStateSave();
-        _init.apply(this, Array.prototype.slice.apply(arguments));
     };
 
     BootstrapTable.prototype.initStateSave = function () {
@@ -124,56 +134,51 @@
             sortOrderStateName = getCookie(this.options.stateSaveIdTable, idsStateSaveList.sortName),
             pageNumberStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.pageNumber),
             pageListStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.pageList),
-            columnsStateSave = JSON.parse(getCookie(this.options.stateSaveIdTable, idsStateSaveList.columns));
+            columnsStateSave = JSON.parse(getCookie(this.options.stateSaveIdTable, idsStateSaveList.columns)),
+            searchStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.searchText);
 
-        if (sortOrderStateSave !== undefined && sortOrderStateSave !== null) {
+        if (sortOrderStateSave) {
             this.options.sortOrder = sortOrderStateSave;
             this.options.sortName = sortOrderStateName;
         }
 
-        if (pageNumberStateSave !== undefined && pageNumberStateSave !== null) {
+        if (pageNumberStateSave) {
             this.options.pageNumber = +pageNumberStateSave;
         }
 
-        if (pageListStateSave !== undefined && pageListStateSave !== null) {
+        if (pageListStateSave) {
             this.options.pageSize = pageListStateSave ===
                 this.options.formatAllRows() ? pageListStateSave : +pageListStateSave;
         }
 
-        if (columnsStateSave !== undefined && columnsStateSave !== null) {
-            $.each(this.options.columns, function (i) {
-                if (columnsStateSave.indexOf(i) > -1) {
-                    this.visible = true;
-                } else {
-                    this.visible = false;
-                }
+        if (columnsStateSave) {
+            $.each(this.options.columns, function (i, column) {
+                column.visible = columnsStateSave.indexOf(i) !== -1;
             });
         }
+
+        if (searchStateSave) {
+            this.options.searchText = searchStateSave;
+        }
     };
 
     BootstrapTable.prototype.onSort = function () {
         _onSort.apply(this, Array.prototype.slice.apply(arguments));
 
-        if (this.options.stateSave && cookieEnabled() && (this.options.stateSaveIdTable !== '')) {
-            setCookie(this.options.stateSaveIdTable, sStateSaveList.sortOrder, this.options.sortOrder, this.options.stateSaveExpire);
-            setCookie(this.options.stateSaveIdTable, idsStateSaveList.sortName, this.options.sortName, this.options.stateSaveExpire);
-        }
+        setCookie(this, idsStateSaveList.sortOrder, this.options.sortOrder);
+        setCookie(this, idsStateSaveList.sortName, this.options.sortName);
     };
 
     BootstrapTable.prototype.onPageNumber = function () {
         _onPageNumber.apply(this, Array.prototype.slice.apply(arguments));
 
-        if (this.options.stateSave && cookieEnabled() && this.options.stateSaveIdTable !== '') {
-            setCookie(this.options.stateSaveIdTable, idsStateSaveList.pageNumber, this.options.pageNumber, this.options.stateSaveExpire);
-        }
+        setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber);
     };
 
     BootstrapTable.prototype.onPageListChange = function () {
         _onPageListChange.apply(this, Array.prototype.slice.apply(arguments));
 
-        if (this.options.stateSave && cookieEnabled() && this.options.stateSaveIdTable !== '') {
-            setCookie(this.options.stateSaveIdTable, idsStateSaveList.pageList, this.options.pageSize, this.options.stateSaveExpire);
-        }
+        setCookie(this, idsStateSaveList.pageList, this.options.pageSize);
     };
 
     BootstrapTable.prototype.toggleColumn = function () {
@@ -187,20 +192,20 @@
             }
         });
 
-        if (this.options.stateSave && cookieEnabled()) {
-            setCookie(this.options.stateSaveIdTable, idsStateSaveList.columns, JSON.stringify(visibleColumns), this.options.stateSaveExpire);
-        }
+        setCookie(this, idsStateSaveList.columns, JSON.stringify(visibleColumns));
     };
 
-    BootstrapTable.prototype.deleteCookie = function (cookieName) {
-        if (cookieName === '') {
-            return;
-        }
+    BootstrapTable.prototype.onSearch = function () {
+        _onSearch.apply(this, Array.prototype.slice.apply(arguments));
 
-        if (!cookieEnabled()) {
+        setCookie(this, idsStateSaveList.searchText, this.searchText);
+    };
+
+    BootstrapTable.prototype.deleteCookie = function (cookieName) {
+        if ((cookieName === '') || (!cookieEnabled())) {
             return;
         }
 
         deleteCookie(idsStateSaveList[cookieName]);
-    }
+    };
 })(jQuery);

+ 24 - 0
src/extensions/keyevents/README.md

@@ -0,0 +1,24 @@
+# Table Key Events
+
+Use Plugin: [bootstrap-table-keyevents](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/keyevents)
+
+## Usage
+
+```html
+<script src="extensions/cookie/bootstrap-table-keyevents.js"></script>
+```
+
+## Options
+
+### keyEvents
+
+* type: Boolean
+* description:
+True to enable the key events. The key event list is:
+    * s: It will be focused the search textbox if it is enabled.
+    * r: It will refresh the table if the showRefresh option is enabled.
+    * t: It will toggle the table view if the showToggle option is enabled.
+    * p: It will fires the pagination switch if the showPaginationSwitch is enabled.
+    * left: It will go to prev page if the pagination is true.
+    * right: It will go to next page if the pagination is true.
+* default: `false`

+ 83 - 0
src/extensions/keyevents/bootstrap-table-keyevents.js

@@ -0,0 +1,83 @@
+/**
+ * @author: Dennis Hernández
+ * @webSite: http://djhvscf.github.io/Blog
+ * @version: v1.0.0
+ *
+ * @update zhixin wen <wenzhixin2010@gmail.com>
+ */
+
+!function ($) {
+
+    'use strict';
+
+    $.extend($.fn.bootstrapTable.defaults, {
+        keyEvents: false
+    });
+
+    var BootstrapTable = $.fn.bootstrapTable.Constructor,
+        _init = BootstrapTable.prototype.init;
+
+    BootstrapTable.prototype.init = function () {
+        _init.apply(this, Array.prototype.slice.apply(arguments));
+
+        this.initKeyEvents();
+    };
+
+
+    BootstrapTable.prototype.initKeyEvents = function () {
+        if (this.options.keyEvents) {
+            var that = this;
+
+            $(document).off('keydown').on('keydown', function (e) {
+                var $search = that.$toolbar.find('.search input'),
+                    $refresh = that.$toolbar.find('button[name="refresh"]'),
+                    $toggle = that.$toolbar.find('button[name="toggle"]'),
+                    $paginationSwitch = that.$toolbar.find('button[name="paginationSwitch"]');
+
+                if (document.activeElement === $search.get(0)) {
+                    return true;
+                }
+
+                switch (e.keyCode) {
+                    case 83: //s
+                        if (!that.options.search) {
+                            return;
+                        }
+                        $search.focus();
+                        return false;
+                    case 82: //r
+                        if (!that.options.showRefresh) {
+                            return;
+                        }
+                        $refresh.click();
+                        return false;
+                    case 84: //t
+                        if (!that.options.showToggle) {
+                            return;
+                        }
+                        $toggle.click();
+                        return false;
+                    case 80: //p
+                        if (!that.options.showPaginationSwitch) {
+                            return;
+                        }
+                        $paginationSwitch.click();
+                        return false;
+                    case 37: // left
+                        if (!that.options.pagination) {
+                            return;
+                        }
+                        that.prevPage();
+                        return false;
+                    case 39: // right
+                        if (!that.options.pagination) {
+                            return;
+                        }
+                        that.nextPage();
+                        return;
+                }
+            });
+        }
+    };
+
+}(jQuery);