~ubuntu-branches/ubuntu/saucy/whoopsie-daisy/saucy

« back to all changes in this revision

Viewing changes to backend/stats/static/js/yui/build/datatable-head/datatable-head-debug.js

  • Committer: Package Import Robot
  • Author(s): Evan Dandrea
  • Date: 2012-04-18 13:04:36 UTC
  • Revision ID: package-import@ubuntu.com-20120418130436-vmt93p8fds516lws
Tags: 0.1.32
Fix failing tests on powerpc and ARM.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
YUI 3.5.0 (build 5089)
 
3
Copyright 2012 Yahoo! Inc. All rights reserved.
 
4
Licensed under the BSD License.
 
5
http://yuilibrary.com/license/
 
6
*/
 
7
YUI.add('datatable-head', function(Y) {
 
8
 
 
9
/**
 
10
View class responsible for rendering the `<thead>` section of a table. Used as
 
11
the default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes.
 
12
 
 
13
@module datatable
 
14
@submodule datatable-head
 
15
@since 3.5.0
 
16
**/
 
17
var Lang = Y.Lang,
 
18
    fromTemplate = Lang.sub,
 
19
    isArray = Lang.isArray,
 
20
    toArray = Y.Array,
 
21
 
 
22
    ClassNameManager = Y.ClassNameManager,
 
23
    _getClassName    = ClassNameManager.getClassName;
 
24
 
 
25
/**
 
26
View class responsible for rendering the `<thead>` section of a table. Used as
 
27
the default `headerView` for `Y.DataTable.Base` and `Y.DataTable` classes.
 
28
 
 
29
Translates the provided array of column configuration objects into a rendered
 
30
`<thead>` based on the data in those objects.
 
31
    
 
32
 
 
33
The structure of the column data is expected to be a single array of objects,
 
34
where each object corresponds to a `<th>`.  Those objects may contain a
 
35
`children` property containing a similarly structured array to indicate the
 
36
nested cells should be grouped under the parent column's colspan in a separate
 
37
row of header cells. E.g.
 
38
 
 
39
<pre><code>
 
40
new Y.DataTable.HeaderView({
 
41
  container: tableNode,
 
42
  columns: [
 
43
    { key: 'id' }, // no nesting
 
44
    { key: 'name', children: [
 
45
      { key: 'firstName', label: 'First' },
 
46
      { key: 'lastName',  label: 'Last' } ] }
 
47
  ]
 
48
}).render();
 
49
</code></pre>
 
50
 
 
51
This would translate to the following visualization:
 
52
 
 
53
<pre>
 
54
---------------------
 
55
|    |     name     |
 
56
|    |---------------
 
57
| id | First | Last |
 
58
---------------------
 
59
</pre>
 
60
 
 
61
Supported properties of the column objects include:
 
62
 
 
63
  * `label`     - The HTML content of the header cell.
 
64
  * `key`       - If `label` is not specified, the `key` is used for content.
 
65
  * `children`  - Array of columns to appear below this column in the next
 
66
                  row.
 
67
  * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells in this
 
68
    column only.
 
69
  * `abbr`      - The content of the 'abbr' attribute of the `<th>`
 
70
  * `className` - Adds this string of CSS classes to the column header
 
71
 
 
72
Through the life of instantiation and rendering, the column objects will have
 
73
the following properties added to them:
 
74
 
 
75
  * `id`       - (Defaulted by DataTable) The id to assign the rendered column
 
76
  * `_colspan` - To supply the `<th>` attribute
 
77
  * `_rowspan` - To supply the `<th>` attribute
 
78
  * `_parent`  - (Added by DataTable) If the column is a child of another
 
79
    column, this points to its parent column
 
80
 
 
81
The column object is also used to provide values for {placeholder} tokens in the
 
82
instance's `CELL_TEMPLATE`, so you can modify the template and include other
 
83
column object properties to populate them.
 
84
 
 
85
@class HeaderView
 
86
@namespace DataTable
 
87
@extends View
 
88
@since 3.5.0
 
89
**/
 
90
Y.namespace('DataTable').HeaderView = Y.Base.create('tableHeader', Y.View, [], {
 
91
    // -- Instance properties -------------------------------------------------
 
92
 
 
93
    /**
 
94
    Template used to create the table's header cell markup.  Override this to
 
95
    customize how header cell markup is created.
 
96
 
 
97
    @property CELL_TEMPLATE
 
98
    @type {HTML}
 
99
    @default '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}>{content}</th>'
 
100
    @since 3.5.0
 
101
    **/
 
102
    CELL_TEMPLATE:
 
103
        '<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}>{content}</th>',
 
104
 
 
105
    /**
 
106
    The data representation of the header rows to render.  This is assigned by
 
107
    parsing the `columns` configuration array, and is used by the render()
 
108
    method.
 
109
 
 
110
    @property columns
 
111
    @type {Array[]}
 
112
    @default (initially unset)
 
113
    @since 3.5.0
 
114
    **/
 
115
    //TODO: should this be protected?
 
116
    //columns: null,
 
117
 
 
118
    /**
 
119
    Template used to create the table's header row markup.  Override this to
 
120
    customize the row markup.
 
121
 
 
122
    @property ROW_TEMPLATE
 
123
    @type {HTML}
 
124
    @default '<tr>{content}</tr>'
 
125
    @since 3.5.0
 
126
    **/
 
127
    ROW_TEMPLATE:
 
128
        '<tr>{content}</tr>',
 
129
 
 
130
    /**
 
131
    The object that serves as the source of truth for column and row data.
 
132
    This property is assigned at instantiation from the `source` property of
 
133
    the configuration object passed to the constructor.
 
134
 
 
135
    @property source
 
136
    @type {Object}
 
137
    @default (initially unset)
 
138
    @since 3.5.0
 
139
    **/
 
140
    //TODO: should this be protected?
 
141
    //source: null,
 
142
 
 
143
 
 
144
    // -- Public methods ------------------------------------------------------
 
145
 
 
146
    /**
 
147
    Builds a CSS class name from the provided tokens.  If the instance is
 
148
    created with `cssPrefix` or `source` in the configuration, it will use this
 
149
    prefix (the `_cssPrefix` of the `source` object) as the base token.  This
 
150
    allows class instances to generate markup with class names that correspond
 
151
    to the parent class that is consuming them.
 
152
 
 
153
    @method getClassName
 
154
    @param {String} token* Any number of tokens to include in the class name
 
155
    @return {String} The generated class name
 
156
    @since 3.5.0
 
157
    **/
 
158
    getClassName: function () {
 
159
        var args = toArray(arguments);
 
160
        args.unshift(this._cssPrefix);
 
161
        args.push(true);
 
162
 
 
163
        return _getClassName.apply(ClassNameManager, args);
 
164
    },
 
165
 
 
166
    /**
 
167
    Creates the `<thead>` Node content by assembling markup generated by
 
168
    populating the `ROW_TEMPLATE` and `CELL_TEMPLATE` templates with content
 
169
    from the `columns` property.
 
170
    
 
171
    @method render
 
172
    @return {HeaderView} The instance
 
173
    @chainable
 
174
    @since 3.5.0
 
175
    **/
 
176
    render: function () {
 
177
        var thead    = this.get('container'),
 
178
            columns  = this.columns,
 
179
            defaults = {
 
180
                _colspan: 1,
 
181
                _rowspan: 1,
 
182
                abbr: ''
 
183
            },
 
184
            i, len, j, jlen, col, html, content, values;
 
185
 
 
186
        if (thead && columns) {
 
187
            html = '';
 
188
 
 
189
            if (columns.length) {
 
190
                for (i = 0, len = columns.length; i < len; ++i) {
 
191
                    content = '';
 
192
 
 
193
                    for (j = 0, jlen = columns[i].length; j < jlen; ++j) {
 
194
                        col = columns[i][j];
 
195
                        values = Y.merge(
 
196
                            defaults,
 
197
                            col, {
 
198
                                className: this.getClassName('header'),
 
199
                                content  : col.label || col.key ||
 
200
                                           ("Column " + (j + 1))
 
201
                            }
 
202
                        );
 
203
 
 
204
                        values._id = col._id ?
 
205
                            ' data-yui3-col-id="' + col._id + '"' : '';
 
206
                        
 
207
                        if (col.abbr) {
 
208
                            values.abbr = ' abbr="' + col.abbr + '"';
 
209
                        }
 
210
 
 
211
                        if (col.className) {
 
212
                            values.className += ' ' + col.className;
 
213
                        }
 
214
 
 
215
                        if (col._first) {
 
216
                            values.className += ' ' + this.getClassName('first', 'header');
 
217
                        }
 
218
 
 
219
                        if (col._id) {
 
220
                            values.className +=
 
221
                                ' ' + this.getClassName('col', col._id);
 
222
                        }
 
223
 
 
224
                        content += fromTemplate(
 
225
                            col.headerTemplate || this.CELL_TEMPLATE, values);
 
226
                    }
 
227
 
 
228
                    html += fromTemplate(this.ROW_TEMPLATE, {
 
229
                        content: content
 
230
                    });
 
231
                }
 
232
            }
 
233
 
 
234
            thead.setContent(html);
 
235
        }
 
236
 
 
237
        this.bindUI();
 
238
 
 
239
        return this;
 
240
    },
 
241
 
 
242
    // -- Protected and private properties and methods ------------------------
 
243
    /**
 
244
    The base token for classes created with the `getClassName` method.
 
245
 
 
246
    @property _cssPrefix
 
247
    @type {String}
 
248
    @default 'yui3-table'
 
249
    @protected
 
250
    @since 3.5.0
 
251
    **/
 
252
    _cssPrefix: ClassNameManager.getClassName('table'),
 
253
 
 
254
    /**
 
255
    Handles changes in the source's columns attribute.  Redraws the headers.
 
256
 
 
257
    @method _afterColumnsChange
 
258
    @param {EventFacade} e The `columnsChange` event object
 
259
    @protected
 
260
    @since 3.5.0
 
261
    **/
 
262
    _afterColumnsChange: function (e) {
 
263
        this.columns = this._parseColumns(e.newVal);
 
264
 
 
265
        this.render();
 
266
    },
 
267
 
 
268
    /**
 
269
    Binds event subscriptions from the UI and the source (if assigned).
 
270
 
 
271
    @method bindUI
 
272
    @protected
 
273
    @since 3.5.0
 
274
    **/
 
275
    bindUI: function () {
 
276
        if (this.source && !this._eventHandles.columnsChange) {
 
277
            // TODO: How best to decouple this?
 
278
            this._eventHandles.columnsChange =
 
279
                this.source.after('columnsChange',
 
280
                    Y.bind('_afterColumnsChange', this));
 
281
        }
 
282
    },
 
283
 
 
284
    /**
 
285
    Destroys the instance.
 
286
 
 
287
    @method destructor
 
288
    @protected
 
289
    @since 3.5.0
 
290
    **/
 
291
    destructor: function () {
 
292
        (new Y.EventHandle(Y.Object.values(this._eventHandles))).detach();
 
293
    },
 
294
 
 
295
    /**
 
296
    Holds the event subscriptions needing to be detached when the instance is
 
297
    `destroy()`ed.
 
298
 
 
299
    @property _eventHandles
 
300
    @type {Object}
 
301
    @default undefined (initially unset)
 
302
    @protected
 
303
    @since 3.5.0
 
304
    **/
 
305
    //_eventHandles: null,
 
306
 
 
307
    /**
 
308
    Initializes the instance. Reads the following configuration properties:
 
309
 
 
310
      * `columns` - (REQUIRED) The initial column information
 
311
      * `cssPrefix` - The base string for classes generated by `getClassName`
 
312
      * `source` - The object to serve as source of truth for column info
 
313
 
 
314
    @method initializer
 
315
    @param {Object} config Configuration data
 
316
    @protected
 
317
    @since 3.5.0
 
318
    **/
 
319
    initializer: function (config) {
 
320
        config || (config = {});
 
321
 
 
322
        var cssPrefix = config.cssPrefix || (config.source || {}).cssPrefix;
 
323
 
 
324
        this.source  = config.source;
 
325
        this.columns = this._parseColumns(config.columns);
 
326
 
 
327
        this._eventHandles = [];
 
328
 
 
329
        if (cssPrefix) {
 
330
            this._cssPrefix = cssPrefix;
 
331
        }
 
332
    },
 
333
 
 
334
    /**
 
335
    Translate the input column format into a structure useful for rendering a
 
336
    `<thead>`, rows, and cells.  The structure of the input is expected to be a
 
337
    single array of objects, where each object corresponds to a `<th>`.  Those
 
338
    objects may contain a `children` property containing a similarly structured
 
339
    array to indicate the nested cells should be grouped under the parent
 
340
    column's colspan in a separate row of header cells. E.g.
 
341
 
 
342
    <pre><code>
 
343
    [
 
344
      { key: 'id' }, // no nesting
 
345
      { key: 'name', children: [
 
346
        { key: 'firstName', label: 'First' },
 
347
        { key: 'lastName',  label: 'Last' } ] }
 
348
    ]
 
349
    </code></pre>
 
350
 
 
351
    would indicate two header rows with the first column 'id' being assigned a
 
352
    `rowspan` of `2`, the 'name' column appearing in the first row with a
 
353
    `colspan` of `2`, and the 'firstName' and 'lastName' columns appearing in
 
354
    the second row, below the 'name' column.
 
355
 
 
356
    <pre>
 
357
    ---------------------
 
358
    |    |     name     |
 
359
    |    |---------------
 
360
    | id | First | Last |
 
361
    ---------------------
 
362
    </pre>
 
363
 
 
364
    Supported properties of the column objects include:
 
365
 
 
366
      * `label`    - The HTML content of the header cell.
 
367
      * `key`      - If `label` is not specified, the `key` is used for content.
 
368
      * `children` - Array of columns to appear below this column in the next
 
369
                     row.
 
370
      * `abbr`     - The content of the 'abbr' attribute of the `<th>`
 
371
      * `headerTemplate` - Overrides the instance's `CELL_TEMPLATE` for cells
 
372
        in this column only.
 
373
 
 
374
    The output structure is basically a simulation of the `<thead>` structure
 
375
    with arrays for rows and objects for cells.  Column objects have the
 
376
    following properties added to them:
 
377
    
 
378
      * `id`       - (Defaulted by DataTable) The id to assign the rendered
 
379
                     column
 
380
      * `_colspan` - Per the `<th>` attribute
 
381
      * `_rowspan` - Per the `<th>` attribute
 
382
      * `_parent`  - (Added by DataTable) If the column is a child of another
 
383
        column, this points to its parent column
 
384
 
 
385
    The column object is also used to provide values for {placeholder}
 
386
    replacement in the `CELL_TEMPLATE`, so you can modify the template and
 
387
    include other column object properties to populate them.
 
388
 
 
389
    @method _parseColumns
 
390
    @param {Object[]} data Array of column object data
 
391
    @return {Array[]} An array of arrays corresponding to the header row
 
392
            structure to render
 
393
    @protected
 
394
    @since 3.5.0
 
395
    **/
 
396
    _parseColumns: function (data) {
 
397
        var columns = [],
 
398
            stack = [],
 
399
            rowSpan = 1,
 
400
            entry, row, col, children, parent, i, len, j;
 
401
        
 
402
        if (isArray(data) && data.length) {
 
403
            // First pass, assign colspans and calculate row count for
 
404
            // non-nested headers' rowspan
 
405
            stack.push([data, -1]);
 
406
 
 
407
            while (stack.length) {
 
408
                entry = stack[stack.length - 1];
 
409
                row   = entry[0];
 
410
                i     = entry[1] + 1;
 
411
 
 
412
                for (len = row.length; i < len; ++i) {
 
413
                    col = row[i];
 
414
                    children = col.children;
 
415
 
 
416
                    Y.stamp(col);
 
417
 
 
418
                    if (isArray(children) && children.length) {
 
419
                        stack.push([children, -1]);
 
420
                        entry[1] = i;
 
421
 
 
422
                        rowSpan = Math.max(rowSpan, stack.length);
 
423
 
 
424
                        // break to let the while loop process the children
 
425
                        break;
 
426
                    } else {
 
427
                        col._colspan = 1;
 
428
                    }
 
429
                }
 
430
 
 
431
                if (i >= len) {
 
432
                    // All columns in this row are processed
 
433
                    if (stack.length > 1) {
 
434
                        entry  = stack[stack.length - 2];
 
435
                        parent = entry[0][entry[1]];
 
436
 
 
437
                        parent._colspan = 0;
 
438
 
 
439
                        for (i = 0, len = row.length; i < len; ++i) {
 
440
                            // Can't use .length because in 3+ rows, colspan
 
441
                            // needs to aggregate the colspans of children
 
442
                            parent._colspan += row[i]._colspan;
 
443
                        }
 
444
                    }
 
445
                    stack.pop();
 
446
                }
 
447
            }
 
448
 
 
449
            // Second pass, build row arrays and assign rowspan
 
450
            for (i = 0; i < rowSpan; ++i) {
 
451
                columns.push([]);
 
452
            }
 
453
 
 
454
            stack.push([data, -1]);
 
455
 
 
456
            while (stack.length) {
 
457
                entry = stack[stack.length - 1];
 
458
                row   = entry[0];
 
459
                i     = entry[1] + 1;
 
460
 
 
461
                for (len = row.length; i < len; ++i) {
 
462
                    col = row[i];
 
463
                    children = col.children;
 
464
 
 
465
                    columns[stack.length - 1].push(col);
 
466
 
 
467
                    entry[1] = i;
 
468
 
 
469
                    // collect the IDs of parent cols
 
470
                    col._headers = [col.id];
 
471
 
 
472
                    for (j = stack.length - 2; j >= 0; --j) {
 
473
                        parent = stack[j][0][stack[j][1]];
 
474
 
 
475
                        col._headers.unshift(parent.id);
 
476
                    }
 
477
 
 
478
                    if (children && children.length) {
 
479
                        // parent cells must assume rowspan 1 (long story)
 
480
 
 
481
                        // break to let the while loop process the children
 
482
                        stack.push([children, -1]);
 
483
                        break;
 
484
                    } else {
 
485
                        col._rowspan = rowSpan - stack.length + 1;
 
486
                    }
 
487
                }
 
488
 
 
489
                if (i >= len) {
 
490
                    // All columns in this row are processed
 
491
                    stack.pop();
 
492
                }
 
493
            }
 
494
        }
 
495
 
 
496
        for (i = 0, len = columns.length; i < len; i += col._rowspan) {
 
497
            col = columns[i][0];
 
498
 
 
499
            col._first = true;
 
500
        }
 
501
 
 
502
        return columns;
 
503
    }
 
504
});
 
505
 
 
506
 
 
507
}, '3.5.0' ,{requires:['datatable-core', 'view', 'classnamemanager']});