Browse Source

Merge pull request #43 from wenzhixin/master

Update my repo
Dennis Hernández 10 years ago
parent
commit
835a1b9c21

+ 12 - 0
docs/_i18n/en/documentation/events.md

@@ -173,5 +173,17 @@
        <td>none</td>
        <td>Fires after the table header is rendered and availble in the DOM</td>
     </tr>
+    <tr>
+        <td>onExpandRow</td>
+        <td>expand-row.bs.table</td>
+        <td>index, row, $detail</td>
+        <td>Fires when click the detail icon to expand the detail view.</td>
+    </tr>
+    <tr>
+       <td>onCollapseRow</td>
+       <td>collapse-row.bs.table</td>
+       <td>index, row</td>
+       <td>Fires when click the detail icon to collapse the detail view.</td>
+    </tr>
     </tbody>
 </table>

+ 14 - 0
docs/_i18n/en/documentation/table-options.md

@@ -332,6 +332,20 @@ The table options is defined in `jQuery.fn.bootstrapTable.defaults`.
         <td>True to show card view table, for example mobile view.</td>
     </tr>
     <tr>
+        <td>detailView</td>
+        <td>data-detail-view</td>
+        <td>Boolean</td>
+        <td>false</td>
+        <td>True to show detail view table.</td>
+    </tr>
+    <tr>
+        <td>detailFormatter</td>
+        <td>data-detail-formatter</td>
+        <td>Function</td>
+        <td>function(index, row) {<br>return '';<br>}</td>
+        <td>Format your detail view when <code>detailView</code> is set to <code>true</code>.</td>
+    </tr>
+    <tr>
         <td>searchAlign</td>
         <td>data-search-align</td>
         <td>String</td>

+ 3 - 3
docs/_i18n/en/extensions/reordercolumns.md

@@ -1,6 +1,6 @@
-# Table Reorder
+# Table Reorder Columns
 
-Use Plugin: [bootstrap-table-reorder](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder) </br>
+Use Plugin: [bootstrap-table-reorder-columns](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reordercolumns) </br>
 Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must include the css file), </br>
 [jquery-ui](https://code.jquery.com/ui/) v1.11
 
@@ -11,7 +11,7 @@ Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must incl
 <link rel="stylesheet" href=".../dragtable.css">
 <script src=".../jquery-ui.js"></script>
 <script src=".../jquery.dragtable.js"></script>
-<script src="extensions/cookie/bootstrap-table-reorder-columns.js"></script>
+<script src="extensions/reordercolumns/bootstrap-table-reorder-columns.js"></script>
 ```
 
 ## Options

+ 74 - 0
docs/_i18n/en/extensions/reorderrows.md

@@ -0,0 +1,74 @@
+# Table Reorder Rows
+
+Use Plugin: [bootstrap-table-reorder-rows](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorderrows) </br>
+Dependence: [tablednd](https://github.com/isocra/TableDnD) v0.9, </br>
+if you want you can include the bootstrap-table-reorder-rows.css file to use the default dragClass
+
+
+## Usage
+
+```html
+<link rel="stylesheet" href=".../bootstrap-table-reorder-rows.css">
+<script src=".../jquery.tablednd.js"></script>
+<script src="extensions/reorderrows/bootstrap-table-reorder-rows.js"></script>
+```
+
+## Options
+
+### reorderableRows
+
+* type: Boolean
+* description: Set true to allow the reorder feature.
+* default: `false`
+
+### onDragStyle
+
+* type: String
+* description: This is the style that is assigned to the row during drag. There are limitations to the styles that can be associated with a row (such as you can't assign a border—well you can, but it won't be displayed).
+* default: `null`
+
+### onDropStyle
+
+* type: String
+* description: This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations to what you can do. Also this replaces the original style, so again consider using onDragClass which is simply added and then removed on drop.
+* default: `null`
+
+### onDragClass
+
+* type: String
+* description: This class is added for the duration of the drag and then removed when the row is dropped. It is more flexible than using onDragStyle since it can be inherited by the row cells and other content.
+* default: `reorder_rows_onDragClass`
+
+### dragHandle
+
+* type: String
+* description: This is the cursor to use
+* default: `null`
+
+### useRowAttrFunc
+
+* type: Boolean
+* description: This function must be use if your `tr` elements won't have the `id` attribute. If your `tr` elements don't have the `id` attribute this plugin don't fire the onDrop event.
+* default: `false`
+
+### onReorderRowsDrag
+
+* type: Function
+* description: Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the table and the row which the user has started to drag.
+* default: `empty function`
+
+### onReorderRowsDrop
+
+* type: Function
+* description: Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table and the row that was dropped.
+* default: `empty function`
+
+## Events
+
+### onReorderRow(reorder-row.bs.table)
+
+Fired when the row was dropped, receive as parameter the new data order
+
+## The existing problems
+
+* After search if the user reorder the rows the data is not shown properly after that.

+ 53 - 0
docs/_i18n/en/extensions/toolbar.md

@@ -0,0 +1,53 @@
+# Table Toolbar
+
+Use Plugin: [bootstrap-table-toolbar](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar)
+
+## Usage
+
+```html
+<script src="extensions/toolbar/bootstrap-table-toolbar.js"></script>
+```
+
+## Options
+
+### advancedSearch
+
+* type: Boolean
+* description: Set true to allow the advanced search.
+* default: `false`
+
+### idForm
+
+* type: String
+* description: Must be set to know the idform.
+* default: `advancedSearch`
+
+### actionForm
+
+* type: String
+* description: Set the action of the form (pop-up).
+* default: ``
+
+### idTable
+
+* type: String
+* description: Set the id of the table to create the pop-up form.
+* default: ``
+
+## Locales
+
+### formatAdvancedSearch
+
+* description: Title of the advanced search modal
+* default: `Advanced search`
+
+### formatAdvancedCloseButton
+
+* description: Text of the close button
+* default: `Close`
+
+## Events
+
+### onColumnAdvancedSearch(column-advanced-search.bs.table)
+
+* Fired when we are searching into the advanced search form

+ 14 - 0
docs/_i18n/es/documentation/events.md

@@ -160,5 +160,19 @@
        <td>none</td>
        <td>Se ejecuta después de que el encabezado es renderizado y disponible en el DOM.</td>
     </tr>
+    <tr>
+        <td>onExpandRow</td>
+        <td>expand-row.bs.table</td>
+        <td>index, row, $detail</td>
+        <td>Fires when click the detail icon to expand the detail view.</td>
+    </tr>
+    <tr>
+       <td>onCollapseRow</td>
+       <td>collapse-row.bs.table</td>
+       <td>index, row</td>
+       <td>Fires when click the detail icon to collapse the detail view.</td>
+    </tr>
+    </tbody>
+</table>
     </tbody>
 </table>

+ 14 - 0
docs/_i18n/es/documentation/table-options.md

@@ -315,6 +315,20 @@ Las opciones de la tabla están definidas en `jQuery.fn.bootstrapTable.defaults`
         <td>True para mostrar la vista de tarjeta, por ejemplo en móviles.</td>
     </tr>
     <tr>
+        <td>detailView</td>
+        <td>data-detail-view</td>
+        <td>Boolean</td>
+        <td>false</td>
+        <td>True to show detail view table.</td>
+    </tr>
+    <tr>
+        <td>detailFormatter</td>
+        <td>data-detail-formatter</td>
+        <td>Function</td>
+        <td>function(index, row) {<br>return '';<br>}</td>
+        <td>Format your detail view when <code>detailView</code> is set to <code>true</code>.</td>
+    </tr>
+    <tr>
         <td>searchAlign</td>
         <td>data-search-align</td>
         <td>String</td>

+ 3 - 3
docs/_i18n/es/extensions/reordercolumns.md

@@ -1,6 +1,6 @@
-# Table Reorder
+# Table Reorder Columns
 
-Use Plugin: [bootstrap-table-reorder](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder) </br>
+Use Plugin: [bootstrap-table-reorder-columns](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reordercolumns) </br>
 Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must include the css file), </br>
 [jquery-ui](https://code.jquery.com/ui/) v1.11
 
@@ -11,7 +11,7 @@ Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must incl
 <link rel="stylesheet" href=".../dragtable.css">
 <script src=".../jquery-ui.js"></script>
 <script src=".../jquery.dragtable.js"></script>
-<script src="extensions/cookie/bootstrap-table-reorder-columns.js"></script>
+<script src="extensions/reordercolumns/bootstrap-table-reorder-columns.js"></script>
 ```
 
 ## Options

+ 74 - 0
docs/_i18n/es/extensions/reorderrows.md

@@ -0,0 +1,74 @@
+# Table Reorder Rows
+
+Use Plugin: [bootstrap-table-reorder-rows](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorderrows) </br>
+Dependence: [tablednd](https://github.com/isocra/TableDnD) v0.9, </br>
+if you want you can include the bootstrap-table-reorder-rows.css file to use the default dragClass
+
+
+## Usage
+
+```html
+<link rel="stylesheet" href=".../bootstrap-table-reorder-rows.css">
+<script src=".../jquery.tablednd.js"></script>
+<script src="extensions/reorderrows/bootstrap-table-reorder-rows.js"></script>
+```
+
+## Options
+
+### reorderableRows
+
+* type: Boolean
+* description: Set true to allow the reorder feature.
+* default: `false`
+
+### onDragStyle
+
+* type: String
+* description: This is the style that is assigned to the row during drag. There are limitations to the styles that can be associated with a row (such as you can't assign a border—well you can, but it won't be displayed).
+* default: `null`
+
+### onDropStyle
+
+* type: String
+* description: This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations to what you can do. Also this replaces the original style, so again consider using onDragClass which is simply added and then removed on drop.
+* default: `null`
+
+### onDragClass
+
+* type: String
+* description: This class is added for the duration of the drag and then removed when the row is dropped. It is more flexible than using onDragStyle since it can be inherited by the row cells and other content.
+* default: `reorder_rows_onDragClass`
+
+### dragHandle
+
+* type: String
+* description: This is the cursor to use
+* default: `null`
+
+### useRowAttrFunc
+
+* type: Boolean
+* description: This function must be use if your `tr` elements won't have the `id` attribute. If your `tr` elements don't have the `id` attribute this plugin don't fire the onDrop event.
+* default: `false`
+
+### onReorderRowsDrag
+
+* type: Function
+* description: Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the table and the row which the user has started to drag.
+* default: `empty function`
+
+### onReorderRowsDrop
+
+* type: Function
+* description: Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table and the row that was dropped.
+* default: `empty function`
+
+## Events
+
+### onReorderRow(reorder-row.bs.table)
+
+Fired when the row was dropped, receive as parameter the new data order
+
+## The existing problems
+
+* After search if the user reorder the rows the data is not shown properly after that.

+ 53 - 0
docs/_i18n/es/extensions/toolbar.md

@@ -0,0 +1,53 @@
+# Table Toolbar
+
+Use Plugin: [bootstrap-table-toolbar](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar)
+
+## Usage
+
+```html
+<script src="extensions/toolbar/bootstrap-table-toolbar.js"></script>
+```
+
+## Options
+
+### advancedSearch
+
+* type: Boolean
+* description: Set true to allow the advanced search.
+* default: `false`
+
+### idForm
+
+* type: String
+* description: Must be set to know the idform.
+* default: `advancedSearch`
+
+### actionForm
+
+* type: String
+* description: Set the action of the form (pop-up).
+* default: ``
+
+### idTable
+
+* type: String
+* description: Set the id of the table to create the pop-up form.
+* default: ``
+
+## Locales
+
+### formatAdvancedSearch
+
+* description: Title of the advanced search modal
+* default: `Advanced search`
+
+### formatAdvancedCloseButton
+
+* description: Text of the close button
+* default: `Close`
+
+## Events
+
+### onColumnAdvancedSearch(column-advanced-search.bs.table)
+
+* Fired when we are searching into the advanced search form

+ 14 - 0
docs/_i18n/zh-cn/documentation/events.md

@@ -173,5 +173,19 @@
        <td>none</td>
        <td>Fires after the table header is rendered and availble in the DOM</td>
     </tr>
+    <tr>
+        <td>onExpandRow</td>
+        <td>expand-row.bs.table</td>
+        <td>index, row, $detail</td>
+        <td>当点击详细图标展开详细页面的时候触发。</td>
+    </tr>
+    <tr>
+       <td>onCollapseRow</td>
+       <td>collapse-row.bs.table</td>
+       <td>index, row</td>
+       <td>当点击详细图片收起详细页面的时候触发。</td>
+    </tr>
+    </tbody>
+</table>
     </tbody>
 </table>

+ 14 - 0
docs/_i18n/zh-cn/documentation/table-options.md

@@ -332,6 +332,20 @@ The table options is defined in `jQuery.fn.bootstrapTable.defaults`.
         <td>True to show card view table, for example mobile view.</td>
     </tr>
     <tr>
+        <td>detailView</td>
+        <td>data-detail-view</td>
+        <td>Boolean</td>
+        <td>false</td>
+        <td>设置为 True 可以显示详细页面模式。</td>
+    </tr>
+    <tr>
+        <td>detailFormatter</td>
+        <td>data-detail-formatter</td>
+        <td>Function</td>
+        <td>function(index, row) {<br>return '';<br>}</td>
+        <td>格式化详细页面模式的视图。</td>
+    </tr>
+    <tr>
         <td>searchAlign</td>
         <td>data-search-align</td>
         <td>String</td>

+ 3 - 3
docs/_i18n/zh-cn/extensions/reordercolumns.md

@@ -1,6 +1,6 @@
-# Table Reorder
+# Table Reorder Columns
 
-Use Plugin: [bootstrap-table-reorder](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder) </br>
+Use Plugin: [bootstrap-table-reorder-columns](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reordercolumns) </br>
 Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must include the css file), </br>
 [jquery-ui](https://code.jquery.com/ui/) v1.11
 
@@ -11,7 +11,7 @@ Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must incl
 <link rel="stylesheet" href=".../dragtable.css">
 <script src=".../jquery-ui.js"></script>
 <script src=".../jquery.dragtable.js"></script>
-<script src="extensions/cookie/bootstrap-table-reorder-columns.js"></script>
+<script src="extensions/reordercolumns/bootstrap-table-reorder-columns.js"></script>
 ```
 
 ## Options

+ 74 - 0
docs/_i18n/zh-cn/extensions/reorderrows.md

@@ -0,0 +1,74 @@
+# Table Reorder Rows
+
+Use Plugin: [bootstrap-table-reorder-rows](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorderrows) </br>
+Dependence: [tablednd](https://github.com/isocra/TableDnD) v0.9, </br>
+if you want you can include the bootstrap-table-reorder-rows.css file to use the default dragClass
+
+
+## Usage
+
+```html
+<link rel="stylesheet" href=".../bootstrap-table-reorder-rows.css">
+<script src=".../jquery.tablednd.js"></script>
+<script src="extensions/reorderrows/bootstrap-table-reorder-rows.js"></script>
+```
+
+## Options
+
+### reorderableRows
+
+* type: Boolean
+* description: Set true to allow the reorder feature.
+* default: `false`
+
+### onDragStyle
+
+* type: String
+* description: This is the style that is assigned to the row during drag. There are limitations to the styles that can be associated with a row (such as you can't assign a border—well you can, but it won't be displayed).
+* default: `null`
+
+### onDropStyle
+
+* type: String
+* description: This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations to what you can do. Also this replaces the original style, so again consider using onDragClass which is simply added and then removed on drop.
+* default: `null`
+
+### onDragClass
+
+* type: String
+* description: This class is added for the duration of the drag and then removed when the row is dropped. It is more flexible than using onDragStyle since it can be inherited by the row cells and other content.
+* default: `reorder_rows_onDragClass`
+
+### dragHandle
+
+* type: String
+* description: This is the cursor to use
+* default: `null`
+
+### useRowAttrFunc
+
+* type: Boolean
+* description: This function must be use if your `tr` elements won't have the `id` attribute. If your `tr` elements don't have the `id` attribute this plugin don't fire the onDrop event.
+* default: `false`
+
+### onReorderRowsDrag
+
+* type: Function
+* description: Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the table and the row which the user has started to drag.
+* default: `empty function`
+
+### onReorderRowsDrop
+
+* type: Function
+* description: Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table and the row that was dropped.
+* default: `empty function`
+
+## Events
+
+### onReorderRow(reorder-row.bs.table)
+
+Fired when the row was dropped, receive as parameter the new data order
+
+## The existing problems
+
+* After search if the user reorder the rows the data is not shown properly after that.

+ 53 - 0
docs/_i18n/zh-cn/extensions/toolbar.md

@@ -0,0 +1,53 @@
+# Table Toolbar
+
+Use Plugin: [bootstrap-table-toolbar](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar)
+
+## Usage
+
+```html
+<script src="extensions/toolbar/bootstrap-table-toolbar.js"></script>
+```
+
+## Options
+
+### advancedSearch
+
+* type: Boolean
+* description: Set true to allow the advanced search.
+* default: `false`
+
+### idForm
+
+* type: String
+* description: Must be set to know the idform.
+* default: `advancedSearch`
+
+### actionForm
+
+* type: String
+* description: Set the action of the form (pop-up).
+* default: ``
+
+### idTable
+
+* type: String
+* description: Set the id of the table to create the pop-up form.
+* default: ``
+
+## Locales
+
+### formatAdvancedSearch
+
+* description: Title of the advanced search modal
+* default: `Advanced search`
+
+### formatAdvancedCloseButton
+
+* description: Text of the close button
+* default: `Close`
+
+## Events
+
+### onColumnAdvancedSearch(column-advanced-search.bs.table)
+
+* Fired when we are searching into the advanced search form

+ 4 - 0
src/bootstrap-table.css

@@ -96,6 +96,10 @@
     padding-right: 30px;
 }
 
+.fixed-table-container th.detail {
+    width: 30px;
+}
+
 .fixed-table-container tbody td {
     border-left: 1px solid #dddddd;
 }

+ 103 - 50
src/bootstrap-table.js

@@ -211,6 +211,10 @@
         idField: undefined,
         uniqueId: undefined,
         cardView: false,
+        detailView: false,
+        detailFormatter: function (index, row) {
+            return '';
+        },
         trimOnSearch: true,
         clickToSelect: false,
         singleSelect: false,
@@ -301,6 +305,12 @@
         },
         onPostRows: function () {
             return false;
+        },
+        onExpandRow: function (index, row, $detail) {
+            return false;
+        },
+        onCollapseRow: function (index, row) {
+            return false;
         }
     };
 
@@ -389,7 +399,9 @@
         'post-body.bs.table': 'onPostBody',
         'post-header.bs.table': 'onPostHeader',
         'pre-rows.bs.table': 'onPreRows',
-        'post-rows.bs.table': 'onPostRows'
+        'post-rows.bs.table': 'onPostRows',
+        'expand-row.bs.table': 'onExpandRow',
+        'collapse-row.bs.table': 'onCollapseRow'
     };
 
     BootstrapTable.prototype.init = function () {
@@ -426,16 +438,23 @@
             '</div>'].join(''));
 
         this.$container.insertAfter(this.$el);
-        this.$container.find('.fixed-table-body').append(this.$el);
+        this.$tableContainer = this.$container.find('.fixed-table-container');
+        this.$tableHeader = this.$container.find('.fixed-table-header');
+        this.$tableBody = this.$container.find('.fixed-table-body');
+        this.$tableLoading = this.$container.find('.fixed-table-loading');
+        this.$tableFooter = this.$container.find('.fixed-table-footer');
+        this.$toolbar = this.$container.find('.fixed-table-toolbar');
+        this.$pagination = this.$container.find('.fixed-table-pagination');
+
+        this.$tableBody.append(this.$el);
         this.$container.after('<div class="clearfix"></div>');
-        this.$loading = this.$container.find('.fixed-table-loading');
 
         this.$el.addClass(this.options.classes);
         if (this.options.striped) {
             this.$el.addClass('table-striped');
         }
         if ($.inArray('table-no-bordered', this.options.classes.split(' ')) !== -1) {
-            this.$container.find('.fixed-table-container').addClass('table-no-bordered');
+            this.$tableContainer.addClass('table-no-bordered');
         }
     };
 
@@ -455,7 +474,7 @@
             var column = $.extend({}, {
                 title: $(this).html(),
                 'class': $(this).attr('class')
-            }, getRealDataAttr($(this).data()));
+            }, $(this).data());
 
             columns.push(column);
         });
@@ -512,6 +531,11 @@
             searchables: []
         };
 
+        if (!this.options.cardView && this.options.detailView) {
+            html.push('<th class="detail"><div class="fht-cell"></div></th>');
+            visibleColumns.push({});
+        }
+
         $.each(this.options.columns, function (i, column) {
             var text = '',
                 halign = '', // header align style
@@ -519,12 +543,12 @@
                 style = '',
                 class_ = sprintf(' class="%s"', column['class']),
                 order = that.options.sortOrder || column.order,
-                searchable = true,
                 unitWidth = 'px',
                 width = column.width;
 
             if (!column.visible) {
-                // Fix #229. Default Sort order is wrong if data-visible="false" is set on the field referenced by data-sort-name.
+                // Fix #229. Default Sort order is wrong
+                // if data-visible="false" is set on the field referenced by data-sort-name.
                 if (column.field === that.options.sortName) {
                     that.header.fields.push(column.field);
                 }
@@ -606,12 +630,12 @@
 
         if (!this.options.showHeader || this.options.cardView) {
             this.$header.hide();
-            this.$container.find('.fixed-table-header').hide();
-            this.$loading.css('top', 0);
+            this.$tableHeader.hide();
+            this.$tableLoading.css('top', 0);
         } else {
             this.$header.show();
-            this.$container.find('.fixed-table-header').show();
-            this.$loading.css('top', cellHeight + 'px');
+            this.$tableHeader.show();
+            this.$tableLoading.css('top', cellHeight + 'px');
             // Assign the correct sortable arrow
             this.getCaretHtml();
         }
@@ -625,11 +649,10 @@
     };
 
     BootstrapTable.prototype.initFooter = function () {
-        this.$footer = this.$container.find('.fixed-table-footer');
         if (!this.options.showFooter || this.options.cardView) {
-            this.$footer.hide();
+            this.$tableFooter.hide();
         } else {
-            this.$footer.show();
+            this.$tableFooter.show();
         }
     };
 
@@ -753,7 +776,7 @@
             $search,
             switchableCount = 0;
 
-        this.$toolbar = this.$container.find('.fixed-table-toolbar').html('');
+        this.$toolbar.html('');
 
         if (typeof this.options.toolbar === 'string') {
             $(sprintf('<div class="bars pull-%s"></div>', this.options.toolbarAlign))
@@ -950,8 +973,6 @@
     };
 
     BootstrapTable.prototype.initPagination = function () {
-        this.$pagination = this.$container.find('.fixed-table-pagination');
-
         if (!this.options.pagination) {
             this.$pagination.hide();
             return;
@@ -1248,6 +1269,14 @@
                 html.push(sprintf('<td colspan="%s">', this.header.fields.length));
             }
 
+            if (!this.options.cardView && this.options.detailView) {
+                html.push('<td>',
+                    '<a class="detail-icon" href="javascript:">',
+                    '<i class="glyphicon glyphicon-plus icon-plus"></i>',
+                    '</a>',
+                    '</td>');
+            }
+
             $.each(this.header.fields, function (j, field) {
                 var text = '',
                     value = item[field],
@@ -1349,7 +1378,8 @@
         // show no records
         if (!html.length) {
             html.push('<tr class="no-records-found">',
-                sprintf('<td colspan="%s">%s</td>', this.header.fields.length, this.options.formatNoMatches()),
+                sprintf('<td colspan="%s">%s</td>',
+                    this.$header.find('th').length, this.options.formatNoMatches()),
                 '</tr>');
         }
 
@@ -1357,7 +1387,6 @@
         this.$body.html(html.join(''));
         this.trigger('post-rows');
 
-
         if (!fixedScroll) {
             this.scrollTo(0);
         }
@@ -1374,10 +1403,31 @@
                 }
             }
         });
-        this.$body.find('tr').off('dblclick').on('dblclick', function () {
+        this.$body.find('> tr').off('dblclick').on('dblclick', function () {
             that.trigger('dbl-click-row', that.data[$(this).data('index')], $(this));
         });
 
+        this.$body.find('> tr > td > .detail-icon').off('click').on('click', function () {
+            var $this = $(this),
+                $tr = $this.parent().parent(),
+                index = $tr.data('index'),
+                row = that.options.data[index];
+
+            // remove and update
+            if ($tr.next().is('tr.detail-view')) {
+                $this.find('i').attr('class', 'glyphicon glyphicon-plus icon-plus');
+                $tr.next().remove();
+                that.trigger('collapse-row', index, row);
+            } else {
+                $this.find('i').attr('class', 'glyphicon glyphicon-minus icon-minus');
+                $tr.after(sprintf('<tr class="detail-view"><td colspan="%s">%s</td></tr>',
+                    $tr.find('td').length, calculateObjectValue(that.options,
+                        that.options.detailFormatter, [index, row], '')));
+                that.trigger('expand-row', index, row, $tr.next().find('td'));
+            }
+            that.resetView();
+        });
+
         this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName));
         this.$selectItem.off('click').on('click', function (event) {
             event.stopImmediatePropagation();
@@ -1406,6 +1456,9 @@
             if (typeof events === 'string') {
                 events = calculateObjectValue(null, events);
             }
+            if (!that.options.cardView && that.options.detailView) {
+                i += 1;
+            }
             for (var key in events) {
                 that.$body.find('tr').each(function () {
                     var $tr = $(this),
@@ -1477,7 +1530,7 @@
         }
 
         if (!silent) {
-            this.$loading.show();
+            this.$tableLoading.show();
         }
         request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {
             type: this.options.method,
@@ -1498,7 +1551,7 @@
             },
             complete: function () {
                 if (!silent) {
-                    that.$loading.hide();
+                    that.$tableLoading.hide();
                 }
             }
         });
@@ -1571,8 +1624,6 @@
 
     BootstrapTable.prototype.fitHeader = function () {
         var that = this,
-            $fixedHeader,
-            $fixedBody,
             fixedBody,
             scrollWidth;
 
@@ -1580,9 +1631,7 @@
             that.timeoutFooter_ = setTimeout($.proxy(that.fitHeader, that), 100);
             return;
         }
-        $fixedHeader = this.$container.find('.fixed-table-header');
-        $fixedBody = this.$container.find('.fixed-table-body');
-        fixedBody = $fixedBody.get(0);
+        fixedBody = this.$tableBody.get(0);
 
         scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth &&
             fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.height() ?
@@ -1591,7 +1640,7 @@
         this.$el.css('margin-top', -this.$header.height());
         this.$header_ = this.$header.clone(true, true);
         this.$selectAll_ = this.$header_.find('[name="btSelectAll"]');
-        $fixedHeader.css({
+        this.$tableHeader.css({
             'margin-right': scrollWidth
         }).find('table').css('width', this.$el.css('width'))
             .html('').attr('class', this.$el.attr('class'))
@@ -1607,8 +1656,8 @@
         });
         // horizontal scroll event
         // TODO: it's probably better improving the layout than binding to scroll event
-        $fixedBody.off('scroll').on('scroll', function () {
-            $fixedHeader.scrollLeft($(this).scrollLeft());
+        this.$tableBody.off('scroll').on('scroll', function () {
+            that.$tableHeader.scrollLeft($(this).scrollLeft());
         });
         that.trigger('post-header');
     };
@@ -1622,6 +1671,10 @@
             return;
         }
 
+        if (!this.options.cardView && this.options.detailView) {
+            html.push('<td></td>');
+        }
+
         $.each(this.options.columns, function (i, column) {
             var falign = '', // footer align style
                 style = '',
@@ -1640,12 +1693,11 @@
 
             html.push('<td', class_, sprintf(' style="%s"', falign + style), '>');
 
-
             html.push(calculateObjectValue(column, column.footerFormatter, [data], '&nbsp;') || '&nbsp;');
             html.push('</td>');
         });
 
-        this.$footer.find('tr').html(html.join(''));
+        this.$tableFooter.find('tr').html(html.join(''));
         clearTimeout(this.timeoutFooter_);
         this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this),
             this.$el.is(':hidden') ? 100 : 0);
@@ -1653,7 +1705,6 @@
 
     BootstrapTable.prototype.fitFooter = function () {
         var that = this,
-            $fixedBody,
             $footerTd,
             elWidth,
             scrollWidth;
@@ -1664,18 +1715,17 @@
             return;
         }
 
-        $fixedBody = this.$container.find('.fixed-table-body');
         elWidth = this.$el.css('width');
-        scrollWidth = elWidth > $fixedBody.width() ? getScrollBarWidth() : 0;
+        scrollWidth = elWidth > this.$tableBody.width() ? getScrollBarWidth() : 0;
 
-        this.$footer.css({
+        this.$tableFooter.css({
             'margin-right': scrollWidth
         }).find('table').css('width', elWidth)
             .attr('class', this.$el.attr('class'));
 
-        $footerTd = this.$footer.find('td');
+        $footerTd = this.$tableFooter.find('td');
 
-        $fixedBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function (i) {
+        this.$tableBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function (i) {
             $footerTd.eq(i).outerWidth($(this).outerWidth());
         });
     };
@@ -1717,8 +1767,7 @@
 
     BootstrapTable.prototype.resetView = function (params) {
         var that = this,
-            padding = 0,
-            $tableContainer = that.$container.find('.fixed-table-container');
+            padding = 0;
 
         if (params && params.height) {
             this.options.height = params.height;
@@ -1732,7 +1781,7 @@
                 paginationHeight = getRealHeight(this.$pagination),
                 height = this.options.height - toolbarHeight - paginationHeight;
 
-            $tableContainer.css('height', height + 'px');
+            this.$tableContainer.css('height', height + 'px');
         }
 
         if (this.options.cardView) {
@@ -1743,11 +1792,11 @@
         }
 
         if (this.options.showHeader && this.options.height) {
-            this.$container.find('.fixed-table-header').show();
+            this.$tableHeader.show();
             this.resetHeader();
             padding += cellHeight;
         } else {
-            this.$container.find('.fixed-table-header').hide();
+            this.$tableHeader.hide();
             this.trigger('post-header');
         }
 
@@ -1760,7 +1809,7 @@
 
         // Assign the correct sortable arrow
         this.getCaretHtml();
-        $tableContainer.css('padding-bottom', padding + 'px');
+        this.$tableContainer.css('padding-bottom', padding + 'px');
     };
 
     BootstrapTable.prototype.getData = function (useCurrentPage) {
@@ -1935,6 +1984,11 @@
             $tr = this.$body.find('tr'),
             $td = $tr.eq(row).find('td').eq(col);
 
+        if (!this.options.cardView && this.options.detailView) {
+            col += 1;
+        }
+        $td = $tr.eq(row).find('td').eq(col);
+
         if (row < 0 || col < 0 || row >= this.data.length) {
             return;
         }
@@ -2046,11 +2100,11 @@
     };
 
     BootstrapTable.prototype.showLoading = function () {
-        this.$loading.show();
+        this.$tableLoading.show();
     };
 
     BootstrapTable.prototype.hideLoading = function () {
-        this.$loading.hide();
+        this.$tableLoading.hide();
     };
 
     BootstrapTable.prototype.togglePagination = function () {
@@ -2097,15 +2151,14 @@
     };
 
     BootstrapTable.prototype.scrollTo = function (value) {
-        var $tbody = this.$container.find('.fixed-table-body');
         if (typeof value === 'string') {
-            value = value === 'bottom' ? $tbody[0].scrollHeight : 0;
+            value = value === 'bottom' ? this.$tableBody[0].scrollHeight : 0;
         }
         if (typeof value === 'number') {
-            $tbody.scrollTop(value);
+            this.$tableBody.scrollTop(value);
         }
         if (typeof value === 'undefined') {
-            return $tbody.scrollTop();
+            return this.$tableBody.scrollTop();
         }
     };