footable_rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,373 @@
1
+ (function($, w, undefined) {
2
+ if (w.footable === undefined || w.foobox === null) throw new Error('Please check and make sure footable.js is included in the page and is loaded prior to this script.');
3
+ var defaults = {
4
+ grid: {
5
+ enabled: true,
6
+ data: null,
7
+ template: null, //row html template, use for make a row.
8
+ cols: null, //column define
9
+ items: null, //data items
10
+ url: null, //get data from url
11
+ ajax: null, //paramater for $.ajax
12
+ activeClass: 'active', //add to row selected
13
+ multiSelect: false, //allow select multiple row
14
+ showIndex: false, //show row index
15
+ showCheckbox: false, //show checkbox for select
16
+ showEmptyInfo: false, //when that is not data in table, show a info to notify user
17
+ emptyInfo: '<p class="text-center text-warning">No Data</p>',
18
+ pagination: {
19
+ "page-size": 20,
20
+ "pagination-class": "pagination pagination-centered"
21
+ },
22
+ indexFormatter: function(val, $td, index) {
23
+ return index + 1;
24
+ },
25
+ checkboxFormatter: function(isTop) {
26
+ return '<input type="checkbox" class="' + (isTop ? 'checkAll' : 'check') + '">';
27
+ },
28
+ events: {
29
+ loaded: 'footable_grid_loaded',
30
+ created: 'footable_grid_created',
31
+ removed: 'footable_grid_removed',
32
+ updated: 'footable_grid_updated'
33
+ }
34
+ }
35
+ };
36
+
37
+ function makeTh(col) {
38
+ var $th = $('<th>' + col.title + '</th>');
39
+ if ($.isPlainObject(col.data)) {
40
+ $th.data(col.data);
41
+ }
42
+ if ($.isPlainObject(col.style)) {
43
+ $th.css(col.style);
44
+ }
45
+ if (col.className) {
46
+ $th.addClass(col.className);
47
+ }
48
+ return $th;
49
+ }
50
+
51
+ function initThead($table, options) {
52
+ var $thead = $table.find('thead');
53
+ if ($thead.size() === 0) {
54
+ $thead = $('<thead>').appendTo($table);
55
+ }
56
+ var $row = $('<tr>').appendTo($thead);
57
+ for (var i = 0, len = options.cols.length; i < len; i++) {
58
+ $row.append(makeTh(options.cols[i]));
59
+ }
60
+ }
61
+
62
+ function initTBody($table) {
63
+ var $tbody = $table.find('tbody');
64
+ if ($tbody.size() === 0) {
65
+ $tbody = $('<tbody>').appendTo($table);
66
+ }
67
+ }
68
+
69
+ function initPagination($table, cols, options) {
70
+ if (options) {
71
+ $table.attr("data-page-size", options['page-size']);
72
+ var $tfoot = $table.find('tfoot');
73
+ if ($tfoot.size() === 0) {
74
+ $tfoot = $('<tfoot class="hide-if-no-paging"></tfoot>').appendTo($table);
75
+ }
76
+ $tfoot.append('<tr><td colspan=' + cols.length + '></td></tr>');
77
+ var $pagination = $("<div>").appendTo($tfoot.find("tr:last-child td"));
78
+ $pagination.addClass(options['pagination-class']);
79
+ }
80
+ }
81
+
82
+ function setToggleColumn(cols) {
83
+ var toggleColumn = cols[0];
84
+ for (var i = 0, len = cols.length; i < len; i++) {
85
+ var col = cols[i];
86
+ if (col.data && (col.data.toggle === true || col.data.toggle === "true")) {
87
+ return;
88
+ }
89
+ }
90
+ toggleColumn.data = $.extend(toggleColumn.data, {
91
+ toggle: true
92
+ });
93
+ }
94
+
95
+ function makeEmptyInfo($table, cols, emptyInfo) {
96
+ if ($table.find("tr.emptyInfo").size() === 0) {
97
+ $table.find('tbody').append('<tr class="emptyInfo"><td colspan="' + cols.length + '">' + emptyInfo + '</td></tr>');
98
+ }
99
+ }
100
+
101
+ function updateRowIndex($tbody, $newRow, detailClass, offset) {
102
+ //update rows index
103
+ $tbody.find('tr:not(.' + detailClass + ')').each(function() {
104
+ var $row = $(this),
105
+ index = $newRow.data('index'),
106
+ oldIndex = parseInt($row.data('index'), 0),
107
+ newIndex = oldIndex + offset;
108
+ if (oldIndex >= index && this !== $newRow.get(0)) {
109
+ $row.attr('data-index', newIndex).data('index', newIndex);
110
+ }
111
+ });
112
+ }
113
+
114
+ function Grid() {
115
+ var grid = this;
116
+ grid.name = 'Footable Grid';
117
+ grid.init = function(ft) {
118
+ var toggleClass = ft.options.classes.toggle;
119
+ var detailClass = ft.options.classes.detail;
120
+ var options = ft.options.grid;
121
+ if (!options.cols) return;
122
+ grid.footable = ft;
123
+ var $table = $(ft.table);
124
+ $table.data('grid', grid);
125
+ if ($.isPlainObject(options.data)) {
126
+ $table.data(options.data);
127
+ }
128
+ grid._items = [];
129
+ setToggleColumn(options.cols);
130
+ if (options.showCheckbox) {
131
+ options.multiSelect = true;
132
+ options.cols.unshift({
133
+ title: options.checkboxFormatter(true),
134
+ name: '',
135
+ data: {
136
+ "sort-ignore": true
137
+ },
138
+ formatter: options.checkboxFormatter
139
+ });
140
+ }
141
+ if (options.showIndex) {
142
+ options.cols.unshift({
143
+ title: '#',
144
+ name: 'index',
145
+ data: {
146
+ "sort-ignore": true
147
+ },
148
+ formatter: options.indexFormatter
149
+ });
150
+ }
151
+ initThead($table, options);
152
+ initTBody($table);
153
+ initPagination($table, options.cols, options.pagination);
154
+ $table.off('.grid').on({
155
+ 'footable_initialized.grid': function(e) {
156
+ if (options.url || options.ajax) {
157
+ $.ajax(options.ajax || {
158
+ url: options.url
159
+ }).then(function(resp) {
160
+ grid.newItem(resp);
161
+ ft.raise(options.events.loaded);
162
+ }, function(jqXHR) {
163
+ throw 'load data from ' + (options.url || options.ajax.url) + ' fail';
164
+ });
165
+ } else {
166
+ grid.newItem(options.items || []);
167
+ ft.raise(options.events.loaded);
168
+ }
169
+ },
170
+ 'footable_sorted.grid footable_grid_created.grid footable_grid_removed.grid': function(event) {
171
+ if (options.showIndex && grid.getItem().length > 0) {
172
+ $table.find('tbody tr:not(.' + detailClass + ')').each(function(index) {
173
+ var $td = $(this).find('td:first');
174
+ $td.html(options.indexFormatter(null, $td, index));
175
+ });
176
+ }
177
+ },
178
+ 'footable_redrawn.grid footable_row_removed.grid': function(event) {
179
+ if (grid.getItem().length === 0 && options.showEmptyInfo) {
180
+ makeEmptyInfo($table, options.cols, options.emptyInfo);
181
+ }
182
+ }
183
+ }).on({
184
+ 'click.grid': function(event) {
185
+ if ($(event.target).closest('td').find('>.' + toggleClass).size() > 0) {
186
+ return true;
187
+ }
188
+ var $tr = $(event.currentTarget);
189
+ if ($tr.hasClass(detailClass)) {
190
+ return true;
191
+ }
192
+ if (!options.multiSelect && !$tr.hasClass(options.activeClass)) {
193
+ $table.find('tbody tr.' + options.activeClass).removeClass(options.activeClass);
194
+ }
195
+ $tr.toggleClass(options.activeClass);
196
+ if (options.showCheckbox) {
197
+ $tr.find('input:checkbox.check').prop('checked', function(index, val) {
198
+ if (event.target === this) {
199
+ return val;
200
+ }
201
+ return !val;
202
+ });
203
+ }
204
+ ft.toggleDetail($tr);
205
+ }
206
+ }, 'tbody tr').on('click.grid', 'thead input:checkbox.checkAll', function(event) {
207
+ var checked = !! event.currentTarget.checked;
208
+ if (checked) {
209
+ $table.find('tbody tr').addClass(options.activeClass);
210
+ } else {
211
+ $table.find('tbody tr').removeClass(options.activeClass);
212
+ }
213
+ $table.find('tbody input:checkbox.check').prop('checked', checked);
214
+ });
215
+ };
216
+ /**
217
+ * get selected rows index;
218
+ */
219
+ grid.getSelected = function() {
220
+ var options = grid.footable.options.grid,
221
+ $selected = $(grid.footable.table).find('tbody>tr.' + options.activeClass);
222
+ return $selected.map(function() {
223
+ return $(this).data('index');
224
+ });
225
+ };
226
+ /**
227
+ * get row's data by index
228
+ */
229
+ grid.getItem = function(index) {
230
+ if (index !== undefined) {
231
+ if ($.isArray(index)) {
232
+ return $.map(index, function(item) {
233
+ return grid._items[item];
234
+ });
235
+ }
236
+ return grid._items[index];
237
+ }
238
+ return grid._items;
239
+ };
240
+
241
+ function makeCell(col, value, index) {
242
+ var $td = $('<td>');
243
+ if (col.formatter) {
244
+ $td.html(col.formatter(value, $td, index));
245
+ } else {
246
+ $td.html(value || '');
247
+ }
248
+ return $td;
249
+ }
250
+ grid._makeRow = function(item, index) {
251
+ var options = grid.footable.options.grid;
252
+ var $row;
253
+ if ($.isFunction(options.template)) {
254
+ $row = $(options.template($.extend({}, {
255
+ __index: index
256
+ }, item)));
257
+ } else {
258
+ $row = $('<tr>');
259
+ for (var i = 0, len = options.cols.length; i < len; i++) {
260
+ var col = options.cols[i];
261
+ $row.append(makeCell(col, item[col.name] || '', index));
262
+ }
263
+ }
264
+ $row.attr('data-index', index);
265
+ return $row;
266
+ };
267
+ /**
268
+ * create rows by js object
269
+ */
270
+ grid.newItem = function(item, index, wait) {
271
+ var $tbody = $(grid.footable.table).find('tbody');
272
+ var detailClass = grid.footable.options.classes.detail;
273
+ $tbody.find('tr.emptyInfo').remove();
274
+ if ($.isArray(item)) {
275
+ for (var atom;
276
+ (atom = item.pop());) {
277
+ grid.newItem(atom, index, true);
278
+ }
279
+ grid.footable.redraw();
280
+ grid.footable.raise(grid.footable.options.grid.events.created, {
281
+ item: item,
282
+ index: index
283
+ });
284
+ return;
285
+ }
286
+ if (!$.isPlainObject(item)) {
287
+ return;
288
+ }
289
+ var $tr, len = grid._items.length;
290
+ if (index === undefined || index < 0 || index > len) {
291
+ $tr = grid._makeRow(item, len++);
292
+ grid._items.push(item);
293
+ $tbody.append($tr);
294
+ } else {
295
+ $tr = grid._makeRow(item, index);
296
+ if (index === 0) {
297
+ grid._items.unshift(item);
298
+ $tbody.prepend($tr);
299
+ } else {
300
+ var $before = $tbody.find('tr[data-index=' + (index - 1) + ']');
301
+ grid._items.splice(index, 0, item);
302
+ if ($before.data('detail_created') === true) {
303
+ $before = $before.next();
304
+ }
305
+ $before.after($tr);
306
+ }
307
+ updateRowIndex($tbody, $tr, detailClass, 1);
308
+ }
309
+ if (!wait) {
310
+ grid.footable.redraw();
311
+ grid.footable.raise(grid.footable.options.grid.events.created, {
312
+ item: item,
313
+ index: index
314
+ });
315
+ }
316
+ };
317
+ /**
318
+ * update row by js object
319
+ */
320
+ grid.setItem = function(item, index) {
321
+ if (!$.isPlainObject(item)) {
322
+ return;
323
+ }
324
+ var $tbody = $(grid.footable.table).find('tbody'),
325
+ $newTr = grid._makeRow(item, index);
326
+ $.extend(grid._items[index], item);
327
+ var $tr = $tbody.find('tr').eq(index);
328
+ $tr.html($newTr.html());
329
+ grid.footable.redraw();
330
+ grid.footable.raise(grid.footable.options.grid.events.updated, {
331
+ item: item,
332
+ index: index
333
+ });
334
+ };
335
+ /**
336
+ * remove rows by index
337
+ */
338
+ grid.removeItem = function(index) {
339
+ var $tbody = $(grid.footable.table).find('tbody');
340
+ var detailClass = grid.footable.options.classes.detail;
341
+ var result = [];
342
+ if ($.isArray(index)) {
343
+ for (var i;
344
+ (i = index.pop());) {
345
+ result.push(grid.removeItem(i));
346
+ }
347
+ grid.footable.raise(grid.footable.options.grid.events.removed, {
348
+ item: result,
349
+ index: index
350
+ });
351
+ return result;
352
+ }
353
+ if (index === undefined) {
354
+ $tbody.find('tr').each(function() {
355
+ result.push(grid._items.shift());
356
+ grid.footable.removeRow(this);
357
+ });
358
+ } else {
359
+ var $tr = $tbody.find('tr[data-index=' + index + ']');
360
+ result = grid._items.splice(index, 1)[0];
361
+ grid.footable.removeRow($tr);
362
+ //update rows index
363
+ updateRowIndex($tbody, $tr, detailClass, -1);
364
+ }
365
+ grid.footable.raise(grid.footable.options.grid.events.removed, {
366
+ item: result,
367
+ index: index
368
+ });
369
+ return result;
370
+ };
371
+ }
372
+ w.footable.plugins.register(Grid, defaults);
373
+ })(jQuery, window);
@@ -0,0 +1,827 @@
1
+ /*!
2
+ * FooTable - Awesome Responsive Tables
3
+ * Version : 2.0.3
4
+ * http://fooplugins.com/plugins/footable-jquery/
5
+ *
6
+ * Requires jQuery - http://jquery.com/
7
+ *
8
+ * Copyright 2014 Steven Usher & Brad Vincent
9
+ * Released under the MIT license
10
+ * You are free to use FooTable in commercial projects as long as this copyright header is left intact.
11
+ *
12
+ * Date: 11 Nov 2014
13
+ */
14
+ (function ($, w, undefined) {
15
+ w.footable = {
16
+ options: {
17
+ delay: 100, // The number of millseconds to wait before triggering the react event
18
+ breakpoints: { // The different screen resolution breakpoints
19
+ phone: 480,
20
+ tablet: 1024
21
+ },
22
+ parsers: { // The default parser to parse the value out of a cell (values are used in building up row detail)
23
+ alpha: function (cell) {
24
+ return $(cell).data('value') || $.trim($(cell).text());
25
+ },
26
+ numeric: function (cell) {
27
+ var val = $(cell).data('value') || $(cell).text().replace(/[^0-9.\-]/g, '');
28
+ val = parseFloat(val);
29
+ if (isNaN(val)) val = 0;
30
+ return val;
31
+ }
32
+ },
33
+ addRowToggle: true,
34
+ calculateWidthOverride: null,
35
+ toggleSelector: ' > tbody > tr:not(.footable-row-detail)', //the selector to show/hide the detail row
36
+ columnDataSelector: '> thead > tr:last-child > th, > thead > tr:last-child > td', //the selector used to find the column data in the thead
37
+ detailSeparator: ':', //the separator character used when building up the detail row
38
+ toggleHTMLElement: '<span />', // override this if you want to insert a click target rather than use a background image.
39
+ createGroupedDetail: function (data) {
40
+ var groups = { '_none': { 'name': null, 'data': [] } };
41
+ for (var i = 0; i < data.length; i++) {
42
+ var groupid = data[i].group;
43
+ if (groupid !== null) {
44
+ if (!(groupid in groups))
45
+ groups[groupid] = { 'name': data[i].groupName || data[i].group, 'data': [] };
46
+
47
+ groups[groupid].data.push(data[i]);
48
+ } else {
49
+ groups._none.data.push(data[i]);
50
+ }
51
+ }
52
+ return groups;
53
+ },
54
+ createDetail: function (element, data, createGroupedDetail, separatorChar, classes) {
55
+ /// <summary>This function is used by FooTable to generate the detail view seen when expanding a collapsed row.</summary>
56
+ /// <param name="element">This is the div that contains all the detail row information, anything could be added to it.</param>
57
+ /// <param name="data">
58
+ /// This is an array of objects containing the cell information for the current row.
59
+ /// These objects look like the below:
60
+ /// obj = {
61
+ /// 'name': String, // The name of the column
62
+ /// 'value': Object, // The value parsed from the cell using the parsers. This could be a string, a number or whatever the parser outputs.
63
+ /// 'display': String, // This is the actual HTML from the cell, so if you have images etc you want moved this is the one to use and is the default value used.
64
+ /// 'group': String, // This is the identifier used in the data-group attribute of the column.
65
+ /// 'groupName': String // This is the actual name of the group the column belongs to.
66
+ /// }
67
+ /// </param>
68
+ /// <param name="createGroupedDetail">The grouping function to group the data</param>
69
+ /// <param name="separatorChar">The separator charactor used</param>
70
+ /// <param name="classes">The array of class names used to build up the detail row</param>
71
+
72
+ var groups = createGroupedDetail(data);
73
+ for (var group in groups) {
74
+ if (groups[group].data.length === 0) continue;
75
+ if (group !== '_none') element.append('<div class="' + classes.detailInnerGroup + '">' + groups[group].name + '</div>');
76
+
77
+ for (var j = 0; j < groups[group].data.length; j++) {
78
+ var separator = (groups[group].data[j].name) ? separatorChar : '';
79
+ element.append($('<div></div>').addClass(classes.detailInnerRow).append($('<div></div>').addClass(classes.detailInnerName)
80
+ .append(groups[group].data[j].name + separator)).append($('<div></div>').addClass(classes.detailInnerValue)
81
+ .attr('data-bind-value', groups[group].data[j].bindName).append(groups[group].data[j].display)));
82
+ }
83
+ }
84
+ },
85
+ classes: {
86
+ main: 'footable',
87
+ loading: 'footable-loading',
88
+ loaded: 'footable-loaded',
89
+ toggle: 'footable-toggle',
90
+ disabled: 'footable-disabled',
91
+ detail: 'footable-row-detail',
92
+ detailCell: 'footable-row-detail-cell',
93
+ detailInner: 'footable-row-detail-inner',
94
+ detailInnerRow: 'footable-row-detail-row',
95
+ detailInnerGroup: 'footable-row-detail-group',
96
+ detailInnerName: 'footable-row-detail-name',
97
+ detailInnerValue: 'footable-row-detail-value',
98
+ detailShow: 'footable-detail-show'
99
+ },
100
+ triggers: {
101
+ initialize: 'footable_initialize', //trigger this event to force FooTable to reinitialize
102
+ resize: 'footable_resize', //trigger this event to force FooTable to resize
103
+ redraw: 'footable_redraw', //trigger this event to force FooTable to redraw
104
+ toggleRow: 'footable_toggle_row', //trigger this event to force FooTable to toggle a row
105
+ expandFirstRow: 'footable_expand_first_row', //trigger this event to force FooTable to expand the first row
106
+ expandAll: 'footable_expand_all', //trigger this event to force FooTable to expand all rows
107
+ collapseAll: 'footable_collapse_all' //trigger this event to force FooTable to collapse all rows
108
+ },
109
+ events: {
110
+ alreadyInitialized: 'footable_already_initialized', //fires when the FooTable has already been initialized
111
+ initializing: 'footable_initializing', //fires before FooTable starts initializing
112
+ initialized: 'footable_initialized', //fires after FooTable has finished initializing
113
+ resizing: 'footable_resizing', //fires before FooTable resizes
114
+ resized: 'footable_resized', //fires after FooTable has resized
115
+ redrawn: 'footable_redrawn', //fires after FooTable has redrawn
116
+ breakpoint: 'footable_breakpoint', //fires inside the resize function, when a breakpoint is hit
117
+ columnData: 'footable_column_data', //fires when setting up column data. Plugins should use this event to capture their own info about a column
118
+ rowDetailUpdating: 'footable_row_detail_updating', //fires before a detail row is updated
119
+ rowDetailUpdated: 'footable_row_detail_updated', //fires when a detail row is being updated
120
+ rowCollapsed: 'footable_row_collapsed', //fires when a row is collapsed
121
+ rowExpanded: 'footable_row_expanded', //fires when a row is expanded
122
+ rowRemoved: 'footable_row_removed', //fires when a row is removed
123
+ reset: 'footable_reset' //fires when FooTable is reset
124
+ },
125
+ debug: false, // Whether or not to log information to the console.
126
+ log: null
127
+ },
128
+
129
+ version: {
130
+ major: 0, minor: 5,
131
+ toString: function () {
132
+ return w.footable.version.major + '.' + w.footable.version.minor;
133
+ },
134
+ parse: function (str) {
135
+ var version = /(\d+)\.?(\d+)?\.?(\d+)?/.exec(str);
136
+ return {
137
+ major: parseInt(version[1], 10) || 0,
138
+ minor: parseInt(version[2], 10) || 0,
139
+ patch: parseInt(version[3], 10) || 0
140
+ };
141
+ }
142
+ },
143
+
144
+ plugins: {
145
+ _validate: function (plugin) {
146
+ ///<summary>Simple validation of the <paramref name="plugin"/> to make sure any members called by FooTable actually exist.</summary>
147
+ ///<param name="plugin">The object defining the plugin, this should implement a string property called "name" and a function called "init".</param>
148
+
149
+ if (!$.isFunction(plugin)) {
150
+ if (w.footable.options.debug === true) console.error('Validation failed, expected type "function", received type "{0}".', typeof plugin);
151
+ return false;
152
+ }
153
+ var p = new plugin();
154
+ if (typeof p['name'] !== 'string') {
155
+ if (w.footable.options.debug === true) console.error('Validation failed, plugin does not implement a string property called "name".', p);
156
+ return false;
157
+ }
158
+ if (!$.isFunction(p['init'])) {
159
+ if (w.footable.options.debug === true) console.error('Validation failed, plugin "' + p['name'] + '" does not implement a function called "init".', p);
160
+ return false;
161
+ }
162
+ if (w.footable.options.debug === true) console.log('Validation succeeded for plugin "' + p['name'] + '".', p);
163
+ return true;
164
+ },
165
+ registered: [], // An array containing all registered plugins.
166
+ register: function (plugin, options) {
167
+ ///<summary>Registers a <paramref name="plugin"/> and its default <paramref name="options"/> with FooTable.</summary>
168
+ ///<param name="plugin">The plugin that should implement a string property called "name" and a function called "init".</param>
169
+ ///<param name="options">The default options to merge with the FooTable's base options.</param>
170
+
171
+ if (w.footable.plugins._validate(plugin)) {
172
+ w.footable.plugins.registered.push(plugin);
173
+ if (typeof options === 'object') $.extend(true, w.footable.options, options);
174
+ }
175
+ },
176
+ load: function(instance){
177
+ var loaded = [], registered, i;
178
+ for(i = 0; i < w.footable.plugins.registered.length; i++){
179
+ try {
180
+ registered = w.footable.plugins.registered[i];
181
+ loaded.push(new registered(instance));
182
+ } catch (err) {
183
+ if (w.footable.options.debug === true) console.error(err);
184
+ }
185
+ }
186
+ return loaded;
187
+ },
188
+ init: function (instance) {
189
+ ///<summary>Loops through all registered plugins and calls the "init" method supplying the current <paramref name="instance"/> of the FooTable as the first parameter.</summary>
190
+ ///<param name="instance">The current instance of the FooTable that the plugin is being initialized for.</param>
191
+
192
+ for (var i = 0; i < instance.plugins.length; i++) {
193
+ try {
194
+ instance.plugins[i]['init'](instance);
195
+ } catch (err) {
196
+ if (w.footable.options.debug === true) console.error(err);
197
+ }
198
+ }
199
+ }
200
+ }
201
+ };
202
+
203
+ var instanceCount = 0;
204
+
205
+ $.fn.footable = function (options) {
206
+ ///<summary>The main constructor call to initialize the plugin using the supplied <paramref name="options"/>.</summary>
207
+ ///<param name="options">
208
+ ///<para>A JSON object containing user defined options for the plugin to use. Any options not supplied will have a default value assigned.</para>
209
+ ///<para>Check the documentation or the default options object above for more information on available options.</para>
210
+ ///</param>
211
+
212
+ options = options || {};
213
+ if (options.breakpoints) { // clear the default breakpoints if the user specifies one
214
+ w.footable.options.breakpoints = {};
215
+ }
216
+ var o = $.extend(true, {}, w.footable.options, options); //merge user and default options
217
+ return this.each(function () {
218
+ instanceCount++;
219
+ var footable = new Footable(this, o, instanceCount);
220
+ $(this).data('footable', footable);
221
+ });
222
+ };
223
+
224
+ //helper for using timeouts
225
+ function Timer() {
226
+ ///<summary>Simple timer object created around a timeout.</summary>
227
+ var t = this;
228
+ t.id = null;
229
+ t.busy = false;
230
+ t.start = function (code, milliseconds) {
231
+ ///<summary>Starts the timer and waits the specified amount of <paramref name="milliseconds"/> before executing the supplied <paramref name="code"/>.</summary>
232
+ ///<param name="code">The code to execute once the timer runs out.</param>
233
+ ///<param name="milliseconds">The time in milliseconds to wait before executing the supplied <paramref name="code"/>.</param>
234
+
235
+ if (t.busy) {
236
+ return;
237
+ }
238
+ t.stop();
239
+ t.id = setTimeout(function () {
240
+ code();
241
+ t.id = null;
242
+ t.busy = false;
243
+ }, milliseconds);
244
+ t.busy = true;
245
+ };
246
+ t.stop = function () {
247
+ ///<summary>Stops the timer if its runnning and resets it back to its starting state.</summary>
248
+
249
+ if (t.id !== null) {
250
+ clearTimeout(t.id);
251
+ t.id = null;
252
+ t.busy = false;
253
+ }
254
+ };
255
+ }
256
+
257
+ function Footable(t, o, id) {
258
+ ///<summary>Inits a new instance of the plugin.</summary>
259
+ ///<param name="t">The main table element to apply this plugin to.</param>
260
+ ///<param name="o">The options supplied to the plugin. Check the defaults object to see all available options.</param>
261
+ ///<param name="id">The id to assign to this instance of the plugin.</param>
262
+
263
+ var ft = this;
264
+ ft.id = id;
265
+ ft.table = t;
266
+ ft.options = o;
267
+ ft.breakpoints = [];
268
+ ft.breakpointNames = '';
269
+ ft.columns = {};
270
+ ft.plugins = w.footable.plugins.load(ft);
271
+
272
+ var opt = ft.options,
273
+ cls = opt.classes,
274
+ evt = opt.events,
275
+ trg = opt.triggers,
276
+ indexOffset = 0;
277
+
278
+ // This object simply houses all the timers used in the FooTable.
279
+ ft.timers = {
280
+ resize: new Timer(),
281
+ register: function (name) {
282
+ ft.timers[name] = new Timer();
283
+ return ft.timers[name];
284
+ }
285
+ };
286
+
287
+ ft.init = function () {
288
+ var $window = $(w), $table = $(ft.table);
289
+
290
+ w.footable.plugins.init(ft);
291
+
292
+ if ($table.hasClass(cls.loaded)) {
293
+ //already loaded FooTable for the table, so don't init again
294
+ ft.raise(evt.alreadyInitialized);
295
+ return;
296
+ }
297
+
298
+ //raise the initializing event
299
+ ft.raise(evt.initializing);
300
+
301
+ $table.addClass(cls.loading);
302
+
303
+ // Get the column data once for the life time of the plugin
304
+ $table.find(opt.columnDataSelector).each(function () {
305
+ var data = ft.getColumnData(this);
306
+ ft.columns[data.index] = data;
307
+ });
308
+
309
+ // Create a nice friendly array to work with out of the breakpoints object.
310
+ for (var name in opt.breakpoints) {
311
+ ft.breakpoints.push({ 'name': name, 'width': opt.breakpoints[name] });
312
+ ft.breakpointNames += (name + ' ');
313
+ }
314
+
315
+ // Sort the breakpoints so the smallest is checked first
316
+ ft.breakpoints.sort(function (a, b) {
317
+ return a['width'] - b['width'];
318
+ });
319
+
320
+ $table
321
+ .unbind(trg.initialize)
322
+ //bind to FooTable initialize trigger
323
+ .bind(trg.initialize, function () {
324
+ //remove previous "state" (to "force" a resize)
325
+ $table.removeData('footable_info');
326
+ $table.data('breakpoint', '');
327
+
328
+ //trigger the FooTable resize
329
+ $table.trigger(trg.resize);
330
+
331
+ //remove the loading class
332
+ $table.removeClass(cls.loading);
333
+
334
+ //add the FooTable and loaded class
335
+ $table.addClass(cls.loaded).addClass(cls.main);
336
+
337
+ //raise the initialized event
338
+ ft.raise(evt.initialized);
339
+ })
340
+ .unbind(trg.redraw)
341
+ //bind to FooTable redraw trigger
342
+ .bind(trg.redraw, function () {
343
+ ft.redraw();
344
+ })
345
+ .unbind(trg.resize)
346
+ //bind to FooTable resize trigger
347
+ .bind(trg.resize, function () {
348
+ ft.resize();
349
+ })
350
+ .unbind(trg.expandFirstRow)
351
+ //bind to FooTable expandFirstRow trigger
352
+ .bind(trg.expandFirstRow, function () {
353
+ $table.find(opt.toggleSelector).first().not('.' + cls.detailShow).trigger(trg.toggleRow);
354
+ })
355
+ .unbind(trg.expandAll)
356
+ //bind to FooTable expandFirstRow trigger
357
+ .bind(trg.expandAll, function () {
358
+ $table.find(opt.toggleSelector).not('.' + cls.detailShow).trigger(trg.toggleRow);
359
+ })
360
+ .unbind(trg.collapseAll)
361
+ //bind to FooTable expandFirstRow trigger
362
+ .bind(trg.collapseAll, function () {
363
+ $table.find('.' + cls.detailShow).trigger(trg.toggleRow);
364
+ });
365
+
366
+ //trigger a FooTable initialize
367
+ $table.trigger(trg.initialize);
368
+
369
+ //bind to window resize
370
+ $window
371
+ .bind('resize.footable', function () {
372
+ ft.timers.resize.stop();
373
+ ft.timers.resize.start(function () {
374
+ ft.raise(trg.resize);
375
+ }, opt.delay);
376
+ });
377
+ };
378
+
379
+ ft.addRowToggle = function () {
380
+ if (!opt.addRowToggle) return;
381
+
382
+ var $table = $(ft.table),
383
+ hasToggleColumn = false;
384
+
385
+ //first remove all toggle spans
386
+ $table.find('span.' + cls.toggle).remove();
387
+
388
+ for (var c in ft.columns) {
389
+ var col = ft.columns[c];
390
+ if (col.toggle) {
391
+ hasToggleColumn = true;
392
+ var selector = '> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > td:nth-child(' + (parseInt(col.index, 10) + 1) + '),' +
393
+ '> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > th:nth-child(' + (parseInt(col.index, 10) + 1) + ')';
394
+ $table.find(selector).not('.' + cls.detailCell).prepend($(opt.toggleHTMLElement).addClass(cls.toggle));
395
+ return;
396
+ }
397
+ }
398
+ //check if we have an toggle column. If not then add it to the first column just to be safe
399
+ if (!hasToggleColumn) {
400
+ $table
401
+ .find('> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > td:first-child')
402
+ .add('> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > th:first-child')
403
+ .not('.' + cls.detailCell)
404
+ .prepend($(opt.toggleHTMLElement).addClass(cls.toggle));
405
+ }
406
+ };
407
+
408
+ ft.setColumnClasses = function () {
409
+ var $table = $(ft.table);
410
+ for (var c in ft.columns) {
411
+ var col = ft.columns[c];
412
+ if (col.className !== null) {
413
+ var selector = '', first = true;
414
+ $.each(col.matches, function (m, match) { //support for colspans
415
+ if (!first) selector += ', ';
416
+ selector += '> tbody > tr:not(.' + cls.detail + ') > td:nth-child(' + (parseInt(match, 10) + 1) + ')';
417
+ first = false;
418
+ });
419
+ //add the className to the cells specified by data-class="blah"
420
+ $table.find(selector).not('.' + cls.detailCell).addClass(col.className);
421
+ }
422
+ }
423
+ };
424
+
425
+ //moved this out into it's own function so that it can be called from other add-ons
426
+ ft.bindToggleSelectors = function () {
427
+ var $table = $(ft.table);
428
+
429
+ if (!ft.hasAnyBreakpointColumn()) return;
430
+
431
+ $table.find(opt.toggleSelector).unbind(trg.toggleRow).bind(trg.toggleRow, function (e) {
432
+ var $row = $(this).is('tr') ? $(this) : $(this).parents('tr:first');
433
+ ft.toggleDetail($row);
434
+ });
435
+
436
+ $table.find(opt.toggleSelector).unbind('click.footable').bind('click.footable', function (e) {
437
+ if ($table.is('.breakpoint') && $(e.target).is('td,th,.'+ cls.toggle)) {
438
+ $(this).trigger(trg.toggleRow);
439
+ }
440
+ });
441
+ };
442
+
443
+ ft.parse = function (cell, column) {
444
+ var parser = opt.parsers[column.type] || opt.parsers.alpha;
445
+ return parser(cell);
446
+ };
447
+
448
+ ft.getColumnData = function (th) {
449
+ var $th = $(th), hide = $th.data('hide'), index = $th.index();
450
+ hide = hide || '';
451
+ hide = jQuery.map(hide.split(','), function (a) {
452
+ return jQuery.trim(a);
453
+ });
454
+ var data = {
455
+ 'index': index,
456
+ 'hide': { },
457
+ 'type': $th.data('type') || 'alpha',
458
+ 'name': $th.data('name') || $.trim($th.text()),
459
+ 'ignore': $th.data('ignore') || false,
460
+ 'toggle': $th.data('toggle') || false,
461
+ 'className': $th.data('class') || null,
462
+ 'matches': [],
463
+ 'names': { },
464
+ 'group': $th.data('group') || null,
465
+ 'groupName': null,
466
+ 'isEditable': $th.data('editable')
467
+ };
468
+
469
+ if (data.group !== null) {
470
+ var $group = $(ft.table).find('> thead > tr.footable-group-row > th[data-group="' + data.group + '"], > thead > tr.footable-group-row > td[data-group="' + data.group + '"]').first();
471
+ data.groupName = ft.parse($group, { 'type': 'alpha' });
472
+ }
473
+
474
+ var pcolspan = parseInt($th.prev().attr('colspan') || 0, 10);
475
+ indexOffset += pcolspan > 1 ? pcolspan - 1 : 0;
476
+ var colspan = parseInt($th.attr('colspan') || 0, 10), curindex = data.index + indexOffset;
477
+ if (colspan > 1) {
478
+ var names = $th.data('names');
479
+ names = names || '';
480
+ names = names.split(',');
481
+ for (var i = 0; i < colspan; i++) {
482
+ data.matches.push(i + curindex);
483
+ if (i < names.length) data.names[i + curindex] = names[i];
484
+ }
485
+ } else {
486
+ data.matches.push(curindex);
487
+ }
488
+
489
+ data.hide['default'] = ($th.data('hide') === "all") || ($.inArray('default', hide) >= 0);
490
+
491
+ var hasBreakpoint = false;
492
+ for (var name in opt.breakpoints) {
493
+ data.hide[name] = ($th.data('hide') === "all") || ($.inArray(name, hide) >= 0);
494
+ hasBreakpoint = hasBreakpoint || data.hide[name];
495
+ }
496
+ data.hasBreakpoint = hasBreakpoint;
497
+ var e = ft.raise(evt.columnData, { 'column': { 'data': data, 'th': th } });
498
+ return e.column.data;
499
+ };
500
+
501
+ ft.getViewportWidth = function () {
502
+ return window.innerWidth || (document.body ? document.body.offsetWidth : 0);
503
+ };
504
+
505
+ ft.calculateWidth = function ($table, info) {
506
+ if (jQuery.isFunction(opt.calculateWidthOverride)) {
507
+ return opt.calculateWidthOverride($table, info);
508
+ }
509
+ if (info.viewportWidth < info.width) info.width = info.viewportWidth;
510
+ if (info.parentWidth < info.width) info.width = info.parentWidth;
511
+ return info;
512
+ };
513
+
514
+ ft.hasBreakpointColumn = function (breakpoint) {
515
+ for (var c in ft.columns) {
516
+ if (ft.columns[c].hide[breakpoint]) {
517
+ if (ft.columns[c].ignore) {
518
+ continue;
519
+ }
520
+ return true;
521
+ }
522
+ }
523
+ return false;
524
+ };
525
+
526
+ ft.hasAnyBreakpointColumn = function () {
527
+ for (var c in ft.columns) {
528
+ if (ft.columns[c].hasBreakpoint) {
529
+ return true;
530
+ }
531
+ }
532
+ return false;
533
+ };
534
+
535
+ ft.resize = function () {
536
+ var $table = $(ft.table);
537
+
538
+ if (!$table.is(':visible')) {
539
+ return;
540
+ } //we only care about FooTables that are visible
541
+
542
+ if (!ft.hasAnyBreakpointColumn()) {
543
+ $table.trigger(trg.redraw);
544
+ return;
545
+ } //we only care about FooTables that have breakpoints
546
+
547
+ var info = {
548
+ 'width': $table.width(), //the table width
549
+ 'viewportWidth': ft.getViewportWidth(), //the width of the viewport
550
+ 'parentWidth': $table.parent().width() //the width of the parent
551
+ };
552
+
553
+ info = ft.calculateWidth($table, info);
554
+
555
+ var pinfo = $table.data('footable_info');
556
+ $table.data('footable_info', info);
557
+ ft.raise(evt.resizing, { 'old': pinfo, 'info': info });
558
+
559
+ // This (if) statement is here purely to make sure events aren't raised twice as mobile safari seems to do
560
+ if (!pinfo || (pinfo && pinfo.width && pinfo.width !== info.width)) {
561
+
562
+ var current = null, breakpoint;
563
+ for (var i = 0; i < ft.breakpoints.length; i++) {
564
+ breakpoint = ft.breakpoints[i];
565
+ if (breakpoint && breakpoint.width && info.width <= breakpoint.width) {
566
+ current = breakpoint;
567
+ break;
568
+ }
569
+ }
570
+
571
+ var breakpointName = (current === null ? 'default' : current['name']),
572
+ hasBreakpointFired = ft.hasBreakpointColumn(breakpointName),
573
+ previousBreakpoint = $table.data('breakpoint');
574
+
575
+ $table
576
+ .data('breakpoint', breakpointName)
577
+ .removeClass('default breakpoint').removeClass(ft.breakpointNames)
578
+ .addClass(breakpointName + (hasBreakpointFired ? ' breakpoint' : ''));
579
+
580
+ //only do something if the breakpoint has changed
581
+ if (breakpointName !== previousBreakpoint) {
582
+ //trigger a redraw
583
+ $table.trigger(trg.redraw);
584
+ //raise a breakpoint event
585
+ ft.raise(evt.breakpoint, { 'breakpoint': breakpointName, 'info': info });
586
+ }
587
+ }
588
+
589
+ ft.raise(evt.resized, { 'old': pinfo, 'info': info });
590
+ };
591
+
592
+ ft.redraw = function () {
593
+ //add the toggler to each row
594
+ ft.addRowToggle();
595
+
596
+ //bind the toggle selector click events
597
+ ft.bindToggleSelectors();
598
+
599
+ //set any cell classes defined for the columns
600
+ ft.setColumnClasses();
601
+
602
+ var $table = $(ft.table),
603
+ breakpointName = $table.data('breakpoint'),
604
+ hasBreakpointFired = ft.hasBreakpointColumn(breakpointName);
605
+
606
+ $table
607
+ .find('> tbody > tr:not(.' + cls.detail + ')').data('detail_created', false).end()
608
+ .find('> thead > tr:last-child > th')
609
+ .each(function () {
610
+ var data = ft.columns[$(this).index()], selector = '', first = true;
611
+ $.each(data.matches, function (m, match) {
612
+ if (!first) {
613
+ selector += ', ';
614
+ }
615
+ var count = match + 1;
616
+ selector += '> tbody > tr:not(.' + cls.detail + ') > td:nth-child(' + count + ')';
617
+ selector += ', > tfoot > tr:not(.' + cls.detail + ') > td:nth-child(' + count + ')';
618
+ selector += ', > colgroup > col:nth-child(' + count + ')';
619
+ first = false;
620
+ });
621
+
622
+ selector += ', > thead > tr[data-group-row="true"] > th[data-group="' + data.group + '"]';
623
+ var $column = $table.find(selector).add(this);
624
+ if (breakpointName !== '') {
625
+ if (data.hide[breakpointName] === false) $column.addClass('footable-visible').show();
626
+ else $column.removeClass('footable-visible').hide();
627
+ }
628
+
629
+ if ($table.find('> thead > tr.footable-group-row').length === 1) {
630
+ var $groupcols = $table.find('> thead > tr:last-child > th[data-group="' + data.group + '"]:visible, > thead > tr:last-child > th[data-group="' + data.group + '"]:visible'),
631
+ $group = $table.find('> thead > tr.footable-group-row > th[data-group="' + data.group + '"], > thead > tr.footable-group-row > td[data-group="' + data.group + '"]'),
632
+ groupspan = 0;
633
+
634
+ $.each($groupcols, function () {
635
+ groupspan += parseInt($(this).attr('colspan') || 1, 10);
636
+ });
637
+
638
+ if (groupspan > 0) $group.attr('colspan', groupspan).show();
639
+ else $group.hide();
640
+ }
641
+ })
642
+ .end()
643
+ .find('> tbody > tr.' + cls.detailShow).each(function () {
644
+ ft.createOrUpdateDetailRow(this);
645
+ });
646
+
647
+ $table.find("[data-bind-name]").each(function () {
648
+ ft.toggleInput(this);
649
+ });
650
+
651
+ $table.find('> tbody > tr.' + cls.detailShow + ':visible').each(function () {
652
+ var $next = $(this).next();
653
+ if ($next.hasClass(cls.detail)) {
654
+ if (!hasBreakpointFired) $next.hide();
655
+ else $next.show();
656
+ }
657
+ });
658
+
659
+ // adding .footable-first-column and .footable-last-column to the first and last th and td of each row in order to allow
660
+ // for styling if the first or last column is hidden (which won't work using :first-child or :last-child)
661
+ $table.find('> thead > tr > th.footable-last-column, > tbody > tr > td.footable-last-column').removeClass('footable-last-column');
662
+ $table.find('> thead > tr > th.footable-first-column, > tbody > tr > td.footable-first-column').removeClass('footable-first-column');
663
+ $table.find('> thead > tr, > tbody > tr')
664
+ .find('> th.footable-visible:last, > td.footable-visible:last')
665
+ .addClass('footable-last-column')
666
+ .end()
667
+ .find('> th.footable-visible:first, > td.footable-visible:first')
668
+ .addClass('footable-first-column');
669
+
670
+ ft.raise(evt.redrawn);
671
+ };
672
+
673
+ ft.toggleDetail = function (row) {
674
+ var $row = (row.jquery) ? row : $(row),
675
+ $next = $row.next();
676
+
677
+ //check if the row is already expanded
678
+ if ($row.hasClass(cls.detailShow)) {
679
+ $row.removeClass(cls.detailShow);
680
+
681
+ //only hide the next row if it's a detail row
682
+ if ($next.hasClass(cls.detail)) $next.hide();
683
+
684
+ ft.raise(evt.rowCollapsed, { 'row': $row[0] });
685
+
686
+ } else {
687
+ ft.createOrUpdateDetailRow($row[0]);
688
+ $row.addClass(cls.detailShow)
689
+ .next().show();
690
+
691
+ ft.raise(evt.rowExpanded, { 'row': $row[0] });
692
+ }
693
+ };
694
+
695
+ ft.removeRow = function (row) {
696
+ var $row = (row.jquery) ? row : $(row);
697
+ if ($row.hasClass(cls.detail)) {
698
+ $row = $row.prev();
699
+ }
700
+ var $next = $row.next();
701
+ if ($row.data('detail_created') === true) {
702
+ //remove the detail row
703
+ $next.remove();
704
+ }
705
+ $row.remove();
706
+
707
+ //raise event
708
+ ft.raise(evt.rowRemoved);
709
+ };
710
+
711
+ ft.appendRow = function (row) {
712
+ var $row = (row.jquery) ? row : $(row);
713
+ $(ft.table).find('tbody').append($row);
714
+
715
+ //redraw the table
716
+ ft.redraw();
717
+ };
718
+
719
+ ft.getColumnFromTdIndex = function (index) {
720
+ /// <summary>Returns the correct column data for the supplied index taking into account colspans.</summary>
721
+ /// <param name="index">The index to retrieve the column data for.</param>
722
+ /// <returns type="json">A JSON object containing the column data for the supplied index.</returns>
723
+ var result = null;
724
+ for (var column in ft.columns) {
725
+ if ($.inArray(index, ft.columns[column].matches) >= 0) {
726
+ result = ft.columns[column];
727
+ break;
728
+ }
729
+ }
730
+ return result;
731
+ };
732
+
733
+ ft.createOrUpdateDetailRow = function (actualRow) {
734
+ var $row = $(actualRow), $next = $row.next(), $detail, values = [];
735
+ if ($row.data('detail_created') === true) return true;
736
+
737
+ if ($row.is(':hidden')) return false; //if the row is hidden for some reason (perhaps filtered) then get out of here
738
+ ft.raise(evt.rowDetailUpdating, { 'row': $row, 'detail': $next });
739
+ $row.find('> td:hidden').each(function () {
740
+ var index = $(this).index(), column = ft.getColumnFromTdIndex(index), name = column.name;
741
+ if (column.ignore === true) return true;
742
+
743
+ if (index in column.names) name = column.names[index];
744
+
745
+ var bindName = $(this).attr("data-bind-name");
746
+ if (bindName != null && $(this).is(':empty')) {
747
+ var bindValue = $('.' + cls.detailInnerValue + '[' + 'data-bind-value="' + bindName + '"]');
748
+ $(this).html($(bindValue).contents().detach());
749
+ }
750
+ var display;
751
+ if (column.isEditable !== false && (column.isEditable || $(this).find(":input").length > 0)) {
752
+ if(bindName == null) {
753
+ bindName = "bind-" + $.now() + "-" + index;
754
+ $(this).attr("data-bind-name", bindName);
755
+ }
756
+ display = $(this).contents().detach();
757
+ }
758
+ if (!display) display = $(this).contents().clone(true, true);
759
+ values.push({ 'name': name, 'value': ft.parse(this, column), 'display': display, 'group': column.group, 'groupName': column.groupName, 'bindName': bindName });
760
+ return true;
761
+ });
762
+ if (values.length === 0) return false; //return if we don't have any data to show
763
+ var colspan = $row.find('> td:visible').length;
764
+ var exists = $next.hasClass(cls.detail);
765
+ if (!exists) { // Create
766
+ $next = $('<tr class="' + cls.detail + '"><td class="' + cls.detailCell + '"><div class="' + cls.detailInner + '"></div></td></tr>');
767
+ $row.after($next);
768
+ }
769
+ $next.find('> td:first').attr('colspan', colspan);
770
+ $detail = $next.find('.' + cls.detailInner).empty();
771
+ opt.createDetail($detail, values, opt.createGroupedDetail, opt.detailSeparator, cls);
772
+ $row.data('detail_created', true);
773
+ ft.raise(evt.rowDetailUpdated, { 'row': $row, 'detail': $next });
774
+ return !exists;
775
+ };
776
+
777
+ ft.raise = function (eventName, args) {
778
+
779
+ if (ft.options.debug === true && $.isFunction(ft.options.log)) ft.options.log(eventName, 'event');
780
+
781
+ args = args || { };
782
+ var def = { 'ft': ft };
783
+ $.extend(true, def, args);
784
+ var e = $.Event(eventName, def);
785
+ if (!e.ft) {
786
+ $.extend(true, e, def);
787
+ } //pre jQuery 1.6 which did not allow data to be passed to event object constructor
788
+ $(ft.table).trigger(e);
789
+ return e;
790
+ };
791
+
792
+ //reset the state of FooTable
793
+ ft.reset = function() {
794
+ var $table = $(ft.table);
795
+ $table.removeData('footable_info')
796
+ .data('breakpoint', '')
797
+ .removeClass(cls.loading)
798
+ .removeClass(cls.loaded);
799
+
800
+ $table.find(opt.toggleSelector).unbind(trg.toggleRow).unbind('click.footable');
801
+
802
+ $table.find('> tbody > tr').removeClass(cls.detailShow);
803
+
804
+ $table.find('> tbody > tr.' + cls.detail).remove();
805
+
806
+ ft.raise(evt.reset);
807
+ };
808
+
809
+ //Switch between row-detail and detail-show.
810
+ ft.toggleInput = function (column) {
811
+ var bindName = $(column).attr("data-bind-name");
812
+ if(bindName != null) {
813
+ var bindValue = $('.' + cls.detailInnerValue + '[' + 'data-bind-value="' + bindName + '"]');
814
+ if(bindValue != null) {
815
+ if($(column).is(":visible")) {
816
+ if(!$(bindValue).is(':empty')) $(column).html($(bindValue).contents().detach());
817
+ } else if(!$(column).is(':empty')) {
818
+ $(bindValue).html($(column).contents().detach());
819
+ }
820
+ }
821
+ }
822
+ };
823
+
824
+ ft.init();
825
+ return ft;
826
+ }
827
+ })(jQuery, window);