|
1 YUI.add('datatable-base', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 A Widget for displaying tabular data. The base implementation of DataTable |
|
5 provides the ability to dynamically generate an HTML table from a set of column |
|
6 configurations and row data. |
|
7 |
|
8 Two classes are included in the `datatable-base` module: `Y.DataTable` and |
|
9 `Y.DataTable.Base`. |
|
10 |
|
11 @module datatable |
|
12 @submodule datatable-base |
|
13 @main datatable |
|
14 @since 3.5.0 |
|
15 **/ |
|
16 |
|
17 // DataTable API docs included before DataTable.Base to make yuidoc work |
|
18 /** |
|
19 A Widget for displaying tabular data. Before feature modules are `use()`d, |
|
20 this class is functionally equivalent to DataTable.Base. However, feature |
|
21 modules can modify this class in non-destructive ways, expanding the API and |
|
22 functionality. |
|
23 |
|
24 This is the primary DataTable class. Out of the box, it provides the ability |
|
25 to dynamically generate an HTML table from a set of column configurations and |
|
26 row data. But feature module inclusion can add table sorting, pagintaion, |
|
27 highlighting, selection, and more. |
|
28 |
|
29 <pre><code> |
|
30 // The functionality of this table would require additional modules be use()d, |
|
31 // but the feature APIs are aggregated onto Y.DataTable. |
|
32 // (Snippet is for illustration. Not all features are available today.) |
|
33 var table = new Y.DataTable({ |
|
34 columns: [ |
|
35 { type: 'checkbox', defaultChecked: true }, |
|
36 { key: 'firstName', sortable: true, resizable: true }, |
|
37 { key: 'lastName', sortable: true }, |
|
38 { key: 'role', formatter: toRoleName } |
|
39 ], |
|
40 data: { |
|
41 source: 'http://myserver.com/service/json', |
|
42 type: 'json', |
|
43 schema: { |
|
44 resultListLocator: 'results.users', |
|
45 fields: [ |
|
46 'username', |
|
47 'firstName', |
|
48 'lastName', |
|
49 { key: 'role', type: 'number' } |
|
50 ] |
|
51 } |
|
52 }, |
|
53 recordType: UserModel, |
|
54 pagedData: { |
|
55 location: 'footer', |
|
56 pageSizes: [20, 50, 'all'], |
|
57 rowsPerPage: 20, |
|
58 pageLinks: 5 |
|
59 }, |
|
60 editable: true |
|
61 }); |
|
62 </code></pre> |
|
63 |
|
64 ### Column Configuration |
|
65 |
|
66 The column configurations are set in the form of an array of objects, where |
|
67 each object corresponds to a column. For columns populated directly from the |
|
68 row data, a 'key' property is required to bind the column to that property or |
|
69 attribute in the row data. |
|
70 |
|
71 Not all columns need to relate to row data, nor do all properties or attributes |
|
72 of the row data need to have a corresponding column. However, only those |
|
73 columns included in the `columns` configuration attribute will be rendered. |
|
74 |
|
75 Other column configuration properties are supported by the configured |
|
76 `view`, class as well as any features added by plugins or class extensions. |
|
77 See the description of DataTable.TableView and its subviews |
|
78 DataTable.HeaderView, DataTable.BodyView, and DataTable.FooterView (and other |
|
79 DataTable feature classes) to see what column properties they support. |
|
80 |
|
81 Some examples of column configurations would be: |
|
82 |
|
83 <pre><code> |
|
84 // Basic |
|
85 var columns = [{ key: 'firstName' }, { key: 'lastName' }, { key: 'age' }]; |
|
86 |
|
87 // For columns without any additional configuration, strings can be used |
|
88 var columns = ['firstName', 'lastName', 'age']; |
|
89 |
|
90 // Multi-row column headers (see DataTable.HeaderView for details) |
|
91 var columns = [ |
|
92 { |
|
93 label: 'Name', |
|
94 children: [ |
|
95 { key: 'firstName' }, |
|
96 { key: 'lastName' } |
|
97 ] |
|
98 }, |
|
99 'age' // mixing and matching objects and strings is ok |
|
100 ]; |
|
101 |
|
102 // Including columns that are not related 1:1 to row data fields/attributes |
|
103 // (See DataTable.BodyView for details) |
|
104 var columns = [ |
|
105 { |
|
106 label: 'Name', // Needed for the column header |
|
107 formatter: function (o) { |
|
108 // Fill the column cells with data from firstName and lastName |
|
109 if (o.data.age > 55) { |
|
110 o.className += ' senior'; |
|
111 } |
|
112 return o.data.lastName + ', ' + o.data.firstName; |
|
113 } |
|
114 }, |
|
115 'age' |
|
116 ]; |
|
117 |
|
118 // Columns that include feature configurations (for illustration; not all |
|
119 // features are available today). |
|
120 var columns = [ |
|
121 { type: 'checkbox', defaultChecked: true }, |
|
122 { key: 'firstName', sortable: true, resizable: true, min-width: '300px' }, |
|
123 { key: 'lastName', sortable: true, resizable: true, min-width: '300px' }, |
|
124 { key: 'age', emptyCellValue: '<em>unknown</em>' } |
|
125 ]; |
|
126 </code></pre> |
|
127 |
|
128 ### Row Data Configuration |
|
129 |
|
130 The `data` configuration attribute is responsible for housing the data objects |
|
131 that will be rendered as rows. You can provide this information in two ways by default: |
|
132 |
|
133 1. An array of simple objects with key:value pairs |
|
134 2. A ModelList of Base-based class instances (presumably Model subclass |
|
135 instances) |
|
136 |
|
137 If an array of objects is passed, it will be translated into a ModelList filled |
|
138 with instances of the class provided to the `recordType` attribute. This |
|
139 attribute can also create a custom Model subclass from an array of field names |
|
140 or an object of attribute configurations. If no `recordType` is provided, one |
|
141 will be created for you from available information (see `_initRecordType`). |
|
142 Providing either your own ModelList instance for `data`, or at least Model |
|
143 class for `recordType`, is the best way to control client-server |
|
144 synchronization when modifying data on the client side. |
|
145 |
|
146 The ModelList instance that manages the table's data is available in the `data` |
|
147 property on the DataTable instance. |
|
148 |
|
149 |
|
150 ### Rendering |
|
151 |
|
152 Table rendering is a collaborative process between the DataTable and its |
|
153 configured `view`. The DataTable creates an instance of the configured `view` |
|
154 (DataTable.TableView by default), and calls its `render()` method. |
|
155 DataTable.TableView, for instance, then creates the `<table>` and `<caption>`, |
|
156 then delegates the rendering of the specific sections of the table to subviews, |
|
157 which can be configured as `headerView`, `bodyView`, and `footerView`. |
|
158 DataTable.TableView defaults the `headerView` to DataTable.HeaderView and the |
|
159 `bodyView` to DataTable.BodyView, but leaves the `footerView` unassigned. |
|
160 Setting any subview to `null` will result in that table section not being |
|
161 rendered. |
|
162 |
|
163 @class DataTable |
|
164 @extends DataTable.Base |
|
165 @since 3.5.0 |
|
166 **/ |
|
167 |
|
168 // DataTable API docs included before DataTable.Base to make yuidoc work |
|
169 /** |
|
170 The baseline implementation of a DataTable. This class should be used |
|
171 primarily as a superclass for a custom DataTable with a specific set of |
|
172 features. Because features can be composed onto `Y.DataTable`, custom |
|
173 subclasses of DataTable.Base will remain unmodified when new feature modules |
|
174 are loaded. |
|
175 |
|
176 Example usage might look like this: |
|
177 |
|
178 <pre><code> |
|
179 // Custom subclass with only sorting and mutability added. If other datatable |
|
180 // feature modules are loaded, this class will not be affected. |
|
181 var MyTableClass = Y.Base.create('table', Y.DataTable.Base, |
|
182 [ Y.DataTable.Sortable, Y.DataTable.Mutable ]); |
|
183 |
|
184 var table = new MyTableClass({ |
|
185 columns: ['firstName', 'lastName', 'age'], |
|
186 data: [ |
|
187 { firstName: 'Frank', lastName: 'Zappa', age: 71 }, |
|
188 { firstName: 'Frank', lastName: 'Lloyd Wright', age: 144 }, |
|
189 { firstName: 'Albert', lastName: 'Einstein', age: 132 }, |
|
190 ... |
|
191 ] |
|
192 }); |
|
193 |
|
194 table.render('#over-there'); |
|
195 |
|
196 // DataTable.Base can be instantiated if a featureless table is needed. |
|
197 var table = new Y.DataTable.Base({ |
|
198 columns: ['firstName', 'lastName', 'age'], |
|
199 data: [ |
|
200 { firstName: 'Frank', lastName: 'Zappa', age: 71 }, |
|
201 { firstName: 'Frank', lastName: 'Lloyd Wright', age: 144 }, |
|
202 { firstName: 'Albert', lastName: 'Einstein', age: 132 }, |
|
203 ... |
|
204 ] |
|
205 }); |
|
206 |
|
207 table.render('#in-here'); |
|
208 </code></pre> |
|
209 |
|
210 DataTable.Base is built from DataTable.Core, and sets the default `view` |
|
211 to `Y.DataTable.TableView`. |
|
212 |
|
213 @class Base |
|
214 @extends Widget |
|
215 @uses DataTable.Core |
|
216 @namespace DataTable |
|
217 @since 3.5.0 |
|
218 **/ |
|
219 Y.DataTable.Base = Y.Base.create('datatable', Y.Widget, [Y.DataTable.Core], { |
|
220 |
|
221 /** |
|
222 Pass through to `delegate()` called from the `contentBox`. |
|
223 |
|
224 @method delegate |
|
225 @param type {String} the event type to delegate |
|
226 @param fn {Function} the callback function to execute. This function |
|
227 will be provided the event object for the delegated event. |
|
228 @param spec {String|Function} a selector that must match the target of the |
|
229 event or a function to test target and its parents for a match |
|
230 @param context {Object} optional argument that specifies what 'this' refers to |
|
231 @param args* {any} 0..n additional arguments to pass on to the callback |
|
232 function. These arguments will be added after the event object. |
|
233 @return {EventHandle} the detach handle |
|
234 @since 3.5.0 |
|
235 **/ |
|
236 delegate: function () { |
|
237 var contentBox = this.get('contentBox'); |
|
238 |
|
239 return contentBox.delegate.apply(contentBox, arguments); |
|
240 }, |
|
241 |
|
242 /** |
|
243 Destroys the table `View` if it's been created. |
|
244 |
|
245 @method destructor |
|
246 @protected |
|
247 @since 3.6.0 |
|
248 **/ |
|
249 destructor: function () { |
|
250 if (this.view) { |
|
251 this.view.destroy(); |
|
252 } |
|
253 }, |
|
254 |
|
255 /** |
|
256 Returns the `<td>` Node from the given row and column index. Alternately, |
|
257 the `seed` can be a Node. If so, the nearest ancestor cell is returned. |
|
258 If the `seed` is a cell, it is returned. If there is no cell at the given |
|
259 coordinates, `null` is returned. |
|
260 |
|
261 Optionally, include an offset array or string to return a cell near the |
|
262 cell identified by the `seed`. The offset can be an array containing the |
|
263 number of rows to shift followed by the number of columns to shift, or one |
|
264 of "above", "below", "next", or "previous". |
|
265 |
|
266 <pre><code>// Previous cell in the previous row |
|
267 var cell = table.getCell(e.target, [-1, -1]); |
|
268 |
|
269 // Next cell |
|
270 var cell = table.getCell(e.target, 'next'); |
|
271 var cell = table.getCell(e.taregt, [0, 1];</pre></code> |
|
272 |
|
273 This is actually just a pass through to the `view` instance's method |
|
274 by the same name. |
|
275 |
|
276 @method getCell |
|
277 @param {Number[]|Node} seed Array of row and column indexes, or a Node that |
|
278 is either the cell itself or a descendant of one. |
|
279 @param {Number[]|String} [shift] Offset by which to identify the returned |
|
280 cell Node |
|
281 @return {Node} |
|
282 @since 3.5.0 |
|
283 **/ |
|
284 getCell: function (/* seed, shift */) { |
|
285 return this.view && this.view.getCell && |
|
286 this.view.getCell.apply(this.view, arguments); |
|
287 }, |
|
288 |
|
289 /** |
|
290 Returns the `<tr>` Node from the given row index, Model, or Model's |
|
291 `clientId`. If the rows haven't been rendered yet, or if the row can't be |
|
292 found by the input, `null` is returned. |
|
293 |
|
294 This is actually just a pass through to the `view` instance's method |
|
295 by the same name. |
|
296 |
|
297 @method getRow |
|
298 @param {Number|String|Model} id Row index, Model instance, or clientId |
|
299 @return {Node} |
|
300 @since 3.5.0 |
|
301 **/ |
|
302 getRow: function (/* id */) { |
|
303 return this.view && this.view.getRow && |
|
304 this.view.getRow.apply(this.view, arguments); |
|
305 }, |
|
306 |
|
307 /** |
|
308 Updates the `_displayColumns` property. |
|
309 |
|
310 @method _afterDisplayColumnsChange |
|
311 @param {EventFacade} e The `columnsChange` event |
|
312 @protected |
|
313 @since 3.6.0 |
|
314 **/ |
|
315 // FIXME: This is a kludge for back compat with features that reference |
|
316 // _displayColumns. They should be updated to TableView plugins. |
|
317 _afterDisplayColumnsChange: function (e) { |
|
318 this._extractDisplayColumns(e.newVal || []); |
|
319 }, |
|
320 |
|
321 /** |
|
322 Attaches subscriptions to relay core change events to the view. |
|
323 |
|
324 @method bindUI |
|
325 @protected |
|
326 @since 3.6.0 |
|
327 **/ |
|
328 bindUI: function () { |
|
329 this._eventHandles.relayCoreChanges = this.after( |
|
330 ['columnsChange', |
|
331 'dataChange', |
|
332 'summaryChange', |
|
333 'captionChange', |
|
334 'widthChange'], |
|
335 Y.bind('_relayCoreAttrChange', this)); |
|
336 }, |
|
337 |
|
338 /** |
|
339 The default behavior of the `renderView` event. Calls `render()` on the |
|
340 `View` instance on the event. |
|
341 |
|
342 @method _defRenderViewFn |
|
343 @param {EventFacade} e The `renderView` event |
|
344 @protected |
|
345 **/ |
|
346 _defRenderViewFn: function (e) { |
|
347 e.view.render(); |
|
348 }, |
|
349 |
|
350 /** |
|
351 Processes the full column array, distilling the columns down to those that |
|
352 correspond to cell data columns. |
|
353 |
|
354 @method _extractDisplayColumns |
|
355 @param {Object[]} columns The full set of table columns |
|
356 @protected |
|
357 **/ |
|
358 // FIXME: this is a kludge for back compat, duplicating logic in the |
|
359 // tableView |
|
360 _extractDisplayColumns: function (columns) { |
|
361 var displayColumns = []; |
|
362 |
|
363 function process(cols) { |
|
364 var i, len, col; |
|
365 |
|
366 for (i = 0, len = cols.length; i < len; ++i) { |
|
367 col = cols[i]; |
|
368 |
|
369 if (Y.Lang.isArray(col.children)) { |
|
370 process(col.children); |
|
371 } else { |
|
372 displayColumns.push(col); |
|
373 } |
|
374 } |
|
375 } |
|
376 |
|
377 process(columns); |
|
378 |
|
379 /** |
|
380 Array of the columns that correspond to those with value cells in the |
|
381 data rows. Excludes colspan header columns (configured with `children`). |
|
382 |
|
383 @property _displayColumns |
|
384 @type {Object[]} |
|
385 @since 3.5.0 |
|
386 **/ |
|
387 this._displayColumns = displayColumns; |
|
388 }, |
|
389 |
|
390 /** |
|
391 Sets up the instance's events. |
|
392 |
|
393 @method initializer |
|
394 @param {Object} [config] Configuration object passed at construction |
|
395 @protected |
|
396 @since 3.6.0 |
|
397 **/ |
|
398 initializer: function () { |
|
399 this.publish('renderView', { |
|
400 defaultFn: Y.bind('_defRenderViewFn', this) |
|
401 }); |
|
402 |
|
403 // Have to use get('columns'), not config.columns because the setter |
|
404 // needs to transform string columns to objects. |
|
405 this._extractDisplayColumns(this.get('columns') || []); |
|
406 |
|
407 // FIXME: kludge for back compat of features that reference |
|
408 // _displayColumns on the instance. They need to be updated to |
|
409 // TableView plugins, most likely. |
|
410 this.after('columnsChange', Y.bind('_afterDisplayColumnsChange', this)); |
|
411 }, |
|
412 |
|
413 /** |
|
414 Relays attribute changes to the instance's `view`. |
|
415 |
|
416 @method _relayCoreAttrChange |
|
417 @param {EventFacade} e The change event |
|
418 @protected |
|
419 @since 3.6.0 |
|
420 **/ |
|
421 _relayCoreAttrChange: function (e) { |
|
422 var attr = (e.attrName === 'data') ? 'modelList' : e.attrName; |
|
423 |
|
424 this.view.set(attr, e.newVal); |
|
425 }, |
|
426 |
|
427 /** |
|
428 Instantiates the configured `view` class that will be responsible for |
|
429 setting up the View class. |
|
430 |
|
431 @method @renderUI |
|
432 @protected |
|
433 @since 3.6.0 |
|
434 **/ |
|
435 renderUI: function () { |
|
436 var self = this, |
|
437 View = this.get('view'); |
|
438 |
|
439 if (View) { |
|
440 this.view = new View( |
|
441 Y.merge( |
|
442 this.getAttrs(), |
|
443 { |
|
444 host : this, |
|
445 container: this.get('contentBox'), |
|
446 modelList: this.data |
|
447 }, |
|
448 this.get('viewConfig'))); |
|
449 |
|
450 // For back compat, share the view instances and primary nodes |
|
451 // on this instance. |
|
452 // TODO: Remove this? |
|
453 if (!this._eventHandles.legacyFeatureProps) { |
|
454 this._eventHandles.legacyFeatureProps = this.view.after({ |
|
455 renderHeader: function (e) { |
|
456 self.head = e.view; |
|
457 self._theadNode = e.view.theadNode; |
|
458 // TODO: clean up the repetition. |
|
459 // This is here so that subscribers to renderHeader etc |
|
460 // have access to this._tableNode from the DT instance |
|
461 self._tableNode = e.view.get('container'); |
|
462 }, |
|
463 renderFooter: function (e) { |
|
464 self.foot = e.view; |
|
465 self._tfootNode = e.view.tfootNode; |
|
466 self._tableNode = e.view.get('container'); |
|
467 }, |
|
468 renderBody: function (e) { |
|
469 self.body = e.view; |
|
470 self._tbodyNode = e.view.tbodyNode; |
|
471 self._tableNode = e.view.get('container'); |
|
472 }, |
|
473 // FIXME: guarantee that the properties are available, even |
|
474 // if the configured (or omitted) views don't create them |
|
475 renderTable: function () { |
|
476 var contentBox = this.get('container'); |
|
477 |
|
478 self._tableNode = this.tableNode || |
|
479 contentBox.one('.' + this.getClassName('table') + |
|
480 ', table'); |
|
481 |
|
482 // FIXME: _captionNode isn't available until after |
|
483 // renderTable unless in the renderX subs I look for |
|
484 // it under the container's parentNode (to account for |
|
485 // scroll breaking out the caption table). |
|
486 self._captionNode = this.captionNode || |
|
487 contentBox.one('caption'); |
|
488 |
|
489 if (!self._theadNode) { |
|
490 self._theadNode = contentBox.one( |
|
491 '.' + this.getClassName('columns') + ', thead'); |
|
492 } |
|
493 |
|
494 if (!self._tbodyNode) { |
|
495 self._tbodyNode = contentBox.one( |
|
496 '.' + this.getClassName('data') + ', tbody'); |
|
497 } |
|
498 |
|
499 if (!self._tfootNode) { |
|
500 self._tfootNode = contentBox.one( |
|
501 '.' + this.getClassName('footer') + ', tfoot'); |
|
502 } |
|
503 } |
|
504 }); |
|
505 } |
|
506 |
|
507 // To *somewhat* preserve table.on('renderHeader', fn) in the |
|
508 // form of table.on('table:renderHeader', fn), because I couldn't |
|
509 // figure out another option. |
|
510 this.view.addTarget(this); |
|
511 } |
|
512 }, |
|
513 |
|
514 /** |
|
515 Fires the `renderView` event, delegating UI updates to the configured View. |
|
516 |
|
517 @method syncUI |
|
518 @since 3.5.0 |
|
519 **/ |
|
520 syncUI: function () { |
|
521 if (this.view) { |
|
522 this.fire('renderView', { view: this.view }); |
|
523 } |
|
524 }, |
|
525 |
|
526 /** |
|
527 Verifies the input value is a function with a `render` method on its |
|
528 prototype. `null` is also accepted to remove the default View. |
|
529 |
|
530 @method _validateView |
|
531 @protected |
|
532 @since 3.5.0 |
|
533 **/ |
|
534 _validateView: function (val) { |
|
535 // TODO support View instances? |
|
536 return val === null || (Y.Lang.isFunction(val) && val.prototype.render); |
|
537 } |
|
538 }, { |
|
539 ATTRS: { |
|
540 /** |
|
541 The View class used to render the `<table>` into the Widget's |
|
542 `contentBox`. This View can handle the entire table rendering itself |
|
543 or delegate to other Views. |
|
544 |
|
545 It is not strictly necessary that the class function assigned here be |
|
546 a View subclass. It must however have a `render()` method. |
|
547 |
|
548 When the DataTable is rendered, an instance of this View will be |
|
549 created and its `render()` method called. The View instance will be |
|
550 assigned to the DataTable instance's `view` property. |
|
551 |
|
552 @attribute view |
|
553 @type {Function} |
|
554 @default Y.DataTable.TableView |
|
555 @since 3.6.0 |
|
556 **/ |
|
557 view: { |
|
558 value: Y.DataTable.TableView, |
|
559 validator: '_validateView' |
|
560 }, |
|
561 |
|
562 /** |
|
563 Configuration object passed to the class constructor in `view` |
|
564 during render. |
|
565 |
|
566 @attribute viewConfig |
|
567 @type {Object} |
|
568 @default undefined (initially unset) |
|
569 @protected |
|
570 @since 3.6.0 |
|
571 **/ |
|
572 viewConfig: {} |
|
573 |
|
574 /** |
|
575 If the View class assigned to the DataTable's `view` attribute supports |
|
576 it, this class will be used for rendering the contents of the |
|
577 `<thead>`—the column headers for the table. |
|
578 |
|
579 Similar to `view`, the instance of this View will be assigned to the |
|
580 DataTable instance's `head` property. |
|
581 |
|
582 It is not strictly necessary that the class function assigned here be |
|
583 a View subclass. It must however have a `render()` method. |
|
584 |
|
585 @attribute headerView |
|
586 @type {Function|Object} |
|
587 @default Y.DataTable.HeaderView |
|
588 @since 3.5.0 |
|
589 **/ |
|
590 /* |
|
591 headerView: { |
|
592 value: Y.DataTable.HeaderView, |
|
593 validator: '_validateView' |
|
594 }, |
|
595 */ |
|
596 |
|
597 /** |
|
598 Configuration object passed to the class constructor in `headerView` |
|
599 during render. |
|
600 |
|
601 @attribute headerConfig |
|
602 @type {Object} |
|
603 @default undefined (initially unset) |
|
604 @protected |
|
605 @since 3.6.0 |
|
606 **/ |
|
607 //headConfig: {}, |
|
608 |
|
609 /** |
|
610 If the View class assigned to the DataTable's `view` attribute supports |
|
611 it, this class will be used for rendering the contents of the `<tfoot>`. |
|
612 |
|
613 Similar to `view`, the instance of this View will be assigned to the |
|
614 DataTable instance's `foot` property. |
|
615 |
|
616 It is not strictly necessary that the class function assigned here be |
|
617 a View subclass. It must however have a `render()` method. |
|
618 |
|
619 @attribute footerView |
|
620 @type {Function|Object} |
|
621 @since 3.5.0 |
|
622 **/ |
|
623 /* |
|
624 footerView: { |
|
625 validator: '_validateView' |
|
626 }, |
|
627 */ |
|
628 |
|
629 /** |
|
630 Configuration object passed to the class constructor in `footerView` |
|
631 during render. |
|
632 |
|
633 @attribute footerConfig |
|
634 @type {Object} |
|
635 @default undefined (initially unset) |
|
636 @protected |
|
637 @since 3.6.0 |
|
638 **/ |
|
639 //footerConfig: {}, |
|
640 |
|
641 /** |
|
642 If the View class assigned to the DataTable's `view` attribute supports |
|
643 it, this class will be used for rendering the contents of the `<tbody>` |
|
644 including all data rows. |
|
645 |
|
646 Similar to `view`, the instance of this View will be assigned to the |
|
647 DataTable instance's `body` property. |
|
648 |
|
649 It is not strictly necessary that the class function assigned here be |
|
650 a View subclass. It must however have a `render()` method. |
|
651 |
|
652 @attribute bodyView |
|
653 @type {Function} |
|
654 @default Y.DataTable.BodyView |
|
655 @since 3.5.0 |
|
656 **/ |
|
657 /* |
|
658 bodyView: { |
|
659 value: Y.DataTable.BodyView, |
|
660 validator: '_validateView' |
|
661 }, |
|
662 */ |
|
663 |
|
664 /** |
|
665 Configuration object passed to the class constructor in `bodyView` |
|
666 during render. |
|
667 |
|
668 @attribute bodyConfig |
|
669 @type {Object} |
|
670 @default undefined (initially unset) |
|
671 @protected |
|
672 @since 3.6.0 |
|
673 **/ |
|
674 //bodyConfig: {} |
|
675 } |
|
676 }); |
|
677 |
|
678 // The DataTable API docs are above DataTable.Base docs. |
|
679 Y.DataTable = Y.mix( |
|
680 Y.Base.create('datatable', Y.DataTable.Base, []), // Create the class |
|
681 Y.DataTable); // Migrate static and namespaced classes |
|
682 |
|
683 |
|
684 }, '@VERSION@', { |
|
685 "requires": [ |
|
686 "datatable-core", |
|
687 "datatable-table", |
|
688 "datatable-head", |
|
689 "datatable-body", |
|
690 "base-build", |
|
691 "widget" |
|
692 ], |
|
693 "skinnable": true |
|
694 }); |