|
1 YUI.add('datatable-table', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 View class responsible for rendering a `<table>` from provided data. Used as |
|
5 the default `view` for `Y.DataTable.Base` and `Y.DataTable` classes. |
|
6 |
|
7 @module datatable |
|
8 @submodule datatable-table |
|
9 @since 3.6.0 |
|
10 **/ |
|
11 var toArray = Y.Array, |
|
12 YLang = Y.Lang, |
|
13 fromTemplate = YLang.sub, |
|
14 |
|
15 isArray = YLang.isArray, |
|
16 isFunction = YLang.isFunction; |
|
17 |
|
18 /** |
|
19 View class responsible for rendering a `<table>` from provided data. Used as |
|
20 the default `view` for `Y.DataTable.Base` and `Y.DataTable` classes. |
|
21 |
|
22 |
|
23 |
|
24 @class TableView |
|
25 @namespace DataTable |
|
26 @extends View |
|
27 @since 3.6.0 |
|
28 **/ |
|
29 Y.namespace('DataTable').TableView = Y.Base.create('table', Y.View, [], { |
|
30 |
|
31 /** |
|
32 The HTML template used to create the caption Node if the `caption` |
|
33 attribute is set. |
|
34 |
|
35 @property CAPTION_TEMPLATE |
|
36 @type {String} |
|
37 @default '<caption class="{className}"/>' |
|
38 @since 3.6.0 |
|
39 **/ |
|
40 CAPTION_TEMPLATE: '<caption class="{className}"/>', |
|
41 |
|
42 /** |
|
43 The HTML template used to create the table Node. |
|
44 |
|
45 @property TABLE_TEMPLATE |
|
46 @type {String} |
|
47 @default '<table cellspacing="0" class="{className}"/>' |
|
48 @since 3.6.0 |
|
49 **/ |
|
50 TABLE_TEMPLATE : '<table cellspacing="0" class="{className}"/>', |
|
51 |
|
52 /** |
|
53 The object or instance of the class assigned to `bodyView` that is |
|
54 responsible for rendering and managing the table's `<tbody>`(s) and its |
|
55 content. |
|
56 |
|
57 @property body |
|
58 @type {Object} |
|
59 @default undefined (initially unset) |
|
60 @since 3.5.0 |
|
61 **/ |
|
62 //body: null, |
|
63 |
|
64 /** |
|
65 The object or instance of the class assigned to `footerView` that is |
|
66 responsible for rendering and managing the table's `<tfoot>` and its |
|
67 content. |
|
68 |
|
69 @property foot |
|
70 @type {Object} |
|
71 @default undefined (initially unset) |
|
72 @since 3.5.0 |
|
73 **/ |
|
74 //foot: null, |
|
75 |
|
76 /** |
|
77 The object or instance of the class assigned to `headerView` that is |
|
78 responsible for rendering and managing the table's `<thead>` and its |
|
79 content. |
|
80 |
|
81 @property head |
|
82 @type {Object} |
|
83 @default undefined (initially unset) |
|
84 @since 3.5.0 |
|
85 **/ |
|
86 //head: null, |
|
87 |
|
88 //-----------------------------------------------------------------------// |
|
89 // Public methods |
|
90 //-----------------------------------------------------------------------// |
|
91 |
|
92 /** |
|
93 Returns the `<td>` Node from the given row and column index. Alternately, |
|
94 the `seed` can be a Node. If so, the nearest ancestor cell is returned. |
|
95 If the `seed` is a cell, it is returned. If there is no cell at the given |
|
96 coordinates, `null` is returned. |
|
97 |
|
98 Optionally, include an offset array or string to return a cell near the |
|
99 cell identified by the `seed`. The offset can be an array containing the |
|
100 number of rows to shift followed by the number of columns to shift, or one |
|
101 of "above", "below", "next", or "previous". |
|
102 |
|
103 <pre><code>// Previous cell in the previous row |
|
104 var cell = table.getCell(e.target, [-1, -1]); |
|
105 |
|
106 // Next cell |
|
107 var cell = table.getCell(e.target, 'next'); |
|
108 var cell = table.getCell(e.taregt, [0, 1];</pre></code> |
|
109 |
|
110 This is actually just a pass through to the `bodyView` instance's method |
|
111 by the same name. |
|
112 |
|
113 @method getCell |
|
114 @param {Number[]|Node} seed Array of row and column indexes, or a Node that |
|
115 is either the cell itself or a descendant of one. |
|
116 @param {Number[]|String} [shift] Offset by which to identify the returned |
|
117 cell Node |
|
118 @return {Node} |
|
119 @since 3.5.0 |
|
120 **/ |
|
121 getCell: function (/* seed, shift */) { |
|
122 return this.body && this.body.getCell && |
|
123 this.body.getCell.apply(this.body, arguments); |
|
124 }, |
|
125 |
|
126 /** |
|
127 Returns the generated CSS classname based on the input. If the `host` |
|
128 attribute is configured, it will attempt to relay to its `getClassName` |
|
129 or use its static `NAME` property as a string base. |
|
130 |
|
131 If `host` is absent or has neither method nor `NAME`, a CSS classname |
|
132 will be generated using this class's `NAME`. |
|
133 |
|
134 @method getClassName |
|
135 @param {String} token* Any number of token strings to assemble the |
|
136 classname from. |
|
137 @return {String} |
|
138 @protected |
|
139 **/ |
|
140 getClassName: function () { |
|
141 // TODO: add attr with setter for host? |
|
142 var host = this.host, |
|
143 NAME = (host && host.constructor.NAME) || |
|
144 this.constructor.NAME; |
|
145 |
|
146 if (host && host.getClassName) { |
|
147 return host.getClassName.apply(host, arguments); |
|
148 } else { |
|
149 return Y.ClassNameManager.getClassName |
|
150 .apply(Y.ClassNameManager, |
|
151 [NAME].concat(toArray(arguments, 0, true))); |
|
152 } |
|
153 }, |
|
154 |
|
155 /** |
|
156 Relays call to the `bodyView`'s `getRecord` method if it has one. |
|
157 |
|
158 @method getRecord |
|
159 @param {String|Node} seed Node or identifier for a row or child element |
|
160 @return {Model} |
|
161 @since 3.6.0 |
|
162 **/ |
|
163 getRecord: function () { |
|
164 return this.body && this.body.getRecord && |
|
165 this.body.getRecord.apply(this.body, arguments); |
|
166 }, |
|
167 |
|
168 /** |
|
169 Returns the `<tr>` Node from the given row index, Model, or Model's |
|
170 `clientId`. If the rows haven't been rendered yet, or if the row can't be |
|
171 found by the input, `null` is returned. |
|
172 |
|
173 This is actually just a pass through to the `bodyView` instance's method |
|
174 by the same name. |
|
175 |
|
176 @method getRow |
|
177 @param {Number|String|Model} id Row index, Model instance, or clientId |
|
178 @return {Node} |
|
179 @since 3.5.0 |
|
180 **/ |
|
181 getRow: function (/* id */) { |
|
182 return this.body && this.body.getRow && |
|
183 this.body.getRow.apply(this.body, arguments); |
|
184 }, |
|
185 |
|
186 |
|
187 //-----------------------------------------------------------------------// |
|
188 // Protected and private methods |
|
189 //-----------------------------------------------------------------------// |
|
190 /** |
|
191 Updates the table's `summary` attribute. |
|
192 |
|
193 @method _afterSummaryChange |
|
194 @param {EventHandle} e The change event |
|
195 @protected |
|
196 @since 3.6.0 |
|
197 **/ |
|
198 _afterSummaryChange: function (e) { |
|
199 this._uiSetSummary(e.newVal); |
|
200 }, |
|
201 |
|
202 /** |
|
203 Updates the table's `<caption>`. |
|
204 |
|
205 @method _afterCaptionChange |
|
206 @param {EventHandle} e The change event |
|
207 @protected |
|
208 @since 3.6.0 |
|
209 **/ |
|
210 _afterCaptionChange: function (e) { |
|
211 this._uiSetCaption(e.newVal); |
|
212 }, |
|
213 |
|
214 /** |
|
215 Updates the table's width. |
|
216 |
|
217 @method _afterWidthChange |
|
218 @param {EventHandle} e The change event |
|
219 @protected |
|
220 @since 3.6.0 |
|
221 **/ |
|
222 _afterWidthChange: function (e) { |
|
223 this._uiSetWidth(e.newVal); |
|
224 }, |
|
225 |
|
226 /** |
|
227 Attaches event subscriptions to relay attribute changes to the child Views. |
|
228 |
|
229 @method _bindUI |
|
230 @protected |
|
231 @since 3.6.0 |
|
232 **/ |
|
233 _bindUI: function () { |
|
234 var relay; |
|
235 |
|
236 if (!this._eventHandles) { |
|
237 relay = Y.bind('_relayAttrChange', this); |
|
238 |
|
239 this._eventHandles = this.after({ |
|
240 columnsChange : relay, |
|
241 modelListChange: relay, |
|
242 summaryChange : Y.bind('_afterSummaryChange', this), |
|
243 captionChange : Y.bind('_afterCaptionChange', this), |
|
244 widthChange : Y.bind('_afterWidthChange', this) |
|
245 }); |
|
246 } |
|
247 }, |
|
248 |
|
249 /** |
|
250 Creates the `<table>`. |
|
251 |
|
252 @method _createTable |
|
253 @return {Node} The `<table>` node |
|
254 @protected |
|
255 @since 3.5.0 |
|
256 **/ |
|
257 _createTable: function () { |
|
258 return Y.Node.create(fromTemplate(this.TABLE_TEMPLATE, { |
|
259 className: this.getClassName('table') |
|
260 })).empty(); |
|
261 }, |
|
262 |
|
263 /** |
|
264 Calls `render()` on the `bodyView` class instance. |
|
265 |
|
266 @method _defRenderBodyFn |
|
267 @param {EventFacade} e The renderBody event |
|
268 @protected |
|
269 @since 3.5.0 |
|
270 **/ |
|
271 _defRenderBodyFn: function (e) { |
|
272 e.view.render(); |
|
273 }, |
|
274 |
|
275 /** |
|
276 Calls `render()` on the `footerView` class instance. |
|
277 |
|
278 @method _defRenderFooterFn |
|
279 @param {EventFacade} e The renderFooter event |
|
280 @protected |
|
281 @since 3.5.0 |
|
282 **/ |
|
283 _defRenderFooterFn: function (e) { |
|
284 e.view.render(); |
|
285 }, |
|
286 |
|
287 /** |
|
288 Calls `render()` on the `headerView` class instance. |
|
289 |
|
290 @method _defRenderHeaderFn |
|
291 @param {EventFacade} e The renderHeader event |
|
292 @protected |
|
293 @since 3.5.0 |
|
294 **/ |
|
295 _defRenderHeaderFn: function (e) { |
|
296 e.view.render(); |
|
297 }, |
|
298 |
|
299 /** |
|
300 Renders the `<table>` and, if there are associated Views, the `<thead>`, |
|
301 `<tfoot>`, and `<tbody>` (empty until `syncUI`). |
|
302 |
|
303 Assigns the generated table nodes to the `tableNode`, `_theadNode`, |
|
304 `_tfootNode`, and `_tbodyNode` properties. Assigns the instantiated Views |
|
305 to the `head`, `foot`, and `body` properties. |
|
306 |
|
307 |
|
308 @method _defRenderTableFn |
|
309 @param {EventFacade} e The renderTable event |
|
310 @protected |
|
311 @since 3.5.0 |
|
312 **/ |
|
313 _defRenderTableFn: function (e) { |
|
314 var container = this.get('container'), |
|
315 attrs = this.getAttrs(); |
|
316 |
|
317 if (!this.tableNode) { |
|
318 this.tableNode = this._createTable(); |
|
319 } |
|
320 |
|
321 attrs.host = this.get('host') || this; |
|
322 attrs.table = this; |
|
323 attrs.container = this.tableNode; |
|
324 |
|
325 this._uiSetCaption(this.get('caption')); |
|
326 this._uiSetSummary(this.get('summary')); |
|
327 this._uiSetWidth(this.get('width')); |
|
328 |
|
329 if (this.head || e.headerView) { |
|
330 if (!this.head) { |
|
331 this.head = new e.headerView(Y.merge(attrs, e.headerConfig)); |
|
332 } |
|
333 |
|
334 this.fire('renderHeader', { view: this.head }); |
|
335 } |
|
336 |
|
337 if (this.foot || e.footerView) { |
|
338 if (!this.foot) { |
|
339 this.foot = new e.footerView(Y.merge(attrs, e.footerConfig)); |
|
340 } |
|
341 |
|
342 this.fire('renderFooter', { view: this.foot }); |
|
343 } |
|
344 |
|
345 attrs.columns = this.displayColumns; |
|
346 |
|
347 if (this.body || e.bodyView) { |
|
348 if (!this.body) { |
|
349 this.body = new e.bodyView(Y.merge(attrs, e.bodyConfig)); |
|
350 } |
|
351 |
|
352 this.fire('renderBody', { view: this.body }); |
|
353 } |
|
354 |
|
355 if (!container.contains(this.tableNode)) { |
|
356 container.append(this.tableNode); |
|
357 } |
|
358 |
|
359 this._bindUI(); |
|
360 }, |
|
361 |
|
362 /** |
|
363 Cleans up state, destroys child views, etc. |
|
364 |
|
365 @method destructor |
|
366 @protected |
|
367 **/ |
|
368 destructor: function () { |
|
369 if (this.head && this.head.destroy) { |
|
370 this.head.destroy(); |
|
371 } |
|
372 delete this.head; |
|
373 |
|
374 if (this.foot && this.foot.destroy) { |
|
375 this.foot.destroy(); |
|
376 } |
|
377 delete this.foot; |
|
378 |
|
379 if (this.body && this.body.destroy) { |
|
380 this.body.destroy(); |
|
381 } |
|
382 delete this.body; |
|
383 |
|
384 if (this._eventHandles) { |
|
385 this._eventHandles.detach(); |
|
386 delete this._eventHandles; |
|
387 } |
|
388 |
|
389 if (this.tableNode) { |
|
390 this.tableNode.remove().destroy(true); |
|
391 } |
|
392 }, |
|
393 |
|
394 /** |
|
395 Processes the full column array, distilling the columns down to those that |
|
396 correspond to cell data columns. |
|
397 |
|
398 @method _extractDisplayColumns |
|
399 @protected |
|
400 **/ |
|
401 _extractDisplayColumns: function () { |
|
402 var columns = this.get('columns'), |
|
403 displayColumns = []; |
|
404 |
|
405 function process(cols) { |
|
406 var i, len, col; |
|
407 |
|
408 for (i = 0, len = cols.length; i < len; ++i) { |
|
409 col = cols[i]; |
|
410 |
|
411 if (isArray(col.children)) { |
|
412 process(col.children); |
|
413 } else { |
|
414 displayColumns.push(col); |
|
415 } |
|
416 } |
|
417 } |
|
418 |
|
419 if (columns) { |
|
420 process(columns); |
|
421 } |
|
422 |
|
423 /** |
|
424 Array of the columns that correspond to those with value cells in the |
|
425 data rows. Excludes colspan header columns (configured with `children`). |
|
426 |
|
427 @property displayColumns |
|
428 @type {Object[]} |
|
429 @since 3.6.0 |
|
430 **/ |
|
431 this.displayColumns = displayColumns; |
|
432 }, |
|
433 |
|
434 /** |
|
435 Publishes core events. |
|
436 |
|
437 @method _initEvents |
|
438 @protected |
|
439 @since 3.5.0 |
|
440 **/ |
|
441 _initEvents: function () { |
|
442 this.publish({ |
|
443 // Y.bind used to allow late binding for method override support |
|
444 renderTable : { defaultFn: Y.bind('_defRenderTableFn', this) }, |
|
445 renderHeader: { defaultFn: Y.bind('_defRenderHeaderFn', this) }, |
|
446 renderBody : { defaultFn: Y.bind('_defRenderBodyFn', this) }, |
|
447 renderFooter: { defaultFn: Y.bind('_defRenderFooterFn', this) } |
|
448 }); |
|
449 }, |
|
450 |
|
451 /** |
|
452 Constructor logic. |
|
453 |
|
454 @method intializer |
|
455 @param {Object} config Configuration object passed to the constructor |
|
456 @protected |
|
457 @since 3.6.0 |
|
458 **/ |
|
459 initializer: function (config) { |
|
460 this.host = config.host; |
|
461 |
|
462 this._initEvents(); |
|
463 |
|
464 this._extractDisplayColumns(); |
|
465 |
|
466 this.after('columnsChange', this._extractDisplayColumns, this); |
|
467 }, |
|
468 |
|
469 /** |
|
470 Relays attribute changes to the child Views. |
|
471 |
|
472 @method _relayAttrChange |
|
473 @param {EventHandle} e The change event |
|
474 @protected |
|
475 @since 3.6.0 |
|
476 **/ |
|
477 _relayAttrChange: function (e) { |
|
478 var attr = e.attrName, |
|
479 val = e.newVal; |
|
480 |
|
481 if (this.head) { |
|
482 this.head.set(attr, val); |
|
483 } |
|
484 |
|
485 if (this.foot) { |
|
486 this.foot.set(attr, val); |
|
487 } |
|
488 |
|
489 if (this.body) { |
|
490 if (attr === 'columns') { |
|
491 val = this.displayColumns; |
|
492 } |
|
493 |
|
494 this.body.set(attr, val); |
|
495 } |
|
496 }, |
|
497 |
|
498 /** |
|
499 Creates the UI in the configured `container`. |
|
500 |
|
501 @method render |
|
502 @chainable |
|
503 **/ |
|
504 render: function () { |
|
505 if (this.get('container')) { |
|
506 this.fire('renderTable', { |
|
507 headerView : this.get('headerView'), |
|
508 headerConfig: this.get('headerConfig'), |
|
509 |
|
510 bodyView : this.get('bodyView'), |
|
511 bodyConfig : this.get('bodyConfig'), |
|
512 |
|
513 footerView : this.get('footerView'), |
|
514 footerConfig: this.get('footerConfig') |
|
515 }); |
|
516 } |
|
517 |
|
518 return this; |
|
519 }, |
|
520 |
|
521 /** |
|
522 Creates, removes, or updates the table's `<caption>` element per the input |
|
523 value. Empty values result in the caption being removed. |
|
524 |
|
525 @method _uiSetCaption |
|
526 @param {String} htmlContent The content to populate the table caption |
|
527 @protected |
|
528 @since 3.5.0 |
|
529 **/ |
|
530 _uiSetCaption: function (htmlContent) { |
|
531 var table = this.tableNode, |
|
532 caption = this.captionNode; |
|
533 |
|
534 if (htmlContent) { |
|
535 if (!caption) { |
|
536 this.captionNode = caption = Y.Node.create( |
|
537 fromTemplate(this.CAPTION_TEMPLATE, { |
|
538 className: this.getClassName('caption') |
|
539 })); |
|
540 |
|
541 table.prepend(this.captionNode); |
|
542 } |
|
543 |
|
544 caption.setHTML(htmlContent); |
|
545 |
|
546 } else if (caption) { |
|
547 caption.remove(true); |
|
548 |
|
549 delete this.captionNode; |
|
550 } |
|
551 }, |
|
552 |
|
553 /** |
|
554 Updates the table's `summary` attribute with the input value. |
|
555 |
|
556 @method _uiSetSummary |
|
557 @protected |
|
558 @since 3.5.0 |
|
559 **/ |
|
560 _uiSetSummary: function (summary) { |
|
561 if (summary) { |
|
562 this.tableNode.setAttribute('summary', summary); |
|
563 } else { |
|
564 this.tableNode.removeAttribute('summary'); |
|
565 } |
|
566 }, |
|
567 |
|
568 /** |
|
569 Sets the `boundingBox` and table width per the input value. |
|
570 |
|
571 @method _uiSetWidth |
|
572 @param {Number|String} width The width to make the table |
|
573 @protected |
|
574 @since 3.5.0 |
|
575 **/ |
|
576 _uiSetWidth: function (width) { |
|
577 var table = this.tableNode; |
|
578 |
|
579 // Table width needs to account for borders |
|
580 table.setStyle('width', !width ? '' : |
|
581 (this.get('container').get('offsetWidth') - |
|
582 (parseInt(table.getComputedStyle('borderLeftWidth'), 10)||0) - |
|
583 (parseInt(table.getComputedStyle('borderLeftWidth'), 10)||0)) + |
|
584 'px'); |
|
585 |
|
586 table.setStyle('width', width); |
|
587 }, |
|
588 |
|
589 /** |
|
590 Ensures that the input is a View class or at least has a `render` method. |
|
591 |
|
592 @method _validateView |
|
593 @param {View|Function} val The View class |
|
594 @return {Boolean} |
|
595 @protected |
|
596 **/ |
|
597 _validateView: function (val) { |
|
598 return isFunction(val) && val.prototype.render; |
|
599 } |
|
600 }, { |
|
601 ATTRS: { |
|
602 /** |
|
603 Content for the `<table summary="ATTRIBUTE VALUE HERE">`. Values |
|
604 assigned to this attribute will be HTML escaped for security. |
|
605 |
|
606 @attribute summary |
|
607 @type {String} |
|
608 @default '' (empty string) |
|
609 @since 3.5.0 |
|
610 **/ |
|
611 //summary: {}, |
|
612 |
|
613 /** |
|
614 HTML content of an optional `<caption>` element to appear above the |
|
615 table. Leave this config unset or set to a falsy value to remove the |
|
616 caption. |
|
617 |
|
618 @attribute caption |
|
619 @type HTML |
|
620 @default undefined (initially unset) |
|
621 @since 3.6.0 |
|
622 **/ |
|
623 //caption: {}, |
|
624 |
|
625 /** |
|
626 Columns to include in the rendered table. |
|
627 |
|
628 This attribute takes an array of objects. Each object is considered a |
|
629 data column or header cell to be rendered. How the objects are |
|
630 translated into markup is delegated to the `headerView`, `bodyView`, |
|
631 and `footerView`. |
|
632 |
|
633 The raw value is passed to the `headerView` and `footerView`. The |
|
634 `bodyView` receives the instance's `displayColumns` array, which is |
|
635 parsed from the columns array. If there are no nested columns (columns |
|
636 configured with a `children` array), the `displayColumns` is the same |
|
637 as the raw value. |
|
638 |
|
639 @attribute columns |
|
640 @type {Object[]} |
|
641 @since 3.6.0 |
|
642 **/ |
|
643 columns: { |
|
644 validator: isArray |
|
645 }, |
|
646 |
|
647 /** |
|
648 Width of the table including borders. This value requires units, so |
|
649 `200` is invalid, but `'200px'` is valid. Setting the empty string |
|
650 (the default) will allow the browser to set the table width. |
|
651 |
|
652 @attribute width |
|
653 @type {String} |
|
654 @default '' |
|
655 @since 3.6.0 |
|
656 **/ |
|
657 width: { |
|
658 value: '', |
|
659 validator: YLang.isString |
|
660 }, |
|
661 |
|
662 /** |
|
663 An instance of this class is used to render the contents of the |
|
664 `<thead>`—the column headers for the table. |
|
665 |
|
666 The instance of this View will be assigned to the instance's `head` |
|
667 property. |
|
668 |
|
669 It is not strictly necessary that the class function assigned here be |
|
670 a View subclass. It must however have a `render()` method. |
|
671 |
|
672 @attribute headerView |
|
673 @type {Function|Object} |
|
674 @default Y.DataTable.HeaderView |
|
675 @since 3.6.0 |
|
676 **/ |
|
677 headerView: { |
|
678 value: Y.DataTable.HeaderView, |
|
679 validator: '_validateView' |
|
680 }, |
|
681 |
|
682 /** |
|
683 Configuration overrides used when instantiating the `headerView` |
|
684 instance. |
|
685 |
|
686 @attribute headerConfig |
|
687 @type {Object} |
|
688 @since 3.6.0 |
|
689 **/ |
|
690 //headerConfig: {}, |
|
691 |
|
692 /** |
|
693 An instance of this class is used to render the contents of the |
|
694 `<tfoot>` (if appropriate). |
|
695 |
|
696 The instance of this View will be assigned to the instance's `foot` |
|
697 property. |
|
698 |
|
699 It is not strictly necessary that the class function assigned here be |
|
700 a View subclass. It must however have a `render()` method. |
|
701 |
|
702 @attribute footerView |
|
703 @type {Function|Object} |
|
704 @since 3.6.0 |
|
705 **/ |
|
706 footerView: { |
|
707 validator: '_validateView' |
|
708 }, |
|
709 |
|
710 /** |
|
711 Configuration overrides used when instantiating the `footerView` |
|
712 instance. |
|
713 |
|
714 @attribute footerConfig |
|
715 @type {Object} |
|
716 @since 3.6.0 |
|
717 **/ |
|
718 //footerConfig: {}, |
|
719 |
|
720 /** |
|
721 An instance of this class is used to render the contents of the table's |
|
722 `<tbody>`—the data cells in the table. |
|
723 |
|
724 The instance of this View will be assigned to the instance's `body` |
|
725 property. |
|
726 |
|
727 It is not strictly necessary that the class function assigned here be |
|
728 a View subclass. It must however have a `render()` method. |
|
729 |
|
730 @attribute bodyView |
|
731 @type {Function|Object} |
|
732 @default Y.DataTable.BodyView |
|
733 @since 3.6.0 |
|
734 **/ |
|
735 bodyView: { |
|
736 value: Y.DataTable.BodyView, |
|
737 validator: '_validateView' |
|
738 } |
|
739 |
|
740 /** |
|
741 Configuration overrides used when instantiating the `bodyView` |
|
742 instance. |
|
743 |
|
744 @attribute bodyConfig |
|
745 @type {Object} |
|
746 @since 3.6.0 |
|
747 **/ |
|
748 //bodyConfig: {} |
|
749 } |
|
750 }); |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 }, '@VERSION@', {"requires": ["datatable-core", "datatable-head", "datatable-body", "view", "classnamemanager"]}); |