--- /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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>DataTable</title>
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic,700italic">
+ <link rel="stylesheet" href="../../build/cssgrids/cssgrids-min.css">
+ <link rel="stylesheet" href="../assets/css/main.css">
+ <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
+ <link rel="shortcut icon" type="image/png" href="../assets/favicon.png">
+ <script src="../../build/yui/yui-min.js"></script>
+
+</head>
+<body>
+<!--
+<a href="https://github.com/yui/yui3"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
+-->
+<div id="doc">
+ <div id="hd">
+ <h1><img src="http://yuilibrary.com/img/yui-logo.png"></h1>
+ </div>
+
+ <a href="#toc" class="jump">Jump to Table of Contents</a>
+
+
+ <h1>DataTable</h1>
+ <div class="yui3-g">
+ <div class="yui3-u-3-4">
+ <div id="main">
+ <div class="content"><style type="text/css">
+ td code {
+ white-space: nowrap;
+ background: #fcfbfa;
+ border: 1px solid #d0d5ec;
+ padding: 0 3px;
+ }
+ .yui3-datatable table {
+ width: auto;
+ }
+
+ .yui3-datatable td, .yui3-datatable th {
+ border: 0 none;
+ }
+
+ .yui3-datatable-col-Module {
+ white-space: nowrap;
+ }
+
+ .yui3-skin-sam .yui3-datatable-message-content {
+ background: #fff;
+ border-bottom: 0 none;
+ }
+
+ .notice {
+ background: #faf3d1;
+ border: 1px solid #eac9a9;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: px;
+ padding: 0 1em;
+ -moz-box-shadow: 0 0 5px #ccc8b3;
+ -webkit-box-shadow: 0 0 5px #ccc8b3;
+ box-shadow: 0 0 5px #ccc8b3;
+ margin-bottom: 1em;
+ }
+ .notice h2 {
+ margin-top: .6em;
+ }
+</style>
+
+<div class="intro component">
+ <p>
+ 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.
+ </p>
+</div>
+
+<h2 id="getting-started">Getting Started</h2>
+
+<p>
+To include the source files for DataTable and its dependencies, first load
+the YUI seed file if you haven't already loaded it.
+</p>
+
+<pre class="code prettyprint"><script src="http://yui.yahooapis.com/3.10.3/build/yui/yui-min.js"></script></pre>
+
+
+<p>
+Next, create a new YUI instance for your application and populate it with the
+modules you need by specifying them as arguments to the <code>YUI().use()</code> method.
+YUI will automatically load any dependencies required by the modules you
+specify.
+</p>
+
+<pre class="code prettyprint"><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></pre>
+
+
+<p>
+For more information on creating YUI instances and on the
+<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_use"><code>use()</code> method</a>, see the
+documentation for the <a href="../yui/index.html">YUI Global Object</a>.
+</p>
+
+
+<p>
+<strong>Note:</strong> be sure to add the <code>yui3-skin-sam</code> classname to the
+page's <code><body></code> element or to a parent element of the widget in order to apply
+the default CSS skin. See <a href="http://yuilibrary.com/yui/docs/tutorials/skins/">Understanding Skinning</a>.
+</p>
+
+<div class="notice">
+ <h2 id="migration-intro">Upgrading from version 3.4.1 or older?</h2>
+
+ <p>
+ DataTable was refactored for 3.5.0. Some APIs were changed in backward
+ incompatible ways.
+ </p>
+
+ <p>
+ Read the <a href="migration.html">3.5.0 Migration Guide</a> for tips to
+ avoid unpleasant surprises. If you still run into issues, please
+ <a href="../../../projects/yui3/newticket/">file a ticket</a>.
+ </p>
+
+ <p>
+ If you are unable to upgrade due to unresolvable issues, you can use the
+ <a href="../datatable-deprecated/index.html"><code>datatable-deprecated</code></a>
+ 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.
+ </p>
+</div>
+
+<h2 id="using">DataTable Basics</h2>
+
+<p>
+ A basic DataTable is made of columns and rows. Define the columns you
+ want to display in your DataTable with the <code>columns</code> attribute. Rows are
+ created for you based on the data you provide to the <code>data</code> attribute.
+</p>
+
+<p>
+ Under the hood, the DataTable class uses a
+ <a href="../model-list/index.html">ModelList</a> instance to manage the row
+ data properties. Read the <a href="#data">Table Data Configuration</a>
+ section below for details about how to load, configure, and work with the
+ table data.
+</p>
+
+<pre class="code prettyprint">// 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");</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="basic-example" class="yui3-skin-sam"></div>
+
+<script>
+YUI({ filter: 'raw' }).use('datatable-base', function (Y) {
+ // 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,
+ caption: "My first DataTable!",
+ summary: "Example DataTable showing basic instantiation configuration"
+ });
+
+ table.render("#basic-example");
+});
+</script>
+
+<h2 id="columns">Column Configuration</h2>
+
+<p>
+ The <code>columns</code> attribute takes an array of field names that correspond to
+ property names in the <code>data</code> 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.
+</p>
+
+
+<p>
+ Use objects instead of key strings to customize how the cells in a column
+ display.
+</p>
+
+<pre class="code prettyprint">// 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");</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="column-example1" class="yui3-skin-sam"></div>
+
+<script>
+YUI().use('datatable-base', function (Y) {
+ // 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", 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("#column-example1");
+});
+</script>
+
+<p>
+ Some column configurations affect the table headers and others affect the
+ data cells.
+</p>
+
+<p>
+ Use the <code>key</code> property to reference the associated data field when
+ configuring columns with objects. Other supported configuration
+ properties are listed in <a href="#column-config">Appendix A</a> below.
+</p>
+
+
+<h3 id="nested">Stacked Column Headers</h3>
+
+<p>
+ Use the <code>children</code> column configuration to create multiple rows of column
+ headers.
+</p>
+
+<pre class="code prettyprint">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");</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="nested-example" class="yui3-skin-sam"></div>
+
+<script>
+YUI().use('datatable-base', function (Y) {
+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: [
+ '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'
+ ]
+ }
+ ],
+ data : data
+}).render("#nested-example");
+});
+</script>
+
+<p>
+ <code>children</code> takes an array of column configurations, just like the <code>columns</code>
+ attribute itself. The columns defined in the <code>children</code> property will have
+ header cells rendered below the parent column's header.
+</p>
+
+<p>
+ Columns that have <code>children</code> don't relate directly to the data cells in the
+ table rows, so they <strong>should not</strong> have a <code>key</code> configured.
+ They should, however, include a <code>label</code> to provide the header's content.
+</p>
+
+<h3 id="formatters">Formatting Cell Data</h3>
+
+<p>
+ Customizing the content of the cells in your table is done using column
+ configurations. The most common formatting-related column configurations
+ are:
+</p>
+
+<ul>
+ <li>
+ <code>allowHTML</code> - set this to <code>true</code> if your cell data, <code>emptyCellValue</code>, or
+ <code>formatter</code> outputs HTML. By default, cell data is HTML escaped for
+ security.
+ </li>
+ <li>
+ <code>emptyCellValue</code> - string to populate cells where no data (empty
+ string, <code>undefined</code>, or <code>null</code>) is available in a record.
+ </li>
+ <li>
+ <code>formatter</code> - string or function used to translate the raw record data
+ for each cell in a given column into a format better suited to display.
+ </li>
+ <li>
+ <code>nodeFormatter</code> - function used to customize the DOM structure of a
+ cell, its row, or its surrounding elements. Use with caution.
+ </li>
+</ul>
+
+<p>
+ When the <code>formatter</code> configuration setting contains a string it will be assumed
+ to be the key into the hash of formatting functions at <code>Y.DataTable.BodyView.Formatters</code>.
+ 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 <code>{value}</code> 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.
+</p>
+<p>
+ The <code>Y.DataTable.BodyView.Formatters</code> is empty for the developers to provide
+ their own formatting functions. A basic set is provided in module
+ <code>datatable-formatters</code> that has to be explicitly loaded. Some of these
+ named formatters accept extra configuration settings in the column definition,
+ as described in their
+ <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.BodyView.Formatters.html">
+ API docs</a>.
+</p>
+<p>
+ <code>formatter</code> functions are expected to return the string content to populate each
+ cell in that column, and <code>nodeFormatter</code>s are provided with the cell Nodes
+ and expected to populate them using the Node API.
+</p>
+
+<p>
+ For best performance, <strong><a href="#formatter-vs-nodeformatter">avoid
+ <code>nodeFormatter</code>s unless absolutely necessary</a></strong>.
+</p>
+
+<pre class="code prettyprint">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));
+ }
+ }
+];</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="formatter-example" class="yui3-skin-sam">
+ <style scoped>
+ .yui3-datatable .yui3-datatable-data .expensive {
+ background-color: #ffe;
+ }
+ .yui3-skin-sam .yui3-datatable-data .auth td {
+ border-bottom: 1px dashed #cbcbcb;
+ }
+ .negative {
+ color: #700;
+ font-weight: 700;
+ }
+ tr.auth td {
+ text-align: right;
+ background-color: #fff;
+ border-top: 1px dashed #cbcbcb;
+ border-left: 1px solid #cbcbcb;
+ padding-right: 5px;
+ }
+ </style>
+</div>
+
+<script>
+YUI().use('datatable-base', function (Y) {
+ 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 > 10) {
+ 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');
+
+ 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.setHTML(prefix + profit.toFixed(2));
+ }
+ }
+ ];
+
+ 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: columns,
+ data : data
+ }).render("#formatter-example");
+});
+</script>
+
+<p>
+ The parameters passed to <code>formatter</code> functions and <code>nodeFormatter</code>
+ functions are described in <a href="#formatter-props">Appendix B</a> and <a
+ href="#nodeformatter-props">Appendix C</a>, respectively. Also look for
+ what can be passed in to the columns in
+ <a href="#column-config">Appendix A</a>.
+</p>
+
+<p>
+ <strong>Note</strong>: It's highly recommended to keep the data in the
+ underlying <code>data</code> 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.
+</p>
+
+<h4 id="formatter-function">Setting content with <code>formatter</code> functions</h4>
+
+<p>
+ Set the cell content with column <code>formatter</code>s by returning the desired
+ content string from the function. Alternately, just update <code>o.value</code> with
+ the new value in the object passed as an argument to the <code>formatter</code>. When
+ updating <code>o.value</code> <em>do not include a return statement</em>.
+</p>
+
+<p>
+ <code>formatters</code> 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.
+</p>
+
+<pre class="code prettyprint">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 },
+ ...</pre>
+
+<p>
+ If such a formatter will be used regularly, it is best to store it in the
+ <code>Y.DataTable.BodyView.Formatters</code> hash. The formatter can later be used
+ by its name.
+</p>
+<p>
+ Named formatters are structured slightly differently in
+ order to improve performance:
+</p>
+<pre class="code prettyprint">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);
+ }
+}</pre>
+
+<p>
+ The function stored in the <code>Formatters</code> 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.
+</p>
+<p>
+ An optional <code>datatable-formatters</code> module provides
+ a collection of such formatters.
+ See the <a href="../api/classes/DataTable.BodyView.Formatters.html">API docs</a>
+ for more information on them.
+</p>
+<p>
+ See <a href="#formatter-props">Appendix B</a> for a list of all properties
+ passed to <code>formatter</code> functions.
+</p>
+
+<h4 id="nodeformatters">Setting content with <code>nodeFormatter</code> functions</h4>
+
+<p>
+ Unlike <code>formatters</code> which can effectively default to the normal rendering
+ logic by leaving <code>o.value</code> unchanged, <code>nodeFormatters</code> 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.
+</p>
+
+<p>
+ <strong><code>nodeFormatter</code>s should return <code>false</code></strong>.
+ <a href="formatter-vs-nodeformatter">See below</a> for details.
+</p>
+
+<p>
+ While there are <a href="#formatter-vs-nodeformatter">few scenarios that
+ require <code>nodeFormatter</code>s</a>, 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 <code><tbody></code>. This means they can reference, and even modify,
+ cells in other rows.
+</p>
+
+<p>
+ Like <code>formatters</code>, <code>nodeFormatters</code> are provided with the data field value,
+ the record data, the record Model instance, and the column configuration
+ object.
+</p>
+
+<p>
+ See <a href="#nodeformatter-props">Appendix C</a> for a list of all
+ properties passed to <code>nodeFormatter</code> functions.
+</p>
+
+<h4 id="formatter-vs-nodeformatter">Why <code>formatter</code> and <code>nodeFormatter</code>?</h4>
+
+<p>
+ For good rendering performance and memory management, DataTable creates
+ table content by assembling <code>innerHTML</code> strings from templates, with
+ <code>{placeholder}</code> tokens replaced with your data. However, this means that
+ the Nodes don't exist yet when a column's <code>formatter</code>s are applied.
+</p>
+
+<p>
+ 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
+ <code>formatter</code> functions. Event subscriptions should be
+ <a href="http://yuilibrary.com/yui/docs/event/delegation.html">delegated</a>
+ from the DataTable instance itself using the
+ <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html#method_delegate"><code>delegate()</code> method</a>.
+</p>
+
+<p>
+ On the rare occasion that you <em>must</em> 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.
+</p>
+
+<p>
+ It is important to note that <code>nodeFormatters</code> 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
+ <code>nodeFormatter</code>, return <code>false</code> to remove them from the internal object
+ cache. <strong>This will not remove the rendered DOM, but it will remove
+ event subscriptions made on those Nodes</strong>.
+</p>
+
+<p>
+ In general, <code>nodeFormatter</code>s should only be used if absolutely necessary,
+ and should <em>always return <code>false</code></em>.
+</p>
+
+<h4 id="formatters-vs-empty">Formatters vs. <code>emptyCellValue</code></h4>
+
+<p>
+ The <code>emptyCellValue</code> 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.
+</p>
+
+<p>
+ String formatters will only be applied if the field data for that cell is
+ not <code>undefined</code>. This allows the <code>emptyCellValue</code> to populate the cell.
+</p>
+
+<p>
+ Function formatters are applied before the return value or (potentially
+ altered) <code>o.value</code> property is tested for <code>undefined</code>, <code>null</code>, or the empty
+ string. In any of these cases, the <code>emptyCellValue</code> populates the cell.
+</p>
+
+<p>
+ The <code>emptyCellValue</code> configuration is ignored by columns configured with
+ <code>nodeFormatter</code>s.
+</p>
+
+
+<h2 id="data">Table Data Configuration</h2>
+
+<p>
+ Each record in the table is stored as a
+ <a href="../model/index.html">Model</a> instance, where the
+ keys of the record objects become Model attributes. This allows you to
+ interact with the models as you would any other <a
+ href="../base/index.html">Base</a>-based class, with <code>get(attr)</code>,
+ <code>set(attr, value)</code>, and subscribing to attribute change events.
+</p>
+
+<pre class="code prettyprint">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);</pre>
+
+
+<p>
+ The Model class used to store the record data is created for you, based on
+ the objects in the <code>data</code> array. If <code>data</code> is not set, the column keys
+ identified in the <code>columns</code> configuration is used.
+</p>
+
+<h3 id="recordtype">Specifying the Record Model</h3>
+
+<p>
+ To use a custom Model for your records, pass your Model subclass to the
+ <code>recordType</code> attribute.
+</p>
+
+<pre class="code prettyprint">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();</pre>
+
+
+<p>
+ Alternately, <code>recordType</code> will accept an array of attribute strings or an
+ <code>ATTRS</code> configuration object to make it easier to create custom attribute
+ behaviors without needing to explicitly build the Model subclass.
+</p>
+
+<p>
+ If the <code>columns</code> configuration is omitted, but the <code>recordType</code> is set, the
+ <code>columns</code> will default to the <code>recordType</code>'s attributes.
+</p>
+
+<pre class="code prettyprint">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
+});</pre>
+
+
+<p>
+ When the table data is loaded asychronously, it is often a good idea to
+ configure the <code>recordType</code>. This can prevent the generation of a record
+ Model that is missing fields that are omitted from the <code>columns</code>
+ configuration because they aren't intended for viewing.
+</p>
+
+<h3 id="modellist">The <code>data</code> ModelList</h3>
+
+<p>
+ The record Models are stored in a
+ <a href="../model-list/index.html">ModelList</a>, which is assigned to the
+ <code>data</code> <em>property</em> on the instance (for easier access than going through <code>table.get('data')</code>).
+</p>
+
+<pre class="code prettyprint">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 });</pre>
+
+
+<p>
+ When assigning the DataTable's <code>data</code> 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
+ <a href="../model-list/#implementing-a-list-sync-layer">data sync layer</a>.
+</p>
+
+<pre class="code prettyprint">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');
+});</pre>
+
+
+<h3 id="getting-data">Getting Remote Table Data</h3>
+
+<p>
+ To fetch remote data, you have three options:
+</p>
+
+<ol>
+ <li>
+ <p>
+ <strong>For quick one-offs</strong>, you can load and parse the
+ data manually, using <code>Y.io(...)</code>, <code>Y.jsonp(...)</code>, etc., then assign
+ that data to the DataTable's <code>data</code> attribute. This isn't very
+ elegant or maintainable, so is best avoided for anything other than
+ proofs of concept.
+ </p>
+ </li>
+ <li>
+ <p>
+ <strong>For the most control</strong>, better maintainability, and
+ better encapsulation of business logic, create Model and ModelList
+ subclasses that
+ <a href="../model-list/#implementing-a-list-sync-layer">implement a
+ sync layer</a> as suggested above.
+ </p>
+ </li>
+ <li>
+ <p>
+ <strong>For common read-only scenarios</strong>, use the
+ <a href="http://yuilibrary.com/yui/docs/api/classes/Plugin.DataTableDataSource.html"><code>Y.Plugin.DataTableDataSource</code></a>
+ plugin to bind your table to a
+ <a href="../datasource/index.html"><code>DataSource</code></a> instance. Use
+ plugins to add DataSource features.
+ </p>
+ </li>
+</ol>
+
+
+<pre class="code prettyprint">// 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"');
+});</pre>
+
+
+<h2 id="features">DataTable Modules and Features</h2>
+
+<p>
+ For a basic, stripped down <code>Y.DataTable</code> class, include the <code>datatable-base</code>
+ module in your <code>use()</code>.
+</p>
+
+<p>
+ Feature modules, such as <code>datatable-sort</code>, will bring in <code>datatable-base</code>
+ automatically. By including only feature modules in your <code>use()</code>, you will
+ get a <code>Y.DataTable</code> that supports specifically those features, without
+ extra code for other features you won't be using.
+</p>
+
+<p>
+ The <code>datatable</code> module is a bundle of <code>datatable-base</code> plus a set of common
+ feature modules. Other feature modules need to be included explicitly in
+ <code>use()</code>.
+</p>
+
+<table>
+<thead>
+ <tr>
+ <th>Module</th>
+ <th>Description</th>
+ <th>In <code>datatable</code>?</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-core.html"><code>datatable-core</code></a></td>
+ <td>
+ The core API for DataTable, implemented as a class extension, used
+ by <code>datatable-base</code> to create <code>Y.DataTable</code> and <code>Y.DataTable.Base</code>.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-base.html"><code>datatable-base</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable</code> and <code>Y.DataTable.Base</code> classes, and
+ defaults the <code>headerView</code> and <code>bodyView</code> to <code>Y.DataTable.HeaderView</code>
+ and <code>Y.DataTable.BodyView</code> respectively.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-head.html"><code>datatable-head</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.HeaderView</code> class as a subclass of
+ <code>Y.View</code>. DataTable defers rendering of the <code><thead></code> content to
+ this View when it is passed as the DataTable's <code>headerView</code>
+ attribute (the default, as set by <code>datatable-base</code>).
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-body.html"><code>datatable-body</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.BodyView</code> class as a subclass of
+ <code>Y.View</code>. DataTable defers rendering of the <code><tbody></code> content to
+ this View when it is passed as the DataTable's <code>bodyView</code>
+ attribute (the default, as set by <code>datatable-base</code>).
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-message.html"><code>datatable-message</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.Message</code> class extension and adds
+ <code>showMessage</code> and <code>hideMessage</code> methods to <code>Y.DataTable</code>.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-column-widths.html"><code>datatable-column-widths</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.ColumnWidths</code> class extension, and adds
+ support for the <code>width</code> property in column configuration objects
+ to <code>Y.DataTable</code>.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-mutable.html"><code>datatable-mutable</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.Mutable</code> class extension and adds methods
+ such as <code>addRow</code>, <code>removeRow</code>, and <code>moveColumn</code> to <code>Y.DataTable</code>.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-sort.html"><code>datatable-sort</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.Sortable</code> class extension and adds methods
+ <code>sort</code> and <code>toggleSort</code> as well as attributes <code>sortable</code> and
+ <code>sortBy</code> to <code>Y.DataTable</code>. Enables sorting the table rows by
+ clicking on column headers.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-datasource.html"><code>datatable-datasource</code></a></td>
+ <td>
+ Creates the <code>Y.Plugin.DataTableDataSource</code> plugin for binding a
+ DataSource instance to the table as its source of record data.
+ </td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-scroll.html"><code>datatable-scroll</code></a></td>
+ <td>
+ Creates the <code>Y.DataTable.Scroll</code> class extension and adds attribute
+ <code>scrollable</code> to <code>Y.DataTable</code>. Adds support for vertically and/or
+ horizontally scrolling table rows within fixed table dimensions.
+ </td>
+ <td>no</td>
+ </tr>
+ <tr>
+ <td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-formatters.html"><code>datatable-formatters</code></a></td>
+ <td>
+ Populates <code>Y.DataTable.BodyView.Formatters</code> with a collection of
+ cell formatting functions.
+ </td>
+ <td>no</td>
+ </tr>
+</tbody>
+</table>
+
+<h3 id="base">Features in <code>DataTable.Base</code></h3>
+
+<p>
+ By including only <code>datatable-base</code> in your <code>use()</code> line, you get both
+ <code>Y.DataTable</code> and <code>Y.DataTable.Base</code> 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 <code>Y.DataTable</code>, but <strong>never</strong> to
+ <code>Y.DataTable.Base</code>.
+</p>
+
+<p>
+ Though it can be instantiated, the purpose of <code>Y.DataTable.Base</code> is
+ primarily as a superclass to a custom DataTable implementation that has a
+ locked set of features that will not be modified, as <code>Y.DataTable</code> can be,
+ by the inclusion of other modules.
+</p>
+
+<pre class="code prettyprint">// 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', ... });
+});</pre>
+
+
+<p>
+ <code>Y.DataTable.Base</code> includes the <code>columns</code>, <code>data</code>, <code>caption</code>, 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.
+</p>
+
+<p>
+ Rendering features include most column configurations, such as <code>children</code>
+ and <code>allowHTML</code>, as well as column formatting options <code>formatter</code>,
+ <code>nodeFormatter</code>, <code>cellTemplate</code>, etc.
+</p>
+
+<h3 id="datatable-message">Table Messages</h3>
+
+<p>
+ The <code>datatable-message</code> 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.
+</p>
+
+<pre class="code prettyprint">var table = new Y.DataTable({
+ columns: ["id", "name", "price"],
+ data: []
+}).render('#example');</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="message-example" class="yui3-skin-sam"></div>
+
+<script>
+YUI({ filter: 'raw' }).use('datatable-message', function (Y) {
+ var table = new Y.DataTable({
+ columns: ["id", "name", "price"],
+ data: []
+ }).render('#message-example');
+});
+</script>
+
+<p>
+ Use <code>table.showMessage("message")</code> and <code>table.hideMessage()</code> to toggle the
+ message display.
+</p>
+
+<p>
+ <code>showMessage</code> supports internationalized strings by using a few named
+ strings, which are registered in the language packs for the
+ <code>datatable-message</code> module . These strings are currently:
+</p>
+
+<ul>
+ <li>
+ <code>table.showMessage("emptyMessage")</code> defaults to "No data to display".
+ </li>
+ <li>
+ <code>table.showMessage("loadingMessage")</code> defaults to "Loading...".
+ </li>
+</ul>
+
+<p>
+ Other values passed to <code>showMessage</code> will pass that content directly
+ through to the message Node.
+</p>
+
+<h3 id="colwidths">Column Width Configuration</h3>
+
+<p>
+ The <code>datatable-column-widths</code> module adds basic support for specifying
+ column widths.
+</p>
+
+<pre class="code prettyprint">var table = new Y.DataTable({
+ columns: [
+ { key: 'item', width: '125px' },
+ { key: 'cost', formatter: '${value}' },
+ ...
+ ],
+ data : data
+}).render("#example");</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="colwidths-example" class="yui3-skin-sam"></div>
+
+<script>
+YUI({ filter: 'raw' }).use('datatable-column-widths', function (Y) {
+ 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: [
+ { key: 'item', width: '125px' },
+ { key: 'cost', formatter: '${value}' },
+ { key: 'price', formatter: '${value}' },
+ { key: 'profit', formatter: function (o) {
+ var price = o.data.price,
+ cost = o.data.cost;
+
+ return (((price - cost) / cost) * 100).toFixed(2) + '%';
+ }
+ }
+ ],
+ data : data
+ }).render("#colwidths-example");
+});
+</script>
+
+<p>
+ <strong>CAVEAT</strong>: 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 <code>width</code> attribute, or constrained by a
+ narrow containing element) is too narrow to fit all data at the configured
+ widths.
+</p>
+
+<p>
+ 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 <code><div></code> either by configuring the column's <code>formatter</code> or
+ <code>cellTemplate</code>, then assign the <code><div></code>'s CSS style with the desired width
+ (or "inherit"), plus <code>overflow: hidden;</code>. Then set the DataTable column's
+ <code>width</code> configuration accordingly.
+</p>
+
+<h3 id="sorting">Column sorting</h3>
+
+<p>
+ The <code>datatable-sort</code> module adds support for sorting the table rows either
+ through the added APIs or by clicking on the table headers.
+</p>
+
+<p>
+ By default, when <code>datatable-sort</code> is included, DataTables will inspects
+ the <code>columns</code> objects, looking for <code>sortable: true</code> to enable table sorting
+ by those columns, triggered by clicking on their respective headers.
+</p>
+<pre class="code prettyprint">var cols = [
+ { key: "Company", sortable: true },
+ { key: "Phone" },
+ { key: "Contact", sortable: true }
+];</pre>
+
+
+<p>
+ For convenience, you can enable header-click sorting for all columns by
+ setting the <code>sortable</code> attribute to <code>true</code>, or pass an array of column keys
+ to enable just those column's headers.
+</p>
+
+<pre class="code prettyprint">// Set all columns to be sortable
+var table = new Y.DataTable({
+ columns: ["Company", "Phone", "Contact"],
+ data: ...
+ sortable: true
+}).render("#example");</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="sort-example1" class="yui3-skin-sam"></div>
+
+<script>
+YUI({ filter: 'raw' }).use('datatable-sort', function (Y) {
+ var table = new Y.DataTable({
+ columns: ['Company', 'Phone', 'Contact'],
+ data: [
+ { Company: "Company Bee", Phone: "415-555-1234", Contact: "Sally Spencer"},
+ { Company: "Acme Company", Phone: "650-555-4444", Contact: "John Jones"},
+ { Company: "Indutrial Industries", Phone: "408-555-5678", Contact: "Robin Smith"}
+ ],
+ sortable: true
+ }).render('#sort-example1');
+});
+</script>
+
+<p>
+ Hold down the <code>shift</code> key while clicking on column headers to subsort by
+ that column. Doing so repeatedly will toggle the subsort direction.
+</p>
+
+<p>
+ As long as the <code>datatable-sort</code> 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.
+</p>
+
+<p>
+ 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.
+</p>
+
+<p>
+ Disable header-click sorting by setting <code>sortable</code> to <code>false</code>.
+</p>
+<p>
+ The default sort order is case insensitive, the sort order can be set to case sensitive
+ by using the <code>caseSensitive</code> attribute, see <a href="#column-config">Appendix A</a> below.
+</p>
+
+<h4 id="customsort">Custom Sorting</h4>
+
+<p>
+ Assign a function to a column's <code>sortFn</code> to support customized sorting. The
+ function will receive the two records being compared and a boolean flag
+ indicating a descending sort was requested.
+</p>
+
+<pre class="code prettyprint">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;
+ }
+ },
+ ...</pre>
+
+
+<p>
+ 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.
+</p>
+
+
+<h4 id="sortapi">Sorting Methods</h4>
+
+<p>
+ To sort the table in the code, call <code>table.sort(NAME OR KEY)</code>. To
+ toggle the sort direction, call <code>table.toggleSort(NAME OR KEY)</code>.
+</p>
+
+<pre class="code prettyprint">// Sorts the table by values in the price field in ascending order
+table.sort('price');
+
+// Flips to descending
+table.toggleSort('price');</pre>
+
+
+<p>
+ To sort by multiple columns, pass an array of column keys to <code>sort</code> or
+ <code>toggleSort</code>.
+</p>
+
+<p>
+ Calling <code>toggleSort</code> with no arguments will reverse all current sort
+ directions. Calling with specific column names or keys will toggle only
+ those columns.
+</p>
+
+<pre class="code prettyprint">// 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');</pre>
+
+
+<p>
+ To specify a sort direction, pass an object instead of a string to <code>sort</code>.
+ The object should have the column name as the key, and sort direction as its
+ value.
+</p>
+
+<pre class="code prettyprint">// Explicitly sort by price in descending order
+table.sort({ price: 'desc' });
+
+// Each column gets its own object
+table.sort([{ author: 'desc' }, { title: 'desc' }]);</pre>
+
+
+<p>
+ Acceptable values for the sort direction are "asc", "desc", 1, and -1. 1 is
+ equivalent to "asc", and -1 to "desc".
+</p>
+
+<h4 id="sortby">The <code>sortBy</code> Attribute</h4>
+
+<p>
+ Every sort operation updates the <code>sortBy</code> attribute. You can also trigger
+ a sort by setting this attribute directly. It accepts the same values as
+ the <code>sort</code> method.
+</p>
+
+<pre class="code prettyprint">// Sort by author in descending order, then by title in ascending order
+table.set('sortBy', [{ author: -1 }, 'title']);</pre>
+
+
+<p>
+ 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.
+</p>
+
+<pre class="code prettyprint">// Pre-sort the data
+var table = new Y.DataTable({
+ columns: ['item', 'cost', 'price'],
+ data: [...],
+ sortBy: { price: -1 }
+});</pre>
+
+
+<h4 id="sortevent">The <code>sort</code> Event</h4>
+
+<p>
+ Clicking on a column header, or calling the <code>sort</code> or <code>toggleSort</code> methods
+ will fire a <code>sort</code> method containing an <code>e.sortBy</code> 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.
+</p>
+
+<p>
+ Preventing the <code>sort</code> event will prevent the <code>sortBy</code> attribute from being
+ updated. Updating the <code>sortBy</code> attribute directly will not fire the <code>sort</code>
+ event, but will still sort the data and update the table.
+</p>
+
+<h3 id="mutation">Table Mutation APIs (<code>addRow</code>, etc)</h3>
+
+<p>
+ The <code>datatable-mutable</code> module adds APIs for adding, removing, and
+ modifying records and columns.
+</p>
+
+<h4 id="column-mutation">Column Mutation Methods</h4>
+
+<p>
+ Use the methods <code>addColumn</code>, <code>removeColumn</code>, <code>modifyColumn</code>, and
+ <code>moveColumn</code> to update the table's configured <code>columns</code>.
+</p>
+
+<pre class="code prettyprint">// 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) + '%)';
+ }
+});</pre>
+
+
+<p>
+ Each column mutation method fires an identically named event. See
+ <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html">the API docs</a> for details.
+</p>
+
+<h4 id="row-mutation">Row Mutation Methods</h4>
+
+<p>
+ Use the methods <code>addRow</code>, <code>addRows</code>, <code>removeRow</code>, and <code>modifyRow</code> to update
+ the table's ModelList.
+</p>
+
+<pre class="code prettyprint">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 });</pre>
+
+<p>
+ 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.
+</p>
+
+<pre class="code prettyprint">// Same as table.addRow(...);
+table.data.add({ item: 'collet', cost: 0.42, price: 2.65 });</pre>
+
+
+<p>
+ 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 <code>sync</code> set to <code>true</code>.
+</p>
+
+<pre class="code prettyprint">// 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 });</pre>
+
+
+<p>
+ If all modifications are destined for the server/origin, you can set the
+ <code>autoSync</code> attribute to <code>true</code>, and the row mutation methods will
+ automatically call into the sync layer.
+</p>
+
+<pre class="code prettyprint">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 });
+});</pre>
+
+
+<h3 id="scrolling">Scrolling</h3>
+
+<p>
+ <strong>Note:</strong> Scrolling is not currently supported on the Android
+ WebKit browser.
+</p>
+
+<p>
+ Scrolling functionality can be added to <code>Y.DataTable</code> by including
+ <code>datatable-scroll</code> module in your <code>use()</code>. <code>datatable-scroll</code> is
+ <strong>NOT</strong> included in the <code>datatable</code> rollup module, so must be
+ included separately.
+</p>
+
+<p>
+ Enable scrolling by setting the <code>scrollable</code> attribute, which accepts values
+ "x", "y", "xy", <code>true</code> (same as "xy"), or <code>false</code> (the default).
+</p>
+
+<p>
+ Note, vertical scrolling also requires the table's <code>height</code> attribute to be
+ set, and horizontal scrolling requires the <code>width</code> to be set.
+</p>
+
+<pre class="code prettyprint">// 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");</pre>
+
+
+<p>This code produces this table:</p>
+
+<div id="scroll-example" class="yui3-skin-sam"></div>
+
+<script>
+YUI().use('datatable-scroll', function (Y) {
+// 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" },
+ { "fish": "Chilean Seabass", "recommendation": "avoid" },
+ { "fish": "Cobia (Imported Farmed)", "recommendation": "avoid" },
+ { "fish": "Cod, Atlantic (Trawl-caught from Canadian and U.S. Atlantic)", "recommendation": "avoid" },
+ { "fish": "Cod, Pacific (Imported)", "recommendation": "avoid" },
+ { "fish": "Crab, King (Imported)", "recommendation": "avoid" },
+ { "fish": "Dab, Common (Danish Seine from Iceland)", "recommendation": "avoid" },
+ { "fish": "Flounder (Wild-caught from U.S. Atlantic, Except Summer Flounder)", "recommendation": "avoid" },
+ { "fish": "Hake, White", "recommendation": "avoid" },
+ { "fish": "Halibut, Atlantic (Wild-caught from U.S.)", "recommendation": "avoid" },
+ { "fish": "Lobster, Caribbean Spiny (Brazil)", "recommendation": "avoid" },
+ { "fish": "Mahi Mahi (Imported Longline)", "recommendation": "avoid" },
+ { "fish": "Marlin, Blue (Imported)", "recommendation": "avoid" },
+ { "fish": "Marlin, Striped", "recommendation": "avoid" },
+ { "fish": "Monkfish", "recommendation": "avoid" },
+ { "fish": "Octopus (Philippines)", "recommendation": "avoid" },
+ { "fish": "Orange Roughy", "recommendation": "avoid" },
+ { "fish": "Plaice, American (Wild-caught from U.S. Atlantic)", "recommendation": "avoid" },
+ { "fish": "Pollock, Atlantic (Danish Seine and Trawl from Iceland)", "recommendation": "avoid" },
+ { "fish": "Salmon (Farmed including Atlantic Except U.S. Farmed in Tank Systems)", "recommendation": "avoid" },
+ { "fish": "Sardines, Atlantic (Mediterranean)", "recommendation": "avoid" },
+ { "fish": "Shad, American (U.S. Atlantic Gillnet)", "recommendation": "avoid" },
+ { "fish": "Shark (Except Common Thresher and Shortfin Mako, from California and Hawaii)", "recommendation": "avoid" },
+ { "fish": "Shrimp (Imported Farmed Except Thailand Farmed in Fully Reciruclating Systems)", "recommendation": "avoid" },
+ { "fish": "Shrimp (Imported Wild-Caught Except Canadian)", "recommendation": "avoid" },
+ { "fish": "Shrimp (Mexico Farmed in Open Systems)", "recommendation": "avoid" },
+ { "fish": "Skates", "recommendation": "avoid" },
+ { "fish": "Snapper, Red (U.S. Gulf of Mexico Wild-caught)", "recommendation": "avoid" },
+ { "fish": "Snapper, Red (Imported Wild-caught)", "recommendation": "avoid" },
+ { "fish": "Sole (Wild-caught from U.S Atlantic)", "recommendation": "avoid" },
+ { "fish": "Sturgeon (Imported Wild-caught)", "recommendation": "avoid" },
+ { "fish": "Swordfish (Imported)", "recommendation": "avoid" }
+];
+
+var table = new Y.DataTable({
+ caption: 'Seafood tips for the US West Coast',
+ columns: ['fish', 'recommendation'],
+ data: data,
+ scrollable: "y",
+ height: "200px",
+ width: "400px" // scrollable is not set to x or xy, so no scrolling
+}).render("#scroll-example");
+});
+</script>
+
+<h2 id="events">DataTable Events</h2>
+
+<p>
+ DataTable is a composition of supporting class instances and extensions, so
+ to centralize event reporting, it is a bubble target for its <code>data</code>
+ ModelList as well as the View instances used for rendering.
+</p>
+
+<p>
+ 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.
+</p>
+
+<pre class="code prettyprint">// 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) { ... });</pre>
+
+
+<p>
+ 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 <code>recordType</code>, you can prefix Model events with the appropriate
+ prefix.
+</p>
+
+<pre class="code prettyprint">// 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();
+ }
+});</pre>
+
+
+<p>
+ The full list of events is included in <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html#events">the DataTable API docs</a>.
+</p>
+
+<h2 id="knownissues">Known Issues</h2>
+
+<ul>
+ <li>
+ Scrolling is
+ <a href="http://yuilibrary.com/projects/yui3/ticket/2529761">not
+ currently supported on Android</a> WebKit browser.
+ </li>
+ <li>
+ Scrolling DataTable
+ <a href="http://yuilibrary.com/projects/yui3/ticket/2531047">may not
+ appear scrollable</a> on iOS browsers or OS X 10.7 depending on the
+ system preference "Show scroll bars" (General).
+ </li>
+</ul>
+
+<h2 id="column-config">Appendix A: Column Configurations</h2>
+
+<p>
+ The properties below are supported in the column configuration objects
+ passed in the <code>columns</code> attribute array.
+</p>
+
+<div id="column-config-table" class="yui3-skin-sam">
+ <table>
+ <thead>
+ <tr>
+ <th scope="col">Configuration</th>
+ <th scope="col">Description</th>
+ <th scope="col">Module</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>key</td>
+ <td>
+<pre class="code prettyprint">{ key: 'username' }</pre>
+
+ <p>
+ Binds the column values to the named property in the <code>data</code>.
+ <p>
+ <p>
+ Optional if <code>formatter</code>, <code>nodeFormatter</code>, or <code>cellTemplate</code>
+ is used to populate the content.
+ </p>
+ <p>It should not be set if <code>children</code> is set.</p>
+ <p>
+ The value is used for the <code>_id</code> property unless the <code>name</code>
+ property is also set.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>name</td>
+ <td>
+<pre class="code prettyprint">{ name: 'fullname', formatter: ... }</pre>
+
+
+ <p>
+ Use this to assign a name to pass to <code>table.getColumn(NAME)</code>
+ or style columns with class "yui3-datatable-col-NAME" if a
+ column isn't assigned a <code>key</code>.
+ </p>
+ <p>
+ The value is used for the <code>_id</code> property.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>field</td>
+ <td>
+<pre class="code prettyprint">{ field: 'fullname', formatter: ... }</pre>
+
+
+ <p>An alias for <code>name</code> for backward compatibility.</p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>id</td>
+ <td>
+<pre class="code prettyprint">{
+ name: 'checkAll',
+ id: 'check-all',
+ label: ...
+ formatter: ...
+}</pre>
+
+ <p>
+ Overrides the default unique id assigned <code><th id="HERE"></code>.
+ </p>
+ <p>
+ <em>Use this with caution</em>, since it can result in
+ duplicate ids in the DOM.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>label</td>
+ <td>
+<pre class="code prettyprint">{ key: 'MfgPrtNum', label: 'Part Number' }</pre>
+
+
+ <p>HTML to populate the header <code><th></code> for the column.</p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>children</td>
+ <td>
+ <p>
+ Used to create stacked headers.
+ <a href="#nested">See the example above</a>.
+ </p>
+
+ <p>
+ Child columns may also contain <code>children</code>. There is no limit
+ to the depth of nesting.
+ </p>
+
+ <p>
+ Columns configured with <code>children</code> are for display only and
+ <strong>should not</strong> be configured with a <code>key</code>.
+ Configurations relating to the display of data, such as
+ <code>formatter</code>, <code>nodeFormatter</code>, <code>emptyCellValue</code>, etc. are
+ ignored.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>abbr</td>
+ <td>
+<pre class="code prettyprint">{
+ key : 'forecast',
+ label: '1yr Target Forecast',
+ abbr : 'Forecast'
+}</pre>
+
+
+ <p>Assigns the value <code><th abbr="HERE"></code>.</p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>title</td>
+ <td>
+<pre class="code prettyprint">{
+ key : 'forecast',
+ label: '1yr Target Forecast',
+ title: 'Target Forecast for the Next 12 Months'
+}</pre>
+
+
+ <p>Assigns the value <code><th title="HERE"></code>.</p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>headerTemplate</td>
+ <td>
+<pre class="code prettyprint">{
+ headerTemplate:
+ '<th id="{id}" ' +
+ 'title="Unread" ' +
+ 'class="{className}" ' +
+ '{_id}>&#9679;</th>'
+}</pre>
+
+
+ <p>
+ Overrides the default
+ <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.HeaderView.html#property_CELL_TEMPLATE">CELL_TEMPLATE</a>
+ used by <code>Y.DataTable.HeaderView</code> 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.
+ </p>
+
+ <p>
+ Use the <code>label</code> configuration if you don't need to
+ customize the <code><th></code> iteself.
+ </p>
+
+ <p>
+ Implementers are strongly encouraged to preserve at least
+ the <code>{id}</code> and <code>{_id}</code> placeholders in the custom value.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>cellTemplate</td>
+ <td>
+<pre class="code prettyprint">{
+ key: 'id',
+ cellTemplate:
+ '<td class="{className}">' +
+ '<input type="checkbox" ' +
+ 'id="{content}">' +
+ '</td>'
+}</pre>
+
+
+ <p>
+ Overrides the default
+ <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.BodyView.html#property_CELL_TEMPLATE">CELL_TEMPLATE</a>
+ used by <code>Y.DataTable.BodyView</code> to render the data cells
+ for this column. This is necessary when more control is
+ needed over the markup for the <code><td></code> itself, rather than
+ its content.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>formatter</td>
+ <td>
+ <p>
+ Used to customize the content of the data cells for this
+ column.
+ </p>
+
+ <p>
+ <a href="#formatters">See the example above</a>
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>nodeFormatter</td>
+ <td>
+ <p>
+ Used to customize the content of the data cells for this
+ column.
+ </p>
+
+ <p>
+ <a href="#formatters">See the example above</a>
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>emptyCellValue</td>
+ <td>
+<pre class="code prettyprint">{
+ key: 'price',
+ emptyCellValue: '???'
+}</pre>
+
+
+ <p>
+ Provides the default value to populate the cell if the data
+ for that cell is <code>undefined</code>, <code>null</code>, or an empty string.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>allowHTML</td>
+ <td>
+<pre class="code prettyprint">{
+ key: 'preview',
+ allowHTML: true
+}</pre>
+
+
+ <p>
+ Skips the security step of HTML escaping the value for cells
+ in this column. This is also necessary if <code>emptyCellValue</code>
+ is set with an HTML string.
+ </p>
+ <p>
+ <code>nodeFormatter</code>s ignore this configuration. If using a
+ <code>nodeFormatter</code>, it is recommended to use
+ <a href="http://yuilibrary.com/yui/docs/api/classes/Escape.html#method_html">Y.Escape.html()</a>
+ on any user supplied content that is to be displayed.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>className</td>
+ <td>
+<pre class="code prettyprint">{
+ key: 'symbol',
+ className: 'no-hide'
+}</pre>
+
+
+ <p>
+ A string of CSS classes that will be added to the <code><td></code>'s
+ <code>class</code> attribute.
+ </p>
+
+ <p>
+ Note, all cells will automatically have a class in the
+ form of "yui3-datatable-col-KEY" added to the <code><td></code>, where
+ KEY is the column's configured <code>name</code>, <code>key</code>, or <code>id</code> (in
+ that order of preference).
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>width</td>
+ <td>
+<pre class="code prettyprint">{ key: 'a', width: '400px' },
+{ key: 'b', width: '10em' }</pre>
+
+
+ <p>
+ Adds a style <code>width</code> setting to an associated <code><col></code>
+ element for the column.
+ </p>
+
+ <p>
+ 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 <code>width</code> configuration or
+ the natural width of the table's containing DOM elements.
+ </p>
+
+ <p>
+ If absolute widths are required, it can be accomplished with
+ some custom CSS and the use of a <code>cellTemplate</code>, or
+ <code>formatter</code>. See
+ <a href="http://yuilibrary.com/yui/docs/api/modules/datatable-column-widths.html">the
+ description of <code>datatable-column-widths</code></a> for an example
+ of how to do this.
+ </p>
+ </td>
+ <td><code>datatable-column-widths</code></td>
+ </tr>
+ <tr>
+ <td>sortable</td>
+ <td>
+<pre class="code prettyprint">{ key: 'lastLogin', sortable: true }</pre>
+
+
+ <p>
+ Used when the instance's <code>sortable</code> attribute is set to
+ "auto" (the default) to determine which columns will support
+ user sorting by clicking on the header.
+ </p>
+ <p>
+ If the instance's <code>key</code> attribute is not set, this
+ configuration is ignored.
+ </p>
+ </td>
+ <td><code>datatable-sort</code></td>
+ </tr>
+ <tr>
+ <td>caseSensitive</td>
+ <td>
+<pre class="code prettyprint">{ key: 'lastLogin', sortable: true, caseSensitive: true }</pre>
+
+
+ <p>
+ When the instance's <code>caseSensitive</code> attribute is set to
+ "true" the sort order is case sensitive (relevant to string columns only).
+ </p>
+ <p>
+ Case sensitive sort is marginally more efficient and should be considered
+ for large data sets when case insensitive sort is not required.
+ </p>
+ </td>
+ <td><code>datatable-sort</code></td>
+ </tr>
+ <tr>
+ <td>sortFn</td>
+ <td>
+<pre class="code prettyprint">{
+ 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;
+ }
+}</pre>
+
+
+ <p>
+ 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
+ <code>true</code> if the sort order should be descending.
+ </p>
+ <p>
+ The function should return <code>-1</code> to sort <code>a</code> above <code>b</code>, <code>-1</code>
+ to sort <code>a</code> below <code>b</code>, and <code>0</code> if they are equal. Keep in
+ mind that the order should be reversed when <code>desc</code> is
+ <code>true</code>.
+ </p>
+ <p>
+ The <code>desc</code> parameter is provided to allow <code>sortFn</code>s to
+ always sort certain values above or below others, such as
+ always sorting <code>null</code>s on top.
+ </p>
+ </td>
+ <td><code>datatable-sort</code></td>
+ </tr>
+ <tr>
+ <td>sortDir</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) If a column is sorted, this
+ will be set to <code>1</code> for ascending order or <code>-1</code> 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
+ <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html#attr_sortBy">sortBy</a>
+ attribute for that.
+ </p>
+ </td>
+ <td><code>datatable-sort</code></td>
+ </tr>
+ <tr>
+ <td>_yuid</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) The unique identifier assigned
+ to each column. This is used for the <code>id</code> if not set, and
+ the <code>_id</code> if none of <code>name</code>, 'field<code>, </code>key<code>, or </code>id` are
+ set.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>_id</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) 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
+ <code>table.getColumn(HERE)</code>, and in the column header's
+ <code><th data-yui3-col-id="HERE"></code>.
+ </p>
+ <p>
+ The value is populated by the first of <code>name</code>, <code>field</code>,
+ <code>key</code>, <code>id</code>, or <code>_yuid</code> to have a value. If that value
+ has already been used (such as when multiple columns have
+ the same <code>key</code>), an incrementer is added to the end. For
+ example, two columns with <code>key: "id"</code> will have <code>_id</code>s of
+ "id" and "id2". <code>table.getColumn("id")</code> will return the
+ first column, and <code>table.getColumn("id2")</code> will return the
+ second.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>_colspan</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) Used by
+ <code>Y.DataTable.HeaderView</code> when building stacked column
+ headers.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>_rowspan</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) Used by
+ <code>Y.DataTable.HeaderView</code> when building stacked column
+ headers.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>_parent</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) Assigned to all columns in a
+ column's <code>children</code> collection. References the parent
+ column object.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ <tr>
+ <td>_headers</td>
+ <td>
+ <p>
+ (<strong>read-only</strong>) Array of the <code>id</code>s of the
+ column and all parent columns. Used by
+ <code>Y.DataTable.BodyView</code> to populate <code><td headers="THIS"></code>
+ when a cell references more than one header.
+ </p>
+ </td>
+ <td><code>datatable-base</code></td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+<h2 id="formatter-props">Appendix B: Formatter Argument Properties</h2>
+
+<p>
+ The properties below are found on the object passed to <code>formatter</code>
+ functions defined in a column configuration. See
+ <a href="#nodeformatter-props">Appendix C</a> for the object properties
+ passed to <code>nodeFormatter</code>s.
+</p>
+
+<div id="formatter-props-table" class="yui3-skin-sam">
+ <table>
+ <thead>
+ <tr>
+ <th scope="col">Property</th>
+ <th scope="col">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>value</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ // assumes a numeric value for this column
+ return '$' + o.value.toFixed(2);
+}</pre>
+
+
+ <p>
+ The raw value from the record Model to populate this cell.
+ Equivalent to <code>o.record.get(o.column.key)</code> or
+ <code>o.data[o.column.key]</code>.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>data</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ return o.data.lname + ', ' + o.data.fname;
+}</pre>
+
+
+ <p>
+ The Model data for this row in simple object format.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>record</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ return '<a href="/service/' + o.record.get('id') + '">' +
+ o.value + '</a>';
+}</pre>
+
+
+ <p>
+ The Model for this row.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>column</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ // Use a custom column property
+ var format = o.column.dateFormat || '%D';
+
+ return Y.DataType.Data.format(o.value, format);
+}</pre>
+
+
+ <p>
+ The column configuration object.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>className</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ if (o.value < 0) {
+ o.className += 'loss';
+ }
+}</pre>
+
+
+ <p>
+ A string of class names to add <code><td class="HERE"></code> in
+ addition to the column class and any classes in the
+ column's <code>className</code> configuration.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>rowIndex</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ return (o.rowIndex + 1) + ' - ' + o.value;
+}</pre>
+
+
+ <p>
+ The index of the current Model in the ModelList.
+ <em>Typically</em> correlates to the row index as well.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>rowClass</code></td>
+ <td>
+<pre class="code prettyprint">formatter: function (o) {
+ if (o.value < 0) {
+ o.rowClass += 'loss';
+ }
+}</pre>
+
+
+ <p>
+ A string of css classes to add <code><tr class="HERE"><td...</code>.
+ </p>
+
+ <p>
+ This is useful to avoid the need for <code>nodeFormatter</code>s to add
+ classes to the containing row.
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+<h2 id="nodeformatter-props">Appendix C: nodeFormatter Argument Properties</h2>
+
+<p>
+ The properties below are found on the object passed to <code>nodeFormatter</code>
+ functions defined in a column configuration. See
+ <a href="#formatter-props">Appendix B</a> for the object properties
+ passed to <code>formatter</code>s.
+</p>
+
+<pre class="code prettyprint">// 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);
+}</pre>
+
+
+<div id="nodeformatter-props-table" class="yui3-skin-sam">
+ <table>
+ <thead>
+ <tr>
+ <th scope="col">Property</th>
+ <th scope="col">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>td</code></td>
+ <td>The <code><td></code> Node for this cell.</td>
+ </tr>
+ <tr>
+ <td><code>cell</code></td>
+ <td>
+ <p>
+ If the cell <code><td></code> contains an element with class
+ "yui3-datatable-liner", this will refer to that Node.
+ Otherwise, it is equivalent to <code>o.td</code> (default behavior).
+ </p>
+
+ <p>
+ By default, liner elements aren't rendered into cells, but
+ to implement absolute column widths, some cell liner
+ element with <code>width</code> and <code>overflow</code> style is required
+ (barring a table style of <code>table-layout: fixed</code>). This may
+ be applied to the columns <code>cellTemplate</code> configuration or
+ to the <code>bodyView</code> instance's <code>CELL_TEMPLATE</code> for all
+ columns.
+ </p>
+
+ <p>
+ Generally, the liner, if present, corresponds to where the
+ content should go, so use <code>o.cell</code> to add content and
+ <code>o.td</code> to specifically work with the <code><td></code> Node.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>value</code></td>
+ <td>
+ The raw value from the record Model to populate this cell.
+ Equivalent to <code>o.record.get(o.column.key)</code> or
+ <code>o.data[o.column.key]</code>.
+ </td>
+ </tr>
+ <tr>
+ <td><code>data</code></td>
+ <td>The Model data for this row in simple object format.</td>
+ </tr>
+ <tr>
+ <td><code>record</code></td>
+ <td>The Model for this row.</td>
+ </tr>
+ <tr>
+ <td><code>column</code></td>
+ <td>The column configuration object.</td>
+ </tr>
+ <tr>
+ <td><code>rowIndex</code></td>
+ <td>
+ The index of the current Model in the ModelList.
+ <em>Typically</em> correlates to the row index as well.
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+<script>
+YUI.add('datatable-node', function (Y) {
+ Y.Plugin.DataTable = Y.Base.create('datatable', Y.DataTable, [], {
+ initializer: function (config) {
+ var columns = config.host.all('thead th').get('text'),
+ count = columns.length,
+ data = [],
+ i;
+
+ config.host.all('tbody td').each(function (node, i) {
+ var record = (i % count) ?
+ data[data.length - 1] :
+ (data[data.length] = {});
+ record[columns[i % count]] = node.getHTML();
+ });
+
+ for (i = columns.length - 1; i >= 0; --i) {
+ columns[i] = { key: columns[i], allowHTML: true }
+ }
+
+ this.setAttrs({
+ columns : columns,
+ data : data
+ });
+
+ this.render();
+
+ config.host.replace(this.get('boundingBox'));
+ }
+ }, {
+ NS: 'table'
+ });
+
+ Y.Node.ATTRS.datatable = {
+ setter: function (val) {
+ if (val === true) {
+ val = {};
+ }
+
+ this.plug(Y.Plugin.DataTable, val);
+ }
+ };
+}, '0.1', { requires: ['datatable-base', 'node-pluginhost'] });
+YUI({ filter: 'raw' }).use('datatable-node', 'datatable-sort', function (Y) {
+ Y.one('#column-config-table table').set('datatable', {
+ sortable: ['Configuration', 'Module']
+ });
+ Y.one('#formatter-props-table table').set('datatable', true);
+ Y.one('#nodeformatter-props-table table').set('datatable', true);
+});
+</script>
+</div>
+ </div>
+ </div>
+
+ <div class="yui3-u-1-4">
+ <div class="sidebar">
+
+ <div id="toc" class="sidebox">
+ <div class="hd">
+ <h2 class="no-toc">Table of Contents</h2>
+ </div>
+
+ <div class="bd">
+ <ul class="toc">
+<li>
+<a href="#getting-started">Getting Started</a>
+</li>
+<li>
+<a href="#migration-intro">Upgrading from version 3.4.1 or older?</a>
+</li>
+<li>
+<a href="#using">DataTable Basics</a>
+</li>
+<li>
+<a href="#columns">Column Configuration</a>
+<ul class="toc">
+<li>
+<a href="#nested">Stacked Column Headers</a>
+</li>
+<li>
+<a href="#formatters">Formatting Cell Data</a>
+<ul class="toc">
+<li>
+<a href="#formatter-function">Setting content with <code>formatter</code> functions</a>
+</li>
+<li>
+<a href="#nodeformatters">Setting content with <code>nodeFormatter</code> functions</a>
+</li>
+<li>
+<a href="#formatter-vs-nodeformatter">Why <code>formatter</code> and <code>nodeFormatter</code>?</a>
+</li>
+<li>
+<a href="#formatters-vs-empty">Formatters vs. <code>emptyCellValue</code></a>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+<li>
+<a href="#data">Table Data Configuration</a>
+<ul class="toc">
+<li>
+<a href="#recordtype">Specifying the Record Model</a>
+</li>
+<li>
+<a href="#modellist">The <code>data</code> ModelList</a>
+</li>
+<li>
+<a href="#getting-data">Getting Remote Table Data</a>
+</li>
+</ul>
+</li>
+<li>
+<a href="#features">DataTable Modules and Features</a>
+<ul class="toc">
+<li>
+<a href="#base">Features in <code>DataTable.Base</code></a>
+</li>
+<li>
+<a href="#datatable-message">Table Messages</a>
+</li>
+<li>
+<a href="#colwidths">Column Width Configuration</a>
+</li>
+<li>
+<a href="#sorting">Column sorting</a>
+<ul class="toc">
+<li>
+<a href="#customsort">Custom Sorting</a>
+</li>
+<li>
+<a href="#sortapi">Sorting Methods</a>
+</li>
+<li>
+<a href="#sortby">The <code>sortBy</code> Attribute</a>
+</li>
+<li>
+<a href="#sortevent">The <code>sort</code> Event</a>
+</li>
+</ul>
+</li>
+<li>
+<a href="#mutation">Table Mutation APIs (<code>addRow</code>, etc)</a>
+<ul class="toc">
+<li>
+<a href="#column-mutation">Column Mutation Methods</a>
+</li>
+<li>
+<a href="#row-mutation">Row Mutation Methods</a>
+</li>
+</ul>
+</li>
+<li>
+<a href="#scrolling">Scrolling</a>
+</li>
+</ul>
+</li>
+<li>
+<a href="#events">DataTable Events</a>
+</li>
+<li>
+<a href="#knownissues">Known Issues</a>
+</li>
+<li>
+<a href="#column-config">Appendix A: Column Configurations</a>
+</li>
+<li>
+<a href="#formatter-props">Appendix B: Formatter Argument Properties</a>
+</li>
+<li>
+<a href="#nodeformatter-props">Appendix C: nodeFormatter Argument Properties</a>
+</li>
+</ul>
+ </div>
+ </div>
+
+
+
+ <div class="sidebox">
+ <div class="hd">
+ <h2 class="no-toc">Examples</h2>
+ </div>
+
+ <div class="bd">
+ <ul class="examples">
+
+
+ <li data-description="This example illustrates simple DataTable use cases.">
+ <a href="datatable-basic.html">Basic DataTable</a>
+ </li>
+
+
+
+ <li data-description="DataTable loaded with JSON data from a remote webservice via DataSource.Get">
+ <a href="datatable-dsget.html">DataTable + DataSource.Get + JSON Data</a>
+ </li>
+
+
+
+ <li data-description="DataTable loaded with XML data from a remote webservice via DataSource.IO.">
+ <a href="datatable-dsio.html">DataTable + DataSource.IO + XML Data</a>
+ </li>
+
+
+
+ <li data-description="Custom format data for display.">
+ <a href="datatable-formatting.html">Formatting Row Data for Display</a>
+ </li>
+
+
+
+ <li data-description="DataTable with nested column headers.">
+ <a href="datatable-nestedcols.html">Nested Column Headers</a>
+ </li>
+
+
+
+ <li data-description="DataTable with column sorting.">
+ <a href="datatable-sort.html">Column Sorting</a>
+ </li>
+
+
+
+ <li data-description="DataTable with vertical and/or horizontal scrolling rows.">
+ <a href="datatable-scroll.html">Scrolling DataTable</a>
+ </li>
+
+
+
+ <li data-description="Using DataTable's recordType attribute to create calculated, sortable columns.">
+ <a href="datatable-recordtype.html">Sortable generated columns</a>
+ </li>
+
+
+
+ <li data-description="Populating one DataTable from details in the data of another.">
+ <a href="datatable-masterdetail.html">Master and detail tables</a>
+ </li>
+
+
+
+ <li data-description="Checkbox column that retains checked state when sorting.">
+ <a href="datatable-chkboxselect.html">Checkbox select column</a>
+ </li>
+
+
+
+
+ </ul>
+ </div>
+ </div>
+
+
+
+ <div class="sidebox">
+ <div class="hd">
+ <h2 class="no-toc">Examples That Use This Component</h2>
+ </div>
+
+ <div class="bd">
+ <ul class="examples">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <li data-description="Shows how to instantiate multiple Panel instances, and use nested modality to interact with a Datatable.">
+ <a href="../panel/panel-form.html">Creating a Modal Form</a>
+ </li>
+
+
+ </ul>
+ </div>
+ </div>
+
+ </div>
+ </div>
+ </div>
+</div>
+
+<script src="../assets/vendor/prettify/prettify-min.js"></script>
+<script>prettyPrint();</script>
+
+<script>
+YUI.Env.Tests = {
+ examples: [],
+ project: '../assets',
+ assets: '../assets/datatable',
+ name: 'datatable',
+ title: 'DataTable',
+ newWindow: '',
+ auto: false
+};
+YUI.Env.Tests.examples.push('datatable-basic');
+YUI.Env.Tests.examples.push('datatable-dsget');
+YUI.Env.Tests.examples.push('datatable-dsio');
+YUI.Env.Tests.examples.push('datatable-formatting');
+YUI.Env.Tests.examples.push('datatable-nestedcols');
+YUI.Env.Tests.examples.push('datatable-sort');
+YUI.Env.Tests.examples.push('datatable-scroll');
+YUI.Env.Tests.examples.push('datatable-recordtype');
+YUI.Env.Tests.examples.push('datatable-masterdetail');
+YUI.Env.Tests.examples.push('datatable-chkboxselect');
+YUI.Env.Tests.examples.push('panel-form');
+
+</script>
+<script src="../assets/yui/test-runner.js"></script>
+
+
+
+</body>
+</html>