Show:
                            /**
                             * The Aria Component.
                             *
                             * @module aui-aria
                             * @submodule aui-aria-table-sortable
                             */
                            
                            var Lang = A.Lang;
                            
                            /**
                             * An extension for A.Plugin.Aria that creates and synchronizes a
                             * screen-reader-friendly `caption` element for the table that
                             * has sortable headers.
                             *
                             * @class TableSortable
                             * @param {Object} config Object literal specifying widget configuration
                             *     properties.
                             * @constructor
                             */
                            
                            function TableSortable() {}
                            
                            /**
                             * Configuration for TableSortable.
                             *
                             * @property ATTRS
                             * @type Object
                             * @static
                             */
                            TableSortable.ATTRS = {
                            
                                /**
                                 * The CSS class to be added to the caption element.
                                 *
                                 * @attribute captionCss
                                 * @default ''
                                 * @type String
                                 */
                                captionCss: {
                                    validator: Lang.isString,
                                    value: ''
                                },
                            
                                /**
                                 * The value of the 'aria-live' attribute.
                                 *
                                 * @attribute captionLive
                                 * @default ''
                                 * @type String
                                 */
                                captionLive: {
                                    validator: Lang.isString,
                                    value: 'polite'
                                },
                            
                                /**
                                 * The caption node in the table.
                                 *
                                 * @attribute captionNode
                                 * @type Node
                                 */
                                captionNode: {
                                    setter: function(val) {
                                        var instance = this;
                            
                                        if (!val) {
                                            val = A.Node.create(Lang.sub(
                                                    instance.TPL_CAPTION, {
                                                        captionCss: instance.get('captionCss')
                                                    }
                                                )
                                            );
                                        }
                            
                                        return A.one(val);
                                    },
                                    value: null
                                },
                            
                                /**
                                 * The role for the caption element.
                                 *
                                 * @attribute captionRole
                                 * @default 'alert'
                                 * @type String
                                 */
                                captionRole: {
                                    validator: Lang.isString,
                                    value: 'alert'
                                },
                            
                                /**
                                 * If the caption element is visible
                                 *
                                 * @attribute captionVisible
                                 * @default false
                                 * @type boolean
                                 */
                                captionVisible: {
                                    validator: Lang.isBoolean,
                                    value: false
                                },
                            
                                /**
                                 * The class to used to hide the caption element but
                                 * leave readable for screen readers.
                                 *
                                 * @attribute screenReaderClass
                                 * @default 'sr-only'
                                 * @type String
                                 */
                                screenReaderClass: {
                                    validator: Lang.isString,
                                    value: 'sr-only'
                                },
                            
                                /**
                                 * Object containing strings stating how the table is sorted.
                                 *
                                 * @attribute stringsSortable
                                 * @default {
                                 *       asc: 'ascending',
                                 *       desc: 'descending',
                                 *       sorted: 'sorted',
                                 *       sortedBy: 'sorted by',
                                 *       notSorted: 'not sorted'
                                 *   }
                                 * @type Object
                                 */
                                stringsSortable: {
                                    value: {
                                        asc: 'ascending',
                                        desc: 'descending',
                                        sorted: 'sorted',
                                        sortedBy: 'sorted by',
                                        notSorted: 'not sorted'
                                    }
                                },
                            
                                /**
                                 * The table node containing the columns to be sorted.
                                 *
                                 * @attribute tableNode
                                 * @type Node
                                 */
                                tableNode: {
                                    setter: A.one,
                                    valueFn: function() {
                                        return this.get('host').get('boundingBox').one('table');
                                    },
                                    writeOnce: true
                                }
                            };
                            
                            TableSortable.prototype = {
                                TPL_CAPTION: '<caption class="{captionCss}"></caption>',
                            
                                /**
                                 * Construction logic executed during TableSortable instantiation. Lifecycle.
                                 *
                                 * @method initializer
                                 * @protected
                                 */
                                initializer: function() {
                                    var instance = this;
                            
                                    instance.after('captionVisibleChange', A.bind(instance._afterCaptionVisibleChange, instance));
                                    instance.get('host').after('sort', A.bind(instance._afterSort, instance));
                                },
                            
                                /**
                                 * Synchronizes the captionNode's text for screen readers with the sorted
                                 * column and its sort direction.
                                 *
                                 * @method syncCaption
                                 * @param {String} columnName
                                 * @param {Boolean} ascending
                                 */
                                syncCaption: function(columnName, ascending) {
                                    var instance = this,
                                        caption = instance._getCaption(),
                                        strings = instance.get('stringsSortable');
                            
                                    caption.text(
                                        Lang.sub(
                                            strings.sortedBy + ': {columnName} {direction}',
                                            {
                                                columnName: columnName,
                                                direction: ascending ? strings.asc : strings.desc
                                            }
                                        )
                                    );
                                },
                            
                                /**
                                 * Handles `captionVisible` events.
                                 *
                                 * @method _afterCaptionVisibleChange
                                 * @param {EventFacade} event
                                 * @protected
                                 */
                                _afterCaptionVisibleChange: function() {
                                    var instance = this;
                            
                                    instance._toggleScreenReaderClass();
                                },
                            
                                /**
                                 * Handles `sort` events from the host.
                                 *
                                 * @method _afterSort
                                 * @param {EventFacade} event
                                 * @protected
                                 */
                                _afterSort: function(event) {
                                    var instance = this,
                                        ascending,
                                        columnName,
                                        sortBy = event.sortBy[0];
                            
                                    columnName = A.Object.keys(sortBy)[0];
                                    ascending = (A.Object.values(sortBy)[0] > 0);
                                    instance.syncCaption(columnName, ascending);
                                },
                            
                                /**
                                 * Returns a reference to the `captionNode`, and accomplishes
                                 * necessary setup to prepare the element for screen readers.
                                 *
                                 * @method _getCaption
                                 * @protected
                                 */
                                _getCaption: function() {
                                    var instance = this,
                                        caption = instance.get('captionNode');
                            
                                    if (!caption.inDoc()) {
                                        instance.get('tableNode').prepend(caption);
                            
                                        caption.setAttribute('aria-live', instance.get('captionLive'));
                                        caption.setAttribute('role', instance.get('captionRole'));
                            
                                        instance._toggleScreenReaderClass();
                                    }
                            
                                    return caption;
                                },
                            
                                /**
                                 * Toggles the screen reader CSS class.
                                 *
                                 * @method _toggleScreenReaderClass
                                 * @protected
                                 */
                                _toggleScreenReaderClass: function() {
                                    var instance = this,
                                        caption = instance._getCaption();
                            
                                    caption.toggleClass(instance.get('screenReaderClass'), !instance.get('captionVisible'));
                                }
                            };
                            
                            A.Base.mix(A.Plugin.Aria, [TableSortable]);