src/cm/media/js/lib/yui/yui_3.10.3/docs/datatable/index.html
changeset 525 89ef5ed3c48b
--- /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">&lt;script src=&quot;http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.10.3&#x2F;build&#x2F;yui&#x2F;yui-min.js&quot;&gt;&lt;&#x2F;script&gt;</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">&lt;script&gt;
+&#x2F;&#x2F; Create a new YUI instance and populate it with the required modules.
+YUI().use(&#x27;datatable&#x27;, function (Y) {
+    &#x2F;&#x2F; DataTable is available and ready for use. Add implementation
+    &#x2F;&#x2F; code here.
+});
+&lt;&#x2F;script&gt;</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>&lt;body&gt;</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">&#x2F;&#x2F; Columns must match data object property names
+var data = [
+    { id: &quot;ga-3475&quot;, name: &quot;gadget&quot;,   price: &quot;$6.99&quot;, cost: &quot;$5.99&quot; },
+    { id: &quot;sp-9980&quot;, name: &quot;sprocket&quot;, price: &quot;$3.75&quot;, cost: &quot;$3.25&quot; },
+    { id: &quot;wi-0650&quot;, name: &quot;widget&quot;,   price: &quot;$4.25&quot;, cost: &quot;$3.75&quot; }
+];
+
+var table = new Y.DataTable({
+    columns: [&quot;id&quot;, &quot;name&quot;, &quot;price&quot;],
+    data: data,
+
+    &#x2F;&#x2F; Optionally configure your table with a caption
+    caption: &quot;My first DataTable!&quot;,
+
+    &#x2F;&#x2F; and&#x2F;or a summary (table attribute)
+    summary: &quot;Example DataTable showing basic instantiation configuration&quot;
+});
+
+table.render(&quot;#example&quot;);</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">&#x2F;&#x2F; Columns must match data object property names
+var data = [
+    { id: &quot;ga-3475&quot;, name: &quot;gadget&quot;,   price: &quot;$6.99&quot;, cost: &quot;$5.99&quot; },
+    { id: &quot;sp-9980&quot;, name: &quot;sprocket&quot;, price: &quot;$3.75&quot;, cost: &quot;$3.25&quot; },
+    { id: &quot;wi-0650&quot;, name: &quot;widget&quot;,   &#x2F;* missing *&#x2F;   cost: &quot;$3.75&quot; }
+];
+
+var table = new Y.DataTable({
+    columns: [
+        &quot;id&quot;,
+        { key: &quot;name&quot;, label: &quot;part name&quot; },
+        { key: &quot;price&quot;, allowHTML: true, emptyCellValue: &quot;&lt;em&gt;(not set)&lt;&#x2F;em&gt;&quot; },
+        &quot;cost&quot;
+    ],
+    data: data
+});
+
+table.render(&quot;#example&quot;);</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 = [
+    &#x27;username&#x27;,
+    {
+        &#x2F;&#x2F; Important: Parent columns do NOT get a key...
+
+        &#x2F;&#x2F; but DO get a label
+        label: &quot;Access&quot;,
+
+        &#x2F;&#x2F; Pass an array of column configurations (strings or objects) as children
+        children: [
+            &#x27;read&#x27;,
+            &#x27;write&#x27;,
+        ]
+    }
+];
+
+var data = [
+    { username: &quot;root&quot;, read: true, write: true },
+    { username: &quot;spilgrim&quot;, read: true, write: false },
+    { username: &quot;fizzgig&quot;, read: false, write: false }
+];
+
+var table = new Y.DataTable({
+    columns: columns,
+    data   : data
+}).render(&quot;#example&quot;);</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: &#x27;item&#x27;,
+        formatter: &#x27;&lt;a href=&quot;#{value}&quot;&gt;{value}&lt;&#x2F;a&gt;&#x27;,
+        allowHTML: true &#x2F;&#x2F; Must be set or the html will be escaped
+    },
+    {
+        key: &#x27;cost&#x27;,
+        formatter: &#x27;${value}&#x27; &#x2F;&#x2F; formatter template string
+    },
+    {
+        key: &#x27;price&#x27;,
+        formatter: function (o) {
+            if (o.value &gt; 3) {
+                o.className += &#x27;expensive&#x27;;
+            }
+
+            return &#x27;$&#x27; + o.value.toFixed(2);
+        }
+    },
+    {
+        label: &#x27;profit&#x27;,
+        nodeFormatter: function (o) {
+            var profit = o.data.price - o.data.cost,
+                prefix = &#x27;$&#x27;,
+                row;
+
+            if (profit &lt; 0) {
+                prefix = &#x27;-&#x27; + prefix;
+                profit = Math.abs(profit);
+                row = o.cell.ancestor();
+
+                o.cell.addClass(&#x27;negative&#x27;);
+
+                &#x2F;&#x2F; Assign a rowspan to the first cell and add a new row
+                &#x2F;&#x2F; below this one to span the last three columns
+                row.one(&#x27;td&#x27;).setAttribute(&#x27;rowspan&#x27;, 2);
+
+                row.insert(
+                    &#x27;&lt;tr class=&quot;auth&quot;&gt;&lt;td colspan=&quot;3&quot;&gt;&#x27; +
+                        &#x27;&lt;button class=&quot;ok&quot;&gt;authorize&lt;&#x2F;button&gt;&#x27; +
+                        &#x27;&lt;button class=&quot;stop&quot;&gt;discontinue&lt;&#x2F;button&gt;&#x27; +
+                    &#x27;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;&#x27;,
+                    &#x27;after&#x27;);
+            }
+
+            o.cell.set(&#x27;text&#x27;, 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     || &#x27;$&#x27;,
+        decimalPlaces     : o.column.decimalPlaces      || 2,
+        decimalSeparator  : o.column.decimalSeparator   || &#x27;.&#x27;,
+        thousandsSeparator: o.column.thousandsSeparator || &#x27;,&#x27;
+    });
+}
+
+var cols = [
+    { key: &quot;price&quot;, 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) {
+    &#x2F;&#x2F; This is done just once per rendering cycle:
+    var fn = Y.DataType.Number.format,
+        format = {
+            prefix            : col.currencySymbol     || &#x27;$&#x27;,
+            decimalPlaces     : col.decimalPlaces      || 2,
+            decimalSeparator  : col.decimalSeparator   || &#x27;.&#x27;,
+            thousandsSeparator: col.thousandsSeparator || &#x27;,&#x27;
+        };
+    return function (o) {
+        &#x2F;&#x2F; 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>&lt;tbody&gt;</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: &quot;widget&quot;,   cost: 23.57, price: 47.5 },
+    { item: &quot;gadget&quot;,   cost: 0.11, price: 6.99 },
+    { item: &quot;sprocket&quot;, cost: 4.08, price: 3.75 },
+    { item: &quot;nut&quot;,      cost: 0.01, price: 0.25 }
+];
+
+var table = new Y.DataTable({
+    columns: [&quot;item&quot;, &quot;cost&quot;, &quot;price&quot;],
+    data: data
+});
+
+var sprocket = table.getRecord(2);
+
+&#x2F;&#x2F; Fires a costChange event, and the table is updated if rendered
+sprocket.set(&#x27;cost&#x27;, 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: [&#x27;slices&#x27;, &#x27;type&#x27;],
+    data: [
+        &#x2F;&#x2F; Y.PieModel has attributes &#x27;slices&#x27;, which defaults to 6, and &#x27;type&#x27;,
+        &#x2F;&#x2F; which defaults to &#x27;apple&#x27;. Records can use these defaults.
+        { type: &#x27;lemon meringue&#x27; },
+        { type: &#x27;chocolate creme&#x27;, slices: 8 },
+        {} &#x2F;&#x2F; equivalent to { type: &#x27;apple&#x27;, slices: 6 }
+    ]
+});
+
+&#x2F;&#x2F; Y.PieModel has its idAttribute assigned to &#x27;type&#x27;, overriding the default
+&#x2F;&#x2F; of &#x27;id&#x27;.  Fetch a PieModel by its id.
+var applePie = pieTable.getRecord(&#x27;apple&#x27;);
+
+&#x2F;&#x2F; 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: &quot;widget&quot;,   cost: 23.57, price: 47.5 },
+    { item: &quot;gadget&quot;,   cost: 0.11, price: 6.99 },
+    { item: &quot;sprocket&quot;, cost: 4.08, price: 3.75 },
+    { item: &quot;nut&quot;,      cost: 0.01, price: 0.25 }
+];
+
+&#x2F;&#x2F; Effectively synonymous with setting the columns attribute if no special
+&#x2F;&#x2F; column configuration is needed.
+var table = new Y.DataTable({
+    recordType: [ &#x27;item&#x27;, &#x27;cost&#x27;, &#x27;price&#x27; ],
+    data: data
+});
+
+&#x2F;&#x2F; 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(&#x27;cost&#x27;) + 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(&#x27;data&#x27;)</code>).
+</p>
+
+<pre class="code prettyprint">var records = [
+    { item: &quot;widget&quot;,   cost: 23.57, price: 47.5 },
+    { item: &quot;gadget&quot;,   cost: 0.11, price: 6.99 },
+    { item: &quot;sprocket&quot;, cost: 4.08, price: 3.75 }
+];
+
+var table = new Y.DataTable({
+    columns: [&quot;item&quot;, &quot;cost&quot;, &quot;price&quot;],
+    data   : records
+});
+
+&#x2F;&#x2F; Add a new Model using the ModelList API. This will fire
+&#x2F;&#x2F; events and change the table if rendered.
+table.data.add({ item: &quot;nut&quot;, 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: [&#x27;type&#x27;, &#x27;slices&#x27;],
+    data: new Y.PieList()
+});
+
+&#x2F;&#x2F; The Y.PieList class implements a sync layer, enabling its load() method
+table.data.load(function () {
+    table.render(&#x27;#pies&#x27;);
+});</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">&#x2F;&#x2F; Create a JSONP DataSource to query YQL
+var myDataSource = new Y.DataSource.Get({
+    source: &#x27;http:&#x2F;&#x2F;query.yahooapis.com&#x2F;v1&#x2F;public&#x2F;yql?format=json&amp;&#x27; +
+            &#x27;env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&amp;q=&#x27;
+});
+
+myDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
+        schema: {
+            resultListLocator: &#x27;query.results.Result&#x27;,
+            resultFields: [
+                &#x27;Title&#x27;,
+                &#x27;Phone&#x27;,
+                {
+                    &#x2F;&#x2F; Important that record fields NOT include &quot;.&quot;, so
+                    &#x2F;&#x2F; extract nested data with locators
+                    key: &#x27;Rating&#x27;,
+                    locator: &quot;Rating.AverageRating&quot;
+                }
+            ]
+        }
+    })
+    .plug(Y.Plugin.DataSourceCache, {
+        max: 3
+    });
+
+&#x2F;&#x2F; No data is provided at construction because it will load via the
+&#x2F;&#x2F; DataTableDataSource plugin
+var table = new Y.DataTable({
+    columns: [&#x27;Title&#x27;, &#x27;Phone&#x27;, &#x27;Rating&#x27;],
+    summary: &#x27;Pizza places near 98089&#x27;
+});
+
+table.plug(Y.Plugin.DataTableDataSource, {
+    datasource: myDataSource
+})
+
+&#x2F;&#x2F; Initially render an empty table and show a loading message
+table.render(&#x27;#pizza&#x27;)
+     .showMessage(&#x27;loadingMessage&#x27;);
+
+&#x2F;&#x2F; Load the data into the table
+table.datasource.load({
+    request: encodeURIComponent(
+        &#x27;select *&#x27; +
+        &#x27; from   local.search&#x27; +
+        &#x27; where  zip=&quot;94089&quot;&#x27; +
+        &#x27; and    query=&quot;pizza&quot;&#x27;);
+});</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>&lt;thead&gt;</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>&lt;tbody&gt;</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">&#x2F;&#x2F; Create a custom DataTable that includes only the core set of APIs, plus
+&#x2F;&#x2F; sorting and message support.
+Y.MyDataTable = Y.Base.create(&#x27;myTable&#x27;, Y.DataTable.Base,
+    [ Y.DataTable.Sortable, Y.DataTable.Message ]);
+
+Y.use(&#x27;datatable-scroll&#x27;, function (Y) {
+    &#x2F;&#x2F; Y.DataTable now has support for scrolling
+    var table = new Y.DataTable({ scrollable: &#x27;y&#x27;, ... });
+
+    &#x2F;&#x2F; Y.MyDataTable does not (the config does nothing)
+    var myTable = new Y.MyDataTable({ scrollable: &#x27;y&#x27;, ... });
+});</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: [&quot;id&quot;, &quot;name&quot;, &quot;price&quot;],
+    data: []
+}).render(&#x27;#example&#x27;);</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(&quot;message&quot;)</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(&quot;emptyMessage&quot;)</code> defaults to "No data to display".
+    </li>
+    <li>
+        <code>table.showMessage(&quot;loadingMessage&quot;)</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: &#x27;item&#x27;, width: &#x27;125px&#x27; },
+        { key: &#x27;cost&#x27;, formatter: &#x27;${value}&#x27; },
+        ...
+    ],
+    data   : data
+}).render(&quot;#example&quot;);</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>&lt;div&gt;</code> either by configuring the column's <code>formatter</code> or
+    <code>cellTemplate</code>, then assign the <code>&lt;div&gt;</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: &quot;Company&quot;, sortable: true },
+    { key: &quot;Phone&quot; },
+    { key: &quot;Contact&quot;, 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">&#x2F;&#x2F; Set all columns to be sortable
+var table = new Y.DataTable({
+    columns: [&quot;Company&quot;, &quot;Phone&quot;, &quot;Contact&quot;],
+    data: ...
+    sortable: true
+}).render(&quot;#example&quot;);</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: &#x27;id&#x27;,
+        label: &#x27;&amp;#9679;&#x27;, &#x2F;&#x2F; a big dot
+        formatter: function (o) {
+            return o.value ? &#x27;&#x27; : &#x27;&amp;#9679;&#x27;; &#x2F;&#x2F; only new records have a dot
+        },
+        sortable: true,
+        sortFn: function (a, b, desc) {
+            var aid   = a.get(&#x27;id&#x27;),
+                bid   = b.get(&#x27;id&#x27;),
+                acid  = a.get(&#x27;clientId&#x27;),
+                bcid  = b.get(&#x27;clientId&#x27;),
+                order = &#x2F;&#x2F; existing records are equivalent
+                        (aid &amp;&amp; bid) ? 0 :
+                        &#x2F;&#x2F; new records are grouped apart from existing records
+                        (aid &amp;&amp; -1) || (bid &amp;&amp; 1) ||
+                        &#x2F;&#x2F; new records are sorted by insertion order
+                        (acid &gt; bcid) ? 1 : -(acid &lt; 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">&#x2F;&#x2F; Sorts the table by values in the price field in ascending order
+table.sort(&#x27;price&#x27;);
+
+&#x2F;&#x2F; Flips to descending
+table.toggleSort(&#x27;price&#x27;);</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">&#x2F;&#x2F; Sort first by author, subsort by title in ascending order
+table.sort([&#x27;author&#x27;, &#x27;title&#x27;]);
+
+&#x2F;&#x2F; Now descending by author then title
+&#x2F;&#x2F; same as table.toggleSort([&#x27;author&#x27;, &#x27;title&#x27;]);
+table.toggleSort();
+
+&#x2F;&#x2F; Now ascending by author, descending by title
+table.toggleSort(&#x27;author&#x27;);</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">&#x2F;&#x2F; Explicitly sort by price in descending order
+table.sort({ price: &#x27;desc&#x27; });
+
+&#x2F;&#x2F; Each column gets its own object
+table.sort([{ author: &#x27;desc&#x27; }, { title: &#x27;desc&#x27; }]);</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">&#x2F;&#x2F; Sort by author in descending order, then by title in ascending order
+table.set(&#x27;sortBy&#x27;, [{ author: -1 }, &#x27;title&#x27;]);</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">&#x2F;&#x2F; Pre-sort the data
+var table = new Y.DataTable({
+    columns: [&#x27;item&#x27;, &#x27;cost&#x27;, &#x27;price&#x27;],
+    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">&#x2F;&#x2F; Insert a column for the profit field in the data records as the third column
+table.addColumn(&#x27;profit&#x27;, 2);
+
+&#x2F;&#x2F; Actually, make that the fourth column
+table.moveColumn(&#x27;profit&#x27;, 3);
+
+&#x2F;&#x2F; Actually, strike that.  Don&#x27;t show it after all
+table.removeColumn(&#x27;profit&#x27;);
+
+&#x2F;&#x2F; Instead, add a formatter to the price column that includes the profit data
+table.modifyColumn(&#x27;price&#x27;, {
+    formatter: function (o) {
+        return o.value + &#x27; (&#x27; + (o.data.profit &#x2F; o.data.cost).toFixed(2) + &#x27;%)&#x27;;
+    }
+});</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: &#x27;collet&#x27;, cost: 0.42, price: 2.65 });
+
+table.addRows([
+    { item: &#x27;nut&#x27;,    cost: 0.42, price: 2.65 },
+    { item: &#x27;washer&#x27;, cost: 0.01, price: 0.08 },
+    { item: &#x27;bit&#x27;,    cost: 0.19, price: 0.97 }
+]);
+
+&#x2F;&#x2F; Remove table records by their Model, id, clientId, or index
+table.removeRow(0);
+
+&#x2F;&#x2F; Modify a record by passing its id, clientId, or index, followed by an
+&#x2F;&#x2F; object with new field values
+table.modifyRow(&#x27;record_4&#x27;, { 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">&#x2F;&#x2F; Same as table.addRow(...);
+table.data.add({ item: &#x27;collet&#x27;, 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">&#x2F;&#x2F; Tell the server we&#x27;re down to one slice of apple pie!
+table.modifyRow(&#x27;apple&#x27;, { slices: 1 }, { sync: true });
+
+&#x2F;&#x2F; Uh oh, make that 0.  No more apple pie :(
+table.removeRow(&#x27;apple&#x27;, { 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: [&#x27;type&#x27;, &#x27;slices&#x27;],
+    data: new Y.PieList()
+    autoSync: true
+});
+
+pies.data.load(function () {
+
+    pies.render(&#x27;#pie-cart&#x27;);
+
+    &#x2F;&#x2F; The new PieModel&#x27;s save() method is called, notifying the server
+    pies.addRow({ type: &#x27;pecan&#x27;, slices: 8 });
+
+    &#x2F;&#x2F; Let us eat some pie!
+    pies.modifyRow(&#x27;lemon meringue&#x27;, { 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">&#x2F;&#x2F; Data from the seafoodwatch YQL table as of 3&#x2F;16&#x2F;2012
+var data = [
+    { &quot;fish&quot;: &quot;Barramundi (Imported Farmed in Open Systems)&quot;, &quot;recommendation&quot;: &quot;avoid&quot; },
+    { &quot;fish&quot;: &quot;Caviar, Paddlefish (Wild caught from U.S.)&quot;, &quot;recommendation&quot;: &quot;avoid&quot; },
+    { &quot;fish&quot;: &quot;Caviar, Sturgeon (Imported Wild-caught)&quot;, &quot;recommendation&quot;: &quot;avoid&quot; },
+    ...
+];
+
+&#x2F;&#x2F; Enable vertical scrolling with scrollable &quot;y&quot;. The width is also set, but
+&#x2F;&#x2F; because scrollable is not &quot;x&quot; or &quot;xy&quot;, this just sets the table width.
+var table = new Y.DataTable({
+    caption: &#x27;Seafood tips for the US West Coast&#x27;,
+    columns: [&#x27;fish&#x27;, &#x27;recommendation&#x27;],
+    data: data,
+    scrollable: &quot;y&quot;,
+    height: &quot;200px&quot;,
+    width:  &quot;400px&quot;
+}).render(&quot;#scroll&quot;);</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">&#x2F;&#x2F; The sort event is from an extension, so it originates from DataTable
+table.after(&#x27;sort&#x27;, function (e) { ... });
+
+&#x2F;&#x2F; Model changes originate from the record&#x27;s Model instance, propagate to the
+&#x2F;&#x2F; table&#x27;s ModelList, then finally to the DataTable, so they must be
+&#x2F;&#x2F; subscribed with an event prefix.  In this case, we&#x27;ll use a wildcard
+&#x2F;&#x2F; prefix.
+table.after(&#x27;*:priceChange&#x27;, 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">&#x2F;&#x2F; Allow DataTable to generate the Model class automatically
+var table = new Y.DataTable({
+    columns: [&#x27;items&#x27;, &#x27;cost&#x27;, &#x27;price&#x27;],
+    data: [
+        { item: &quot;widget&quot;, cost: 23.57, price: 47.5 },
+        { item: &quot;gadget&quot;, cost: 0.11, price: 6.99 },
+        ...
+    ]
+});
+
+&#x2F;&#x2F; generated Model classes have prefix &quot;record&quot;
+table.after(&#x27;record:change&#x27;, function (e) { ... });
+
+&#x2F;&#x2F; PieList uses PieModels, which have a prefix of, you guessed it, &quot;pie&quot;
+var pies = new Y.DataTable({
+    columns: [&#x27;type&#x27;, &#x27;slices&#x27;],
+    data: new Y.PieList()
+});
+
+pies.on(&#x27;pie:slicesChange&#x27;, function (e) {
+    if (e.target.get(&#x27;type&#x27;) === &#x27;chocolate creme&#x27;) {
+        &#x2F;&#x2F; Oh no you don&#x27;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: &#x27;username&#x27; }</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: &#x27;fullname&#x27;, 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: &#x27;fullname&#x27;, 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: &#x27;checkAll&#x27;,
+  id: &#x27;check-all&#x27;,
+  label: ...
+  formatter: ...
+}</pre>
+
+                <p>
+                    Overrides the default unique id assigned <code>&lt;th id=&quot;HERE&quot;&gt;</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: &#x27;MfgPrtNum&#x27;, label: &#x27;Part Number&#x27; }</pre>
+
+
+                <p>HTML to populate the header <code>&lt;th&gt;</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  : &#x27;forecast&#x27;,
+  label: &#x27;1yr Target Forecast&#x27;,
+  abbr : &#x27;Forecast&#x27;
+}</pre>
+
+
+                <p>Assigns the value <code>&lt;th abbr=&quot;HERE&quot;&gt;</code>.</p>
+            </td>
+            <td><code>datatable-base</code></td>
+        </tr>
+        <tr>
+            <td>title</td>
+            <td>
+<pre class="code prettyprint">{
+  key  : &#x27;forecast&#x27;,
+  label: &#x27;1yr Target Forecast&#x27;,
+  title: &#x27;Target Forecast for the Next 12 Months&#x27;
+}</pre>
+
+
+                <p>Assigns the value <code>&lt;th title=&quot;HERE&quot;&gt;</code>.</p>
+            </td>
+            <td><code>datatable-base</code></td>
+        </tr>
+        <tr>
+            <td>headerTemplate</td>
+            <td>
+<pre class="code prettyprint">{
+  headerTemplate:
+    &#x27;&lt;th id=&quot;{id}&quot; &#x27; +
+        &#x27;title=&quot;Unread&quot; &#x27; +
+        &#x27;class=&quot;{className}&quot; &#x27; +
+        &#x27;{_id}&gt;&amp;#9679;&lt;&#x2F;th&gt;&#x27;
+}</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>&lt;th&gt;</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: &#x27;id&#x27;,
+  cellTemplate:
+    &#x27;&lt;td class=&quot;{className}&quot;&gt;&#x27; +
+      &#x27;&lt;input type=&quot;checkbox&quot; &#x27; +
+             &#x27;id=&quot;{content}&quot;&gt;&#x27; +
+    &#x27;&lt;&#x2F;td&gt;&#x27;
+}</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>&lt;td&gt;</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: &#x27;price&#x27;,
+  emptyCellValue: &#x27;???&#x27;
+}</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: &#x27;preview&#x27;,
+  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: &#x27;symbol&#x27;,
+  className: &#x27;no-hide&#x27;
+}</pre>
+
+
+                <p>
+                    A string of CSS classes that will be added to the <code>&lt;td&gt;</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>&lt;td&gt;</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: &#x27;a&#x27;, width: &#x27;400px&#x27; },
+{ key: &#x27;b&#x27;, width: &#x27;10em&#x27; }</pre>
+
+
+                <p>
+                    Adds a style <code>width</code> setting to an associated <code>&lt;col&gt;</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: &#x27;lastLogin&#x27;, 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: &#x27;lastLogin&#x27;, 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: &#x27;Name&#x27;,
+  sortFn: function (a, b, desc) {
+    var an = a.get(&#x27;lname&#x27;) + b.get(&#x27;fname&#x27;),
+        bn = a.get(&#x27;lname&#x27;) + b.get(&#x27;fname&#x27;),
+        order = (an &gt; bn) ? 1 : -(an &lt; bn);
+
+    return desc ? -order : order;
+  },
+  formatter: function (o) {
+    return o.data.lname + &#x27;, &#x27; + 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>&lt;th data-yui3-col-id=&quot;HERE&quot;&gt;</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: &quot;id&quot;</code> will have <code>_id</code>s of
+                    "id" and "id2".  <code>table.getColumn(&quot;id&quot;)</code> will return the
+                    first column, and <code>table.getColumn(&quot;id2&quot;)</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>&lt;td headers=&quot;THIS&quot;&gt;</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) {
+    &#x2F;&#x2F; assumes a numeric value for this column
+    return &#x27;$&#x27; + 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 + &#x27;, &#x27; + 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 &#x27;&lt;a href=&quot;&#x2F;service&#x2F;&#x27; + o.record.get(&#x27;id&#x27;) + &#x27;&quot;&gt;&#x27; +
+        o.value + &#x27;&lt;&#x2F;a&gt;&#x27;;
+}</pre>
+
+
+                <p>
+                    The Model for this row.
+                </p>
+            </td>
+        </tr>
+        <tr>
+            <td><code>column</code></td>
+            <td>
+<pre class="code prettyprint">formatter: function (o) {
+    &#x2F;&#x2F; Use a custom column property
+    var format = o.column.dateFormat || &#x27;%D&#x27;;
+
+    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 &lt; 0) {
+        o.className += &#x27;loss&#x27;;
+    }
+}</pre>
+
+
+                <p>
+                    A string of class names to add <code>&lt;td class=&quot;HERE&quot;&gt;</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) + &#x27; - &#x27; + 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 &lt; 0) {
+        o.rowClass += &#x27;loss&#x27;;
+    }
+}</pre>
+
+
+                <p>
+                    A string of css classes to add <code>&lt;tr class=&quot;HERE&quot;&gt;&lt;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">&#x2F;&#x2F; Reference nodeFormatter
+nodeFormatter: function (o) {
+    if (o.value &lt; o.data.quota) {
+        o.td.setAttribute(&#x27;rowspan&#x27;, 2);
+        o.td.setAttribute(&#x27;data-term-id&#x27;, this.record.get(&#x27;id&#x27;));
+
+        o.td.ancestor().insert(
+            &#x27;&lt;tr&gt;&lt;td colspan&quot;3&quot;&gt;&#x27; +
+                &#x27;&lt;button class=&quot;term&quot;&gt;terminate&lt;&#x2F;button&gt;&#x27; +
+            &#x27;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;&#x27;,
+            &#x27;after&#x27;);
+    }
+
+    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>&lt;td&gt;</code> Node for this cell.</td>
+        </tr>
+        <tr>
+            <td><code>cell</code></td>
+            <td>
+                <p>
+                    If the cell <code>&lt;td&gt;</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>&lt;td&gt;</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&#x27;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>