diff -r 322d0feea350 -r 89ef5ed3c48b src/cm/media/js/lib/yui/yui_3.10.3/docs/datatable/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui_3.10.3/docs/datatable/index.html Tue Jul 16 14:29:46 2013 +0200 @@ -0,0 +1,2828 @@ + + + + + DataTable + + + + + + + + + + +
+
+

+
+ + Jump to Table of Contents + + +

DataTable

+
+
+
+
+ +
+

+ The DataTable widget is responsible for rendering columnar data into a + highly customizable and fully accessible HTML table. The core + functionality of DataTable is to visualize structured data as a table. + A variety of class extensions can then be used to add features to the + table such as sorting and scrolling. +

+
+ +

Getting Started

+ +

+To include the source files for DataTable and its dependencies, first load +the YUI seed file if you haven't already loaded it. +

+ +
<script src="http://yui.yahooapis.com/3.10.3/build/yui/yui-min.js"></script>
+ + +

+Next, create a new YUI instance for your application and populate it with the +modules you need by specifying them as arguments to the YUI().use() method. +YUI will automatically load any dependencies required by the modules you +specify. +

+ +
<script>
+// Create a new YUI instance and populate it with the required modules.
+YUI().use('datatable', function (Y) {
+    // DataTable is available and ready for use. Add implementation
+    // code here.
+});
+</script>
+ + +

+For more information on creating YUI instances and on the +use() method, see the +documentation for the YUI Global Object. +

+ + +

+Note: be sure to add the yui3-skin-sam classname to the +page's <body> element or to a parent element of the widget in order to apply +the default CSS skin. See Understanding Skinning. +

+ +
+

Upgrading from version 3.4.1 or older?

+ +

+ DataTable was refactored for 3.5.0. Some APIs were changed in backward + incompatible ways. +

+ +

+ Read the 3.5.0 Migration Guide for tips to + avoid unpleasant surprises. If you still run into issues, please + file a ticket. +

+ +

+ If you are unable to upgrade due to unresolvable issues, you can use the + datatable-deprecated + module suite, which is equivalent to the 3.4.1 implementation. But be + aware that these modules will be removed in a future version of YUI. +

+
+ +

DataTable Basics

+ +

+ A basic DataTable is made of columns and rows. Define the columns you + want to display in your DataTable with the columns attribute. Rows are + created for you based on the data you provide to the data attribute. +

+ +

+ Under the hood, the DataTable class uses a + ModelList instance to manage the row + data properties. Read the Table Data Configuration + section below for details about how to load, configure, and work with the + table data. +

+ +
// Columns must match data object property names
+var data = [
+    { id: "ga-3475", name: "gadget",   price: "$6.99", cost: "$5.99" },
+    { id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
+    { id: "wi-0650", name: "widget",   price: "$4.25", cost: "$3.75" }
+];
+
+var table = new Y.DataTable({
+    columns: ["id", "name", "price"],
+    data: data,
+
+    // Optionally configure your table with a caption
+    caption: "My first DataTable!",
+
+    // and/or a summary (table attribute)
+    summary: "Example DataTable showing basic instantiation configuration"
+});
+
+table.render("#example");
+ + +

This code produces this table:

+ +
+ + + +

Column Configuration

+ +

+ The columns attribute takes an array of field names that correspond to + property names in the data objects. These field names are called "keys". + As long as these keys exist in your data, DataTable will display the + values in the table. By default, the key is also used as the label of the + column header. +

+ + +

+ Use objects instead of key strings to customize how the cells in a column + display. +

+ +
// Columns must match data object property names
+var data = [
+    { id: "ga-3475", name: "gadget",   price: "$6.99", cost: "$5.99" },
+    { id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
+    { id: "wi-0650", name: "widget",   /* missing */   cost: "$3.75" }
+];
+
+var table = new Y.DataTable({
+    columns: [
+        "id",
+        { key: "name", label: "part name" },
+        { key: "price", allowHTML: true, emptyCellValue: "<em>(not set)</em>" },
+        "cost"
+    ],
+    data: data
+});
+
+table.render("#example");
+ + +

This code produces this table:

+ +
+ + + +

+ Some column configurations affect the table headers and others affect the + data cells. +

+ +

+ Use the key property to reference the associated data field when + configuring columns with objects. Other supported configuration + properties are listed in Appendix A below. +

+ + +

Stacked Column Headers

+ +

+ Use the children column configuration to create multiple rows of column + headers. +

+ +
var columns = [
+    'username',
+    {
+        // Important: Parent columns do NOT get a key...
+
+        // but DO get a label
+        label: "Access",
+
+        // Pass an array of column configurations (strings or objects) as children
+        children: [
+            'read',
+            'write',
+        ]
+    }
+];
+
+var data = [
+    { username: "root", read: true, write: true },
+    { username: "spilgrim", read: true, write: false },
+    { username: "fizzgig", read: false, write: false }
+];
+
+var table = new Y.DataTable({
+    columns: columns,
+    data   : data
+}).render("#example");
+ + +

This code produces this table:

+ +
+ + + +

+ children takes an array of column configurations, just like the columns + attribute itself. The columns defined in the children property will have + header cells rendered below the parent column's header. +

+ +

+ Columns that have children don't relate directly to the data cells in the + table rows, so they should not have a key configured. + They should, however, include a label to provide the header's content. +

+ +

Formatting Cell Data

+ +

+ Customizing the content of the cells in your table is done using column + configurations. The most common formatting-related column configurations + are: +

+ +
    +
  • + allowHTML - set this to true if your cell data, emptyCellValue, or + formatter outputs HTML. By default, cell data is HTML escaped for + security. +
  • +
  • + emptyCellValue - string to populate cells where no data (empty + string, undefined, or null) is available in a record. +
  • +
  • + formatter - string or function used to translate the raw record data + for each cell in a given column into a format better suited to display. +
  • +
  • + nodeFormatter - function used to customize the DOM structure of a + cell, its row, or its surrounding elements. Use with caution. +
  • +
+ +

+ When the formatter configuration setting contains a string it will be assumed + to be the key into the hash of formatting functions at Y.DataTable.BodyView.Formatters. + If any such function is found, it will be used, otherwise, the string will be + presumed to be a template which may contain placeholders for data enclosed + in curly braces. The {value} placeholder would use the value destined for + the current cell. The values of other fields in the record corresponding + to the current row can be shown by providing their name enclosed in curly braces. + These other fields + don't need to have column definitions of their own, they will simply be read + from the underlying Model instance. +

+

+ The Y.DataTable.BodyView.Formatters is empty for the developers to provide + their own formatting functions. A basic set is provided in module + datatable-formatters that has to be explicitly loaded. Some of these + named formatters accept extra configuration settings in the column definition, + as described in their + + API docs. +

+

+ formatter functions are expected to return the string content to populate each + cell in that column, and nodeFormatters are provided with the cell Nodes + and expected to populate them using the Node API. +

+ +

+ For best performance, avoid + nodeFormatters unless absolutely necessary. +

+ +
var columns = [
+    {
+        key: 'item',
+        formatter: '<a href="#{value}">{value}</a>',
+        allowHTML: true // Must be set or the html will be escaped
+    },
+    {
+        key: 'cost',
+        formatter: '${value}' // formatter template string
+    },
+    {
+        key: 'price',
+        formatter: function (o) {
+            if (o.value > 3) {
+                o.className += 'expensive';
+            }
+
+            return '$' + o.value.toFixed(2);
+        }
+    },
+    {
+        label: 'profit',
+        nodeFormatter: function (o) {
+            var profit = o.data.price - o.data.cost,
+                prefix = '$',
+                row;
+
+            if (profit < 0) {
+                prefix = '-' + prefix;
+                profit = Math.abs(profit);
+                row = o.cell.ancestor();
+
+                o.cell.addClass('negative');
+
+                // Assign a rowspan to the first cell and add a new row
+                // below this one to span the last three columns
+                row.one('td').setAttribute('rowspan', 2);
+
+                row.insert(
+                    '<tr class="auth"><td colspan="3">' +
+                        '<button class="ok">authorize</button>' +
+                        '<button class="stop">discontinue</button>' +
+                    '</td></tr>',
+                    'after');
+            }
+
+            o.cell.set('text', prefix + profit.toFixed(2));
+        }
+    }
+];
+ + +

This code produces this table:

+ +
+ +
+ + + +

+ The parameters passed to formatter functions and nodeFormatter + functions are described in Appendix B and Appendix C, respectively. Also look for + what can be passed in to the columns in + Appendix A. +

+ +

+ Note: It's highly recommended to keep the data in the + underlying data ModelList as pure data, free from presentational + concerns. For example, use real numbers, not numeric strings, and store + link urls and labels either in separate data fields or in a single data + field, but as separate properties of a value object. This allows the data + to be used for calculations such as sorting or averaging. +

+ +

Setting content with formatter functions

+ +

+ Set the cell content with column formatters by returning the desired + content string from the function. Alternately, just update o.value with + the new value in the object passed as an argument to the formatter. When + updating o.value do not include a return statement. +

+ +

+ formatters are very powerful because not only do they have access to the + record's value for that column's field, but they also receive the rest of + the record's data, the record Model instance itself, and the column + configuration object. This allows you to include any extra configurations + in your column configuration that might be useful to customizing how cells + in the column are rendered. +

+ +
function currency(o) {
+    return Y.DataType.Number.format(o.value, {
+        prefix            : o.column.currencySymbol     || '$',
+        decimalPlaces     : o.column.decimalPlaces      || 2,
+        decimalSeparator  : o.column.decimalSeparator   || '.',
+        thousandsSeparator: o.column.thousandsSeparator || ','
+    });
+}
+
+var cols = [
+    { key: "price", formatter: currency, decimalPlaces: 3 },
+    ...
+ +

+ If such a formatter will be used regularly, it is best to store it in the + Y.DataTable.BodyView.Formatters hash. The formatter can later be used + by its name. +

+

+ Named formatters are structured slightly differently in + order to improve performance: +

+
Y.DataTable.BodyView.Formatters.currency = function (col) {
+    // This is done just once per rendering cycle:
+    var fn = Y.DataType.Number.format,
+        format = {
+            prefix            : col.currencySymbol     || '$',
+            decimalPlaces     : col.decimalPlaces      || 2,
+            decimalSeparator  : col.decimalSeparator   || '.',
+            thousandsSeparator: col.thousandsSeparator || ','
+        };
+    return function (o) {
+        // This is done once per row:
+        return fn(o.value, format);
+    }
+}
+ +

+ The function stored in the Formatters table is not the formatter function + itself, instead, it returns the formatting function. The outer function is called just + once per rendering cycle and does any preliminary setup usually based on the + column configuration which it receives as its only argument, storing any + information in local variables. The returned formatting function is then + run once per row accessing all the setup information via closure. +

+

+ An optional datatable-formatters module provides + a collection of such formatters. + See the API docs + for more information on them. +

+

+ See Appendix B for a list of all properties + passed to formatter functions. +

+ +

Setting content with nodeFormatter functions

+ +

+ Unlike formatters which can effectively default to the normal rendering + logic by leaving o.value unchanged, nodeFormatters must assign content + to the cells themselves. The cell's initial classes will be set up, but + that's it. Everything else is your responsibility. +

+ +

+ nodeFormatters should return false. + See below for details. +

+ +

+ While there are few scenarios that + require nodeFormatters, they do have the benefits of having the Node + API for constructing more complex DOM subtrees and the ability to access + all nodes in the <tbody>. This means they can reference, and even modify, + cells in other rows. +

+ +

+ Like formatters, nodeFormatters are provided with the data field value, + the record data, the record Model instance, and the column configuration + object. +

+ +

+ See Appendix C for a list of all + properties passed to nodeFormatter functions. +

+ +

Why formatter and nodeFormatter?

+ +

+ For good rendering performance and memory management, DataTable creates + table content by assembling innerHTML strings from templates, with + {placeholder} tokens replaced with your data. However, this means that + the Nodes don't exist yet when a column's formatters are applied. +

+ +

+ To minimize the need to create Nodes for each cell, the default rendering + logic supports the addition of cell classes as well as row classes via + formatter functions. Event subscriptions should be + delegated + from the DataTable instance itself using the + delegate() method. +

+ +

+ On the rare occasion that you must use Nodes to supply the cell + data, DataTable allows a second pass over the generated DOM elements once + the initial string concatenation has been completed and the full HTML + content created. +

+ +

+ It is important to note that nodeFormatters will necessarily create a + Node instance for each cell in that column, which will increase the memory + footprint of your application. If the Node instance wrappers around the + DOM elements don't need to be maintained beyond the life of the + nodeFormatter, return false to remove them from the internal object + cache. This will not remove the rendered DOM, but it will remove + event subscriptions made on those Nodes. +

+ +

+ In general, nodeFormatters should only be used if absolutely necessary, + and should always return false. +

+ +

Formatters vs. emptyCellValue

+ +

+ The emptyCellValue configuration is useful to provide fallback content in + the case of missing or empty column data, but it interacts with each type of + formatter differently. +

+ +

+ String formatters will only be applied if the field data for that cell is + not undefined. This allows the emptyCellValue to populate the cell. +

+ +

+ Function formatters are applied before the return value or (potentially + altered) o.value property is tested for undefined, null, or the empty + string. In any of these cases, the emptyCellValue populates the cell. +

+ +

+ The emptyCellValue configuration is ignored by columns configured with + nodeFormatters. +

+ + +

Table Data Configuration

+ +

+ Each record in the table is stored as a + Model instance, where the + keys of the record objects become Model attributes. This allows you to + interact with the models as you would any other Base-based class, with get(attr), + set(attr, value), and subscribing to attribute change events. +

+ +
var data = [
+    { item: "widget",   cost: 23.57, price: 47.5 },
+    { item: "gadget",   cost: 0.11, price: 6.99 },
+    { item: "sprocket", cost: 4.08, price: 3.75 },
+    { item: "nut",      cost: 0.01, price: 0.25 }
+];
+
+var table = new Y.DataTable({
+    columns: ["item", "cost", "price"],
+    data: data
+});
+
+var sprocket = table.getRecord(2);
+
+// Fires a costChange event, and the table is updated if rendered
+sprocket.set('cost', 2.65);
+ + +

+ The Model class used to store the record data is created for you, based on + the objects in the data array. If data is not set, the column keys + identified in the columns configuration is used. +

+ +

Specifying the Record Model

+ +

+ To use a custom Model for your records, pass your Model subclass to the + recordType attribute. +

+ +
var pieTable = new Y.DataTable({
+    recordType: Y.PieModel,
+    columns: ['slices', 'type'],
+    data: [
+        // Y.PieModel has attributes 'slices', which defaults to 6, and 'type',
+        // which defaults to 'apple'. Records can use these defaults.
+        { type: 'lemon meringue' },
+        { type: 'chocolate creme', slices: 8 },
+        {} // equivalent to { type: 'apple', slices: 6 }
+    ]
+});
+
+// Y.PieModel has its idAttribute assigned to 'type', overriding the default
+// of 'id'.  Fetch a PieModel by its id.
+var applePie = pieTable.getRecord('apple');
+
+// eatSlice is a method on the Y.PieModel prototype
+applePie.eatSlice();
+ + +

+ Alternately, recordType will accept an array of attribute strings or an + ATTRS configuration object to make it easier to create custom attribute + behaviors without needing to explicitly build the Model subclass. +

+ +

+ If the columns configuration is omitted, but the recordType is set, the + columns will default to the recordType's attributes. +

+ +
var data = [
+    { item: "widget",   cost: 23.57, price: 47.5 },
+    { item: "gadget",   cost: 0.11, price: 6.99 },
+    { item: "sprocket", cost: 4.08, price: 3.75 },
+    { item: "nut",      cost: 0.01, price: 0.25 }
+];
+
+// Effectively synonymous with setting the columns attribute if no special
+// column configuration is needed.
+var table = new Y.DataTable({
+    recordType: [ 'item', 'cost', 'price' ],
+    data: data
+});
+
+// Or for more control, pass an ATTRS configuration object
+var table = new Y.DataTable({
+    recordType: {
+        item: {},
+        cost: {
+            value: 0,
+            setter: function (val) { return +val || 0; }
+        },
+        price: {
+            valueFn: function () { return (this.get('cost') + 0.1) * 10; },
+            setter: function (val) { return +val || 0; }
+        }
+    },
+    data: data
+});
+ + +

+ When the table data is loaded asychronously, it is often a good idea to + configure the recordType. This can prevent the generation of a record + Model that is missing fields that are omitted from the columns + configuration because they aren't intended for viewing. +

+ +

The data ModelList

+ +

+ The record Models are stored in a + ModelList, which is assigned to the + data property on the instance (for easier access than going through table.get('data')). +

+ +
var records = [
+    { item: "widget",   cost: 23.57, price: 47.5 },
+    { item: "gadget",   cost: 0.11, price: 6.99 },
+    { item: "sprocket", cost: 4.08, price: 3.75 }
+];
+
+var table = new Y.DataTable({
+    columns: ["item", "cost", "price"],
+    data   : records
+});
+
+// Add a new Model using the ModelList API. This will fire
+// events and change the table if rendered.
+table.data.add({ item: "nut", cost: 0.01, price: 0.25 });
+ + +

+ When assigning the DataTable's data attribute with an array, a ModelList + is created for you. But you can also pass a ModelList instance if you are + sharing a ModelList between widgets on the page, or you have created custom + Model and ModelList classes with additional logic, such as adding a + data sync layer. +

+ +
var table = new Y.DataTable({
+    columns: ['type', 'slices'],
+    data: new Y.PieList()
+});
+
+// The Y.PieList class implements a sync layer, enabling its load() method
+table.data.load(function () {
+    table.render('#pies');
+});
+ + +

Getting Remote Table Data

+ +

+ To fetch remote data, you have three options: +

+ +
    +
  1. +

    + For quick one-offs, you can load and parse the + data manually, using Y.io(...), Y.jsonp(...), etc., then assign + that data to the DataTable's data attribute. This isn't very + elegant or maintainable, so is best avoided for anything other than + proofs of concept. +

    +
  2. +
  3. +

    + For the most control, better maintainability, and + better encapsulation of business logic, create Model and ModelList + subclasses that + implement a + sync layer as suggested above. +

    +
  4. +
  5. +

    + For common read-only scenarios, use the + Y.Plugin.DataTableDataSource + plugin to bind your table to a + DataSource instance. Use + plugins to add DataSource features. +

    +
  6. +
+ + +
// Create a JSONP DataSource to query YQL
+var myDataSource = new Y.DataSource.Get({
+    source: 'http://query.yahooapis.com/v1/public/yql?format=json&' +
+            'env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&q='
+});
+
+myDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
+        schema: {
+            resultListLocator: 'query.results.Result',
+            resultFields: [
+                'Title',
+                'Phone',
+                {
+                    // Important that record fields NOT include ".", so
+                    // extract nested data with locators
+                    key: 'Rating',
+                    locator: "Rating.AverageRating"
+                }
+            ]
+        }
+    })
+    .plug(Y.Plugin.DataSourceCache, {
+        max: 3
+    });
+
+// No data is provided at construction because it will load via the
+// DataTableDataSource plugin
+var table = new Y.DataTable({
+    columns: ['Title', 'Phone', 'Rating'],
+    summary: 'Pizza places near 98089'
+});
+
+table.plug(Y.Plugin.DataTableDataSource, {
+    datasource: myDataSource
+})
+
+// Initially render an empty table and show a loading message
+table.render('#pizza')
+     .showMessage('loadingMessage');
+
+// Load the data into the table
+table.datasource.load({
+    request: encodeURIComponent(
+        'select *' +
+        ' from   local.search' +
+        ' where  zip="94089"' +
+        ' and    query="pizza"');
+});
+ + +

DataTable Modules and Features

+ +

+ For a basic, stripped down Y.DataTable class, include the datatable-base + module in your use(). +

+ +

+ Feature modules, such as datatable-sort, will bring in datatable-base + automatically. By including only feature modules in your use(), you will + get a Y.DataTable that supports specifically those features, without + extra code for other features you won't be using. +

+ +

+ The datatable module is a bundle of datatable-base plus a set of common + feature modules. Other feature modules need to be included explicitly in + use(). +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ModuleDescriptionIn datatable?
datatable-core + The core API for DataTable, implemented as a class extension, used + by datatable-base to create Y.DataTable and Y.DataTable.Base. + yes
datatable-base + Creates the Y.DataTable and Y.DataTable.Base classes, and + defaults the headerView and bodyView to Y.DataTable.HeaderView + and Y.DataTable.BodyView respectively. + yes
datatable-head + Creates the Y.DataTable.HeaderView class as a subclass of + Y.View. DataTable defers rendering of the <thead> content to + this View when it is passed as the DataTable's headerView + attribute (the default, as set by datatable-base). + yes
datatable-body + Creates the Y.DataTable.BodyView class as a subclass of + Y.View. DataTable defers rendering of the <tbody> content to + this View when it is passed as the DataTable's bodyView + attribute (the default, as set by datatable-base). + yes
datatable-message + Creates the Y.DataTable.Message class extension and adds + showMessage and hideMessage methods to Y.DataTable. + yes
datatable-column-widths + Creates the Y.DataTable.ColumnWidths class extension, and adds + support for the width property in column configuration objects + to Y.DataTable. + yes
datatable-mutable + Creates the Y.DataTable.Mutable class extension and adds methods + such as addRow, removeRow, and moveColumn to Y.DataTable. + yes
datatable-sort + Creates the Y.DataTable.Sortable class extension and adds methods + sort and toggleSort as well as attributes sortable and + sortBy to Y.DataTable. Enables sorting the table rows by + clicking on column headers. + yes
datatable-datasource + Creates the Y.Plugin.DataTableDataSource plugin for binding a + DataSource instance to the table as its source of record data. + yes
datatable-scroll + Creates the Y.DataTable.Scroll class extension and adds attribute + scrollable to Y.DataTable. Adds support for vertically and/or + horizontally scrolling table rows within fixed table dimensions. + no
datatable-formatters + Populates Y.DataTable.BodyView.Formatters with a collection of + cell formatting functions. + no
+ +

Features in DataTable.Base

+ +

+ By including only datatable-base in your use() line, you get both + Y.DataTable and Y.DataTable.Base classes. With no other module + inclusion, these classes are effectively the same. When additional + DataTable related modules are included, those modules' features will + usually be added to Y.DataTable, but never to + Y.DataTable.Base. +

+ +

+ Though it can be instantiated, the purpose of Y.DataTable.Base is + primarily as a superclass to a custom DataTable implementation that has a + locked set of features that will not be modified, as Y.DataTable can be, + by the inclusion of other modules. +

+ +
// Create a custom DataTable that includes only the core set of APIs, plus
+// sorting and message support.
+Y.MyDataTable = Y.Base.create('myTable', Y.DataTable.Base,
+    [ Y.DataTable.Sortable, Y.DataTable.Message ]);
+
+Y.use('datatable-scroll', function (Y) {
+    // Y.DataTable now has support for scrolling
+    var table = new Y.DataTable({ scrollable: 'y', ... });
+
+    // Y.MyDataTable does not (the config does nothing)
+    var myTable = new Y.MyDataTable({ scrollable: 'y', ... });
+});
+ + +

+ Y.DataTable.Base includes the columns, data, caption, and other + basic table attributes, the underlying ModelList and View rendering + architecture, as well as methods to fetch rows and cells or columns and + records. +

+ +

+ Rendering features include most column configurations, such as children + and allowHTML, as well as column formatting options formatter, + nodeFormatter, cellTemplate, etc. +

+ +

Table Messages

+ +

+ The datatable-message module adds the ability to display a message in the + table body. By default, the "emptyMessage" will display when the table's + ModelList has no data records. The message will hide when data is added. +

+ +
var table = new Y.DataTable({
+    columns: ["id", "name", "price"],
+    data: []
+}).render('#example');
+ + +

This code produces this table:

+ +
+ + + +

+ Use table.showMessage("message") and table.hideMessage() to toggle the + message display. +

+ +

+ showMessage supports internationalized strings by using a few named + strings, which are registered in the language packs for the + datatable-message module . These strings are currently: +

+ +
    +
  • + table.showMessage("emptyMessage") defaults to "No data to display". +
  • +
  • + table.showMessage("loadingMessage") defaults to "Loading...". +
  • +
+ +

+ Other values passed to showMessage will pass that content directly + through to the message Node. +

+ +

Column Width Configuration

+ +

+ The datatable-column-widths module adds basic support for specifying + column widths. +

+ +
var table = new Y.DataTable({
+    columns: [
+        { key: 'item', width: '125px' },
+        { key: 'cost', formatter: '${value}' },
+        ...
+    ],
+    data   : data
+}).render("#example");
+ + +

This code produces this table:

+ +
+ + + +

+ CAVEAT: Column widths will expand beyond the configured + value if column cells contain data that is long and can't line-wrap. Also, + column widths may be reduced below the configured value if the table width + (by configuring the DataTable's width attribute, or constrained by a + narrow containing element) is too narrow to fit all data at the configured + widths. +

+ +

+ To force column widths, including cell data truncation and allowing the + table to spill beyond its configured or inherited width, wrap the cell + content in a <div> either by configuring the column's formatter or + cellTemplate, then assign the <div>'s CSS style with the desired width + (or "inherit"), plus overflow: hidden;. Then set the DataTable column's + width configuration accordingly. +

+ +

Column sorting

+ +

+ The datatable-sort module adds support for sorting the table rows either + through the added APIs or by clicking on the table headers. +

+ +

+ By default, when datatable-sort is included, DataTables will inspects + the columns objects, looking for sortable: true to enable table sorting + by those columns, triggered by clicking on their respective headers. +

+
var cols = [
+    { key: "Company", sortable: true },
+    { key: "Phone" },
+    { key: "Contact", sortable: true }
+];
+ + +

+ For convenience, you can enable header-click sorting for all columns by + setting the sortable attribute to true, or pass an array of column keys + to enable just those column's headers. +

+ +
// Set all columns to be sortable
+var table = new Y.DataTable({
+    columns: ["Company", "Phone", "Contact"],
+    data: ...
+    sortable: true
+}).render("#example");
+ + +

This code produces this table:

+ +
+ + + +

+ Hold down the shift key while clicking on column headers to subsort by + that column. Doing so repeatedly will toggle the subsort direction. +

+ +

+ As long as the datatable-sort module has been included, you will always + be able to sort the table data through the API, even by columns that aren't + configured to accept header-click sorting. +

+ +

+ When a table is sorted, any new records added to the DataTable's ModelList + will be inserted at the proper sorted index, as will the created table + rows. +

+ +

+ Disable header-click sorting by setting sortable to false. +

+

+ The default sort order is case insensitive, the sort order can be set to case sensitive + by using the caseSensitive attribute, see Appendix A below. +

+ +

Custom Sorting

+ +

+ Assign a function to a column's sortFn to support customized sorting. The + function will receive the two records being compared and a boolean flag + indicating a descending sort was requested. +

+ +
var columns = [
+    {
+        key: 'id',
+        label: '&#9679;', // a big dot
+        formatter: function (o) {
+            return o.value ? '' : '&#9679;'; // only new records have a dot
+        },
+        sortable: true,
+        sortFn: function (a, b, desc) {
+            var aid   = a.get('id'),
+                bid   = b.get('id'),
+                acid  = a.get('clientId'),
+                bcid  = b.get('clientId'),
+                order = // existing records are equivalent
+                        (aid && bid) ? 0 :
+                        // new records are grouped apart from existing records
+                        (aid && -1) || (bid && 1) ||
+                        // new records are sorted by insertion order
+                        (acid > bcid) ? 1 : -(acid < bcid);
+
+            return desc ? -order : order;
+        }
+    },
+    ...
+ + +

+ The function must return 1, 0, or -1. 1 specifies that the Model passed as + the first parameter should sort below the Model passed as the second + parameter. -1 for above, and 0 if they are equivalent for the purpose of + this sort. +

+ + +

Sorting Methods

+ +

+ To sort the table in the code, call table.sort(NAME OR KEY). To + toggle the sort direction, call table.toggleSort(NAME OR KEY). +

+ +
// Sorts the table by values in the price field in ascending order
+table.sort('price');
+
+// Flips to descending
+table.toggleSort('price');
+ + +

+ To sort by multiple columns, pass an array of column keys to sort or + toggleSort. +

+ +

+ Calling toggleSort with no arguments will reverse all current sort + directions. Calling with specific column names or keys will toggle only + those columns. +

+ +
// Sort first by author, subsort by title in ascending order
+table.sort(['author', 'title']);
+
+// Now descending by author then title
+// same as table.toggleSort(['author', 'title']);
+table.toggleSort();
+
+// Now ascending by author, descending by title
+table.toggleSort('author');
+ + +

+ To specify a sort direction, pass an object instead of a string to sort. + The object should have the column name as the key, and sort direction as its + value. +

+ +
// Explicitly sort by price in descending order
+table.sort({ price: 'desc' });
+
+// Each column gets its own object
+table.sort([{ author: 'desc' }, { title: 'desc' }]);
+ + +

+ Acceptable values for the sort direction are "asc", "desc", 1, and -1. 1 is + equivalent to "asc", and -1 to "desc". +

+ +

The sortBy Attribute

+ +

+ Every sort operation updates the sortBy attribute. You can also trigger + a sort by setting this attribute directly. It accepts the same values as + the sort method. +

+ +
// Sort by author in descending order, then by title in ascending order
+table.set('sortBy', [{ author: -1 }, 'title']);
+ + +

+ To specify an initial sort order for your table, assign this attribute + during instantiation. This will sort the data as soon as it is added + to the table's ModelList. +

+ +
// Pre-sort the data
+var table = new Y.DataTable({
+    columns: ['item', 'cost', 'price'],
+    data: [...],
+    sortBy: { price: -1 }
+});
+ + +

The sort Event

+ +

+ Clicking on a column header, or calling the sort or toggleSort methods + will fire a sort method containing an e.sortBy property that + corresponds to the requested sort column and direction. The value will be + in either string or object format, depending on how each method was used. +

+ +

+ Preventing the sort event will prevent the sortBy attribute from being + updated. Updating the sortBy attribute directly will not fire the sort + event, but will still sort the data and update the table. +

+ +

Table Mutation APIs (addRow, etc)

+ +

+ The datatable-mutable module adds APIs for adding, removing, and + modifying records and columns. +

+ +

Column Mutation Methods

+ +

+ Use the methods addColumn, removeColumn, modifyColumn, and + moveColumn to update the table's configured columns. +

+ +
// Insert a column for the profit field in the data records as the third column
+table.addColumn('profit', 2);
+
+// Actually, make that the fourth column
+table.moveColumn('profit', 3);
+
+// Actually, strike that.  Don't show it after all
+table.removeColumn('profit');
+
+// Instead, add a formatter to the price column that includes the profit data
+table.modifyColumn('price', {
+    formatter: function (o) {
+        return o.value + ' (' + (o.data.profit / o.data.cost).toFixed(2) + '%)';
+    }
+});
+ + +

+ Each column mutation method fires an identically named event. See + the API docs for details. +

+ +

Row Mutation Methods

+ +

+ Use the methods addRow, addRows, removeRow, and modifyRow to update + the table's ModelList. +

+ +
table.addRow({ item: 'collet', cost: 0.42, price: 2.65 });
+
+table.addRows([
+    { item: 'nut',    cost: 0.42, price: 2.65 },
+    { item: 'washer', cost: 0.01, price: 0.08 },
+    { item: 'bit',    cost: 0.19, price: 0.97 }
+]);
+
+// Remove table records by their Model, id, clientId, or index
+table.removeRow(0);
+
+// Modify a record by passing its id, clientId, or index, followed by an
+// object with new field values
+table.modifyRow('record_4', { cost: 0.74 });
+ +

+ Everything that's done by these methods can be accomplished through the + table's ModelList instance methods, but having methods on the table itself + can make the code more readable. +

+ +
// Same as table.addRow(...);
+table.data.add({ item: 'collet', cost: 0.42, price: 2.65 });
+ + +

+ By default, changes made to the table are only local, they don't update the + server or other data origin if the data was served remotely. However, if + your table's ModelList is built with a sync layer, the mutation methods + can also trigger the appropriate sync behavior by passing an additional + argument to the methods, an object with the property sync set to true. +

+ +
// Tell the server we're down to one slice of apple pie!
+table.modifyRow('apple', { slices: 1 }, { sync: true });
+
+// Uh oh, make that 0.  No more apple pie :(
+table.removeRow('apple', { sync: true });
+ + +

+ If all modifications are destined for the server/origin, you can set the + autoSync attribute to true, and the row mutation methods will + automatically call into the sync layer. +

+ +
var pies = new Y.DataTable({
+    columns: ['type', 'slices'],
+    data: new Y.PieList()
+    autoSync: true
+});
+
+pies.data.load(function () {
+
+    pies.render('#pie-cart');
+
+    // The new PieModel's save() method is called, notifying the server
+    pies.addRow({ type: 'pecan', slices: 8 });
+
+    // Let us eat some pie!
+    pies.modifyRow('lemon meringue', { slices: 5 });
+});
+ + +

Scrolling

+ +

+ Note: Scrolling is not currently supported on the Android + WebKit browser. +

+ +

+ Scrolling functionality can be added to Y.DataTable by including + datatable-scroll module in your use(). datatable-scroll is + NOT included in the datatable rollup module, so must be + included separately. +

+ +

+ Enable scrolling by setting the scrollable attribute, which accepts values + "x", "y", "xy", true (same as "xy"), or false (the default). +

+ +

+ Note, vertical scrolling also requires the table's height attribute to be + set, and horizontal scrolling requires the width to be set. +

+ +
// Data from the seafoodwatch YQL table as of 3/16/2012
+var data = [
+    { "fish": "Barramundi (Imported Farmed in Open Systems)", "recommendation": "avoid" },
+    { "fish": "Caviar, Paddlefish (Wild caught from U.S.)", "recommendation": "avoid" },
+    { "fish": "Caviar, Sturgeon (Imported Wild-caught)", "recommendation": "avoid" },
+    ...
+];
+
+// Enable vertical scrolling with scrollable "y". The width is also set, but
+// because scrollable is not "x" or "xy", this just sets the table width.
+var table = new Y.DataTable({
+    caption: 'Seafood tips for the US West Coast',
+    columns: ['fish', 'recommendation'],
+    data: data,
+    scrollable: "y",
+    height: "200px",
+    width:  "400px"
+}).render("#scroll");
+ + +

This code produces this table:

+ +
+ + + +

DataTable Events

+ +

+ DataTable is a composition of supporting class instances and extensions, so + to centralize event reporting, it is a bubble target for its data + ModelList as well as the View instances used for rendering. +

+ +

+ In other words, some events you may need to subscribe to using an event + prefix to be notified. Often, using a wildcard prefix is the simplest + method to ensure your subscribers will be notified, even if classes change. +

+ +
// The sort event is from an extension, so it originates from DataTable
+table.after('sort', function (e) { ... });
+
+// Model changes originate from the record's Model instance, propagate to the
+// table's ModelList, then finally to the DataTable, so they must be
+// subscribed with an event prefix.  In this case, we'll use a wildcard
+// prefix.
+table.after('*:priceChange', function (e) { ... });
+ + +

+ DataTable generates a custom Model class with the "record" event prefix, if + you want to be more specific. Otherwise, if your table uses a custom Model + class for its recordType, you can prefix Model events with the appropriate + prefix. +

+ +
// Allow DataTable to generate the Model class automatically
+var table = new Y.DataTable({
+    columns: ['items', 'cost', 'price'],
+    data: [
+        { item: "widget", cost: 23.57, price: 47.5 },
+        { item: "gadget", cost: 0.11, price: 6.99 },
+        ...
+    ]
+});
+
+// generated Model classes have prefix "record"
+table.after('record:change', function (e) { ... });
+
+// PieList uses PieModels, which have a prefix of, you guessed it, "pie"
+var pies = new Y.DataTable({
+    columns: ['type', 'slices'],
+    data: new Y.PieList()
+});
+
+pies.on('pie:slicesChange', function (e) {
+    if (e.target.get('type') === 'chocolate creme') {
+        // Oh no you don't!
+        e.preventDefault();
+    }
+});
+ + +

+ The full list of events is included in the DataTable API docs. +

+ +

Known Issues

+ + + +

Appendix A: Column Configurations

+ +

+ The properties below are supported in the column configuration objects + passed in the columns attribute array. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationDescriptionModule
key +
{ key: 'username' }
+ +

+ Binds the column values to the named property in the data. +

+

+ Optional if formatter, nodeFormatter, or cellTemplate + is used to populate the content. +

+

It should not be set if children is set.

+

+ The value is used for the _id property unless the name + property is also set. +

+
datatable-base
name +
{ name: 'fullname', formatter: ... }
+ + +

+ Use this to assign a name to pass to table.getColumn(NAME) + or style columns with class "yui3-datatable-col-NAME" if a + column isn't assigned a key. +

+

+ The value is used for the _id property. +

+
datatable-base
field +
{ field: 'fullname', formatter: ... }
+ + +

An alias for name for backward compatibility.

+
datatable-base
id +
{
+  name: 'checkAll',
+  id: 'check-all',
+  label: ...
+  formatter: ...
+}
+ +

+ Overrides the default unique id assigned <th id="HERE">. +

+

+ Use this with caution, since it can result in + duplicate ids in the DOM. +

+
datatable-base
label +
{ key: 'MfgPrtNum', label: 'Part Number' }
+ + +

HTML to populate the header <th> for the column.

+
datatable-base
children +

+ Used to create stacked headers. + See the example above. +

+ +

+ Child columns may also contain children. There is no limit + to the depth of nesting. +

+ +

+ Columns configured with children are for display only and + should not be configured with a key. + Configurations relating to the display of data, such as + formatter, nodeFormatter, emptyCellValue, etc. are + ignored. +

+
datatable-base
abbr +
{
+  key  : 'forecast',
+  label: '1yr Target Forecast',
+  abbr : 'Forecast'
+}
+ + +

Assigns the value <th abbr="HERE">.

+
datatable-base
title +
{
+  key  : 'forecast',
+  label: '1yr Target Forecast',
+  title: 'Target Forecast for the Next 12 Months'
+}
+ + +

Assigns the value <th title="HERE">.

+
datatable-base
headerTemplate +
{
+  headerTemplate:
+    '<th id="{id}" ' +
+        'title="Unread" ' +
+        'class="{className}" ' +
+        '{_id}>&#9679;</th>'
+}
+ + +

+ Overrides the default + CELL_TEMPLATE + used by Y.DataTable.HeaderView to render the header cell + for this column. This is necessary when more control is + needed over the markup for the header itself, rather than + its content. +

+ +

+ Use the label configuration if you don't need to + customize the <th> iteself. +

+ +

+ Implementers are strongly encouraged to preserve at least + the {id} and {_id} placeholders in the custom value. +

+
datatable-base
cellTemplate +
{
+  key: 'id',
+  cellTemplate:
+    '<td class="{className}">' +
+      '<input type="checkbox" ' +
+             'id="{content}">' +
+    '</td>'
+}
+ + +

+ Overrides the default + CELL_TEMPLATE + used by Y.DataTable.BodyView to render the data cells + for this column. This is necessary when more control is + needed over the markup for the <td> itself, rather than + its content. +

+
datatable-base
formatter +

+ Used to customize the content of the data cells for this + column. +

+ +

+ See the example above +

+
datatable-base
nodeFormatter +

+ Used to customize the content of the data cells for this + column. +

+ +

+ See the example above +

+
datatable-base
emptyCellValue +
{
+  key: 'price',
+  emptyCellValue: '???'
+}
+ + +

+ Provides the default value to populate the cell if the data + for that cell is undefined, null, or an empty string. +

+
datatable-base
allowHTML +
{
+  key: 'preview',
+  allowHTML: true
+}
+ + +

+ Skips the security step of HTML escaping the value for cells + in this column. This is also necessary if emptyCellValue + is set with an HTML string. +

+

+ nodeFormatters ignore this configuration. If using a + nodeFormatter, it is recommended to use + Y.Escape.html() + on any user supplied content that is to be displayed. +

+
datatable-base
className +
{
+  key: 'symbol',
+  className: 'no-hide'
+}
+ + +

+ A string of CSS classes that will be added to the <td>'s + class attribute. +

+ +

+ Note, all cells will automatically have a class in the + form of "yui3-datatable-col-KEY" added to the <td>, where + KEY is the column's configured name, key, or id (in + that order of preference). +

+
datatable-base
width +
{ key: 'a', width: '400px' },
+{ key: 'b', width: '10em' }
+ + +

+ Adds a style width setting to an associated <col> + element for the column. +

+ +

+ Note, the assigned width will not truncate cell content, and + it will not preserve the configured width if doing so would + compromise either the instance's width configuration or + the natural width of the table's containing DOM elements. +

+ +

+ If absolute widths are required, it can be accomplished with + some custom CSS and the use of a cellTemplate, or + formatter. See + the + description of datatable-column-widths for an example + of how to do this. +

+
datatable-column-widths
sortable +
{ key: 'lastLogin', sortable: true }
+ + +

+ Used when the instance's sortable attribute is set to + "auto" (the default) to determine which columns will support + user sorting by clicking on the header. +

+

+ If the instance's key attribute is not set, this + configuration is ignored. +

+
datatable-sort
caseSensitive +
{ key: 'lastLogin', sortable: true, caseSensitive: true }
+ + +

+ When the instance's caseSensitive attribute is set to + "true" the sort order is case sensitive (relevant to string columns only). +

+

+ Case sensitive sort is marginally more efficient and should be considered + for large data sets when case insensitive sort is not required. +

+
datatable-sort
sortFn +
{
+  label: 'Name',
+  sortFn: function (a, b, desc) {
+    var an = a.get('lname') + b.get('fname'),
+        bn = a.get('lname') + b.get('fname'),
+        order = (an > bn) ? 1 : -(an < bn);
+
+    return desc ? -order : order;
+  },
+  formatter: function (o) {
+    return o.data.lname + ', ' + o.data.fname;
+  }
+}
+ + +

+ Allows a column to be sorted using a custom algorithm. The + function receives three parameters, the first two being the + two record Models to compare, and the third being a boolean + true if the sort order should be descending. +

+

+ The function should return -1 to sort a above b, -1 + to sort a below b, and 0 if they are equal. Keep in + mind that the order should be reversed when desc is + true. +

+

+ The desc parameter is provided to allow sortFns to + always sort certain values above or below others, such as + always sorting nulls on top. +

+
datatable-sort
sortDir +

+ (read-only) If a column is sorted, this + will be set to 1 for ascending order or -1 for + descending. This configuration is public for inspection, + but can't be used during DataTable instantiation to set the + sort direction of the column. Use the table's + sortBy + attribute for that. +

+
datatable-sort
_yuid +

+ (read-only) The unique identifier assigned + to each column. This is used for the id if not set, and + the _id if none of name, 'field, key, or id` are + set. +

+
datatable-base
_id +

+ (read-only) A unique-to-this-instance name + used extensively in the rendering process. It is also used + to create the column's classname, as the input name + table.getColumn(HERE), and in the column header's + <th data-yui3-col-id="HERE">. +

+

+ The value is populated by the first of name, field, + key, id, or _yuid to have a value. If that value + has already been used (such as when multiple columns have + the same key), an incrementer is added to the end. For + example, two columns with key: "id" will have _ids of + "id" and "id2". table.getColumn("id") will return the + first column, and table.getColumn("id2") will return the + second. +

+
datatable-base
_colspan +

+ (read-only) Used by + Y.DataTable.HeaderView when building stacked column + headers. +

+
datatable-base
_rowspan +

+ (read-only) Used by + Y.DataTable.HeaderView when building stacked column + headers. +

+
datatable-base
_parent +

+ (read-only) Assigned to all columns in a + column's children collection. References the parent + column object. +

+
datatable-base
_headers +

+ (read-only) Array of the ids of the + column and all parent columns. Used by + Y.DataTable.BodyView to populate <td headers="THIS"> + when a cell references more than one header. +

+
datatable-base
+
+ +

Appendix B: Formatter Argument Properties

+ +

+ The properties below are found on the object passed to formatter + functions defined in a column configuration. See + Appendix C for the object properties + passed to nodeFormatters. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
value +
formatter: function (o) {
+    // assumes a numeric value for this column
+    return '$' + o.value.toFixed(2);
+}
+ + +

+ The raw value from the record Model to populate this cell. + Equivalent to o.record.get(o.column.key) or + o.data[o.column.key]. +

+
data +
formatter: function (o) {
+    return o.data.lname + ', ' + o.data.fname;
+}
+ + +

+ The Model data for this row in simple object format. +

+
record +
formatter: function (o) {
+    return '<a href="/service/' + o.record.get('id') + '">' +
+        o.value + '</a>';
+}
+ + +

+ The Model for this row. +

+
column +
formatter: function (o) {
+    // Use a custom column property
+    var format = o.column.dateFormat || '%D';
+
+    return Y.DataType.Data.format(o.value, format);
+}
+ + +

+ The column configuration object. +

+
className +
formatter: function (o) {
+    if (o.value < 0) {
+        o.className += 'loss';
+    }
+}
+ + +

+ A string of class names to add <td class="HERE"> in + addition to the column class and any classes in the + column's className configuration. +

+
rowIndex +
formatter: function (o) {
+    return (o.rowIndex + 1) + ' - ' + o.value;
+}
+ + +

+ The index of the current Model in the ModelList. + Typically correlates to the row index as well. +

+
rowClass +
formatter: function (o) {
+    if (o.value < 0) {
+        o.rowClass += 'loss';
+    }
+}
+ + +

+ A string of css classes to add <tr class="HERE"><td.... +

+ +

+ This is useful to avoid the need for nodeFormatters to add + classes to the containing row. +

+
+
+ +

Appendix C: nodeFormatter Argument Properties

+ +

+ The properties below are found on the object passed to nodeFormatter + functions defined in a column configuration. See + Appendix B for the object properties + passed to formatters. +

+ +
// Reference nodeFormatter
+nodeFormatter: function (o) {
+    if (o.value < o.data.quota) {
+        o.td.setAttribute('rowspan', 2);
+        o.td.setAttribute('data-term-id', this.record.get('id'));
+
+        o.td.ancestor().insert(
+            '<tr><td colspan"3">' +
+                '<button class="term">terminate</button>' +
+            '</td></tr>',
+            'after');
+    }
+
+    o.cell.setHTML(o.value);
+}
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
tdThe <td> Node for this cell.
cell +

+ If the cell <td> contains an element with class + "yui3-datatable-liner", this will refer to that Node. + Otherwise, it is equivalent to o.td (default behavior). +

+ +

+ By default, liner elements aren't rendered into cells, but + to implement absolute column widths, some cell liner + element with width and overflow style is required + (barring a table style of table-layout: fixed). This may + be applied to the columns cellTemplate configuration or + to the bodyView instance's CELL_TEMPLATE for all + columns. +

+ +

+ Generally, the liner, if present, corresponds to where the + content should go, so use o.cell to add content and + o.td to specifically work with the <td> Node. +

+
value + The raw value from the record Model to populate this cell. + Equivalent to o.record.get(o.column.key) or + o.data[o.column.key]. +
dataThe Model data for this row in simple object format.
recordThe Model for this row.
columnThe column configuration object.
rowIndex + The index of the current Model in the ModelList. + Typically correlates to the row index as well. +
+
+ +
+
+
+ +
+ +
+
+
+ + + + + + + + + + +