sort.js revision f5443cec5378e1eba162c289f05b690b699c9c7b
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith/**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithAdds support for sorting the table data by API methods `table.sort(...)` or
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith`table.toggleSort(...)` or by clicking on column headers in the rendered UI.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithSorting by the API is enabled automatically when this module is `use()`d. To
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithenable UI triggered sorting, set the DataTable's `sortable` attribute to
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith`true`.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith<pre><code>
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithvar table = new Y.DataTable({
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith columns: [ 'id', 'username', 'name', 'birthdate' ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith data: [ ... ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith sortable: true
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith});
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithtable.render('#table');
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith</code></pre>
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithSetting `sortable` to `true` will enable UI sorting for all columns. To enable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithUI sorting for certain columns only, set `sortable` to an array of column keys,
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithor just add `sortable: true` to the respective column configuration objects.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithThis uses the default setting of `sortable: auto` for the DataTable instance.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith<pre><code>
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithvar table = new Y.DataTable({
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith columns: [
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith 'id',
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith { key: 'username', sortable: true },
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith { key: 'name', sortable: true },
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith { key: 'birthdate', sortable: true }
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith data: [ ... ]
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith // sortable: 'auto' is the default
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith});
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith// OR
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithvar table = new Y.DataTable({
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith columns: [ 'id', 'username', 'name', 'birthdate' ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith data: [ ... ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith sortable: [ 'username', 'name', 'birthdate' ]
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith});
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith</code></pre>
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithTo disable UI sorting for all columns, set `sortable` to `false`. This still
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithpermits sorting via the API methods.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithAs new records are inserted into the table's `data` ModelList, they will be inserted at the correct index to preserve the sort order.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithThe current sort order is stored in the `sortBy` attribute. Assigning this value at instantiation will automatically sort your data.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithSorting is done by a simple value comparison using &lt; and &gt; on the field
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithvalue. If you need custom sorting, add a sort function in the column's
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith`sortFn` property. Columns whose content is generated by formatters, but don't
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithrelate to a single `key`, require a `sortFn` to be sortable.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith<pre><code>
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithfunction nameSort(a, b) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith var aa = a.get('lastName'),
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith bb = a.get('lastName');
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith if (aa === bb) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith aa = a.get('firstName');
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith bb = b.get('firstName');
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith }
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith return (aa > bb) ? 1 : (aa < bb) ? -1 : 0;
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smithvar table = new Y.DataTable({
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith columns: [ 'id', 'username', { key: name, sortFn: nameSort }, 'birthdate' ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith data: [ ... ],
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith sortable: [ 'username', 'name', 'birthdate' ]
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith});
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith</code></pre>
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke SmithSee the user guide for more details.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith@module datatable-sort
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@class DataTable.Sortable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith@for DataTable
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith**/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smithvar YLang = Y.Lang,
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith isBoolean = YLang.isBoolean,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith isString = YLang.isString,
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith isArray = YLang.isArray,
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith isObject = YLang.isObject,
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith toArray = Y.Array,
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith dirMap = {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith asc : 1,
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith desc: -1,
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith "1" : 1,
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith "-1": -1
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith };
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smithfunction Sortable() {}
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke SmithSortable.ATTRS = {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith // Which columns in the UI should suggest and respond to sorting interaction
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith // pass an empty array if no UI columns should show sortable, but you want the
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith // table.sort(...) API
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Controls which column headers can trigger sorting by user clicks.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Acceptable values are:
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * "auto" - (default) looks for `sortable: true` in the column configurations
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `true` - all columns are enabled
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `false - no UI sortable is enabled
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * {String[]} - array of key names to give sortable headers
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @attribute sortable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {String|String[]|Boolean}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @default "auto"
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith sortable: {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith value: 'auto',
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith validator: '_validateSortable'
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith },
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith The current sort configuration to maintain in the data.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Accepts column `key` strings or objects with a single property, the column
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith `key`, with a value of 1, -1, "asc", or "desc". E.g. `{ username: 'asc'
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith }`. String values are assumed to be ascending.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Example values would be:
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `"username"` - sort by the data's `username` field or the `key`
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith associated to a column with that `name`.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `{ username: "desc" }` - sort by `username` in descending order.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Alternately, use values "asc", 1 (same as "asc"), or -1 (same as "desc").
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `["lastName", "firstName"]` - ascending sort by `lastName`, but for
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith records with the same `lastName`, ascending subsort by `firstName`.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Array can have as many items as you want.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `[{ lastName: -1 }, "firstName"]` - descending sort by `lastName`,
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith ascending subsort by `firstName`. Mixed types are ok.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @attribute sortBy
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {String|String[]|Object|Object[]}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith sortBy: {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith validator: '_validateSortBy',
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith getter: '_getSortBy'
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Strings containing language for sorting tooltips.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @attribute strings
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @type {Object}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @default (strings for current lang configured in the YUI instance config)
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith strings: {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith valueFn: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return Y.Intl.get('datatable-sort');
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith};
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke SmithY.mix(Sortable.prototype, {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Sort the data in the `data` ModelList and refresh the table with the new
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith order.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Acceptable values for `fields` are `key` strings or objects with a single
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith property, the column `key`, with a value of 1, -1, "asc", or "desc". E.g.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith `{ username: 'asc' }`. String values are assumed to be ascending.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Example values would be:
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `"username"` - sort by the data's `username` field or the `key`
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith associated to a column with that `name`.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `{ username: "desc" }` - sort by `username` in descending order.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Alternately, use values "asc", 1 (same as "asc"), or -1 (same as "desc").
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `["lastName", "firstName"]` - ascending sort by `lastName`, but for
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith records with the same `lastName`, ascending subsort by `firstName`.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Array can have as many items as you want.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith * `[{ lastName: -1 }, "firstName"]` - descending sort by `lastName`,
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith ascending subsort by `firstName`. Mixed types are ok.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @method sort
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @param {String|String[]|Object|Object[]} fields The field(s) to sort by
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {Object} [payload] Extra `sort` event payload you want to send along
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @return {DataTable}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @chainable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith sort: function (fields, payload) {
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith return this.fire('sort', Y.merge((payload || {}), {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy: fields || this.get('sortBy')
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith /**
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith Reverse the current sort direction of one or more fields currently being
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith sorted by.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Pass the `key` of the column or columns you want the sort order reversed
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith for.
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @method toggleSort
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @param {String|String[]} fields The field(s) to reverse sort order for
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {Object} [payload] Extra `sort` event payload you want to send along
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @return {DataTable}
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith @chainable
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith toggleSort: function (columns, payload) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var current = this._sortBy,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy = [],
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith i, len, j, col, index;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // To avoid updating column configs or sortBy directly
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (i = 0, len = current.length; i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith col = {};
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith col[current[i]._id] = current[i].sortDir;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy.push(col);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (columns) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith columns = toArray(columns);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith for (i = 0, len = columns.length; i < len; ++i) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith col = columns[i];
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith index = -1;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith for (j = sortBy.length - 1; i >= 0; --i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (sortBy[j][col]) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy[j][col] *= -1;
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith break;
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith } else {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith for (i = 0, len = sortBy.length; i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (col in sortBy[i]) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (sortBy[i].hasOwnProperty(col)) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy[i][col] *= -1;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith break;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
59c94cbcd6e39e484a57bf3665a8ab98beafc57eLuke Smith return this.fire('sort', Y.merge((payload || {}), {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith sortBy: sortBy
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith }));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith //--------------------------------------------------------------------------
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // Protected properties and methods
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith //--------------------------------------------------------------------------
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Applies the sorting logic to the new ModelList if the `newVal` is a new
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith ModelList.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _afterDataChange
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {EventFacade} e the `dataChange` event
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _afterDataChange: function (e) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // object values always trigger a change event, but we only want to
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // call _initSortFn if the value passed to the `data` attribute was a
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // new ModelList, not a set of new data as an array, or even the same
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // ModelList.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (e.prevVal !== e.newVal || e.newVal.hasOwnProperty('_compare')) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._initSortFn();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Sorts the `data` ModelList based on the new `sortBy` configuration.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _afterSortByChange
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {EventFacade} e The `sortByChange` event
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith _afterSortByChange: function (e) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // Can't use a setter because it's a chicken and egg problem. The
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // columns need to be set up to translate, but columns are initialized
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // from Core's initializer. So construction-time assignment would
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith // fail.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._setSortBy();
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // Don't sort unless sortBy has been set
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (this._sortBy.length) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (!this.data.comparator) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this.data.comparator = this._sortComparator;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this.data.sort();
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Subscribes to state changes that warrant updating the UI, and adds the
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith click handler for triggering the sort operation from the UI.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _bindSortUI
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith _bindSortUI: function () {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this.after(['sortableChange', 'sortByChange', 'columnsChange'],
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._uiSetSortable);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (this._theadNode) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._sortHandle = this._theadNode.delegate('click',
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Y.rbind('_onUITriggerSort', this),
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith '.' + this.getClassName('sortable', 'column'));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Sets the `sortBy` attribute from the `sort` event's `e.sortBy` value.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _defSortFn
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {EventFacade} e The `sort` event
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _defSortFn: function (e) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this.set.apply(this, ['sortBy', e.sortBy].concat(e.details));
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Removes the click subscription from the header for sorting.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method destructor
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith destructor: function () {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (this._sortHandle) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this._sortHandle.detach();
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Getter for the `sortBy` attribute.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Supports the special subattribute "sortBy.state" to get a normalized JSON
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith version of the current sort state. Otherwise, returns the last assigned
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith value.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _getSortBy
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {String|String[]|Object|Object[]} val The current sortBy value
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {String} detail String passed to `get(HERE)`. to parse subattributes
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @example Comparing `get("sortBy")` with `get("sortBy.state")`
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith var table = new Y.DataTable({
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith columns: [ ... ],
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith data: [ ... ],
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith sortBy: 'username'
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith });
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith table.get('sortBy'); // 'username'
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith table.get('sortBy.state'); // { key: 'username', dir: 1 }
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith table.sort(['lastName', { firstName: "desc" }]);
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith table.get('sortBy'); // ['lastName', { firstName: "desc" }]
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith table.get('sortBy.state'); // [{ key: "lastName", dir: 1 }, { key: "firstName", dir: -1 }]
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _getSortBy: function (val, detail) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var state, i, len, col;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // "sortBy." is 7 characters. Used to catch
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith detail = detail.slice(7);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // TODO: table.get('sortBy.asObject')? table.get('sortBy.json')?
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (detail === 'state') {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith state = [];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (i = 0, len = this._sortBy.length; i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith col = this._sortBy[i];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith state.push({
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column: col._id,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith dir: col.sortDir
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith });
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // TODO: Always return an array?
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return { state: (state.length === 1) ? state[0] : state };
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith } else {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return val;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Sets up the initial sort state and instance properties. Publishes events
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith and subscribes to attribute change events to maintain internal state.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method initializer
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith initializer: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var boundParseSortable = Y.bind('_parseSortable', this);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._parseSortable();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._setSortBy();
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._initSortFn();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.after({
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith renderHeader : Y.bind('_renderSortable', this),
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith dataChange : Y.bind('_afterDataChange', this),
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortByChange : Y.bind('_afterSortByChange', this),
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith sortableChange: boundParseSortable,
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith columnsChange : boundParseSortable
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith });
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.publish('sort', {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith defaultFn: Y.bind('_defSortFn', this)
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith });
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Creates a `_compare` function for the `data` ModelList to allow custom
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith sorting by multiple fields.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _initSortFn
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _initSortFn: function () {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith var self = this;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // TODO: This should be a ModelList extension.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // FIXME: Modifying a component of the host seems a little smelly
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // FIXME: Declaring inline override to leverage closure vs
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // compiling a new function for each column/sortable change or
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // binding the _compare implementation to this, resulting in an
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // extra function hop during sorting. Lesser of three evils?
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.data._compare = function (a, b) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var cmp = 0,
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith i, len, col, dir, aa, bb;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith col = self._sortBy[i];
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith dir = col.sortDir;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (col.sortFn) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith cmp = col.sortFn(a, b) * dir;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith } else {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // FIXME? Requires columns without sortFns to have key
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith aa = a.get(col.key);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith bb = b.get(col.key);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith return cmp;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith };
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith if (this._sortBy.length) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.data.comparator = this._sortComparator;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // TODO: is this necessary? Should it be elsewhere?
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.data.sort();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith } else {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // Leave the _compare method in place to avoid having to set it
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // up again. Mistake?
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith delete this.data.comparator;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Fires the `sort` event in response to user clicks on sortable column
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith headers.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _onUITriggerSort
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {DOMEventFacade} e The `click` event
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _onUITriggerSort: function (e) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var id = e.currentTarget.get('id'),
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith config = {},
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith dir = 1,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith e.preventDefault();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // TODO: if (e.ctrlKey) { /* subsort */ }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (id) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith Y.Array.each(this._displayColumns, function (col) {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (id === col._yuid) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column = col._id;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // Flip current sortDir or default to 1 (asc)
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith dir = -(col.sortDir|0) || 1;
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith }
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith });
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (column) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith config[column] = dir;
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this.fire('sort', {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith originEvent: e,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy: [config]
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith });
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Normalizes the possible input values for the `sortable` attribute, storing
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith the results in the `_sortable` property.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _parseSortable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _parseSortable: function () {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith var sortable = this.get('sortable'),
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith columns = [],
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith i, len, col;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (isArray(sortable)) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith for (i = 0, len = sortable.length; i < len; ++i) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith col = sortable[i];
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // isArray is called because arrays are objects, but will rely
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // on getColumn to nullify them for the subsequent if (col)
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith if (!isObject(col, true) || isArray(col)) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith col = this.getColumn(col);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (col) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith columns.push(col);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith } else if (sortable) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith columns = this._displayColumns.slice();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (sortable === 'auto') {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith for (i = columns.length - 1; i >= 0; --i) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith if (!columns[i].sortable) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith columns.splice(i, 1);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this._sortable = columns;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Initial application of the sortable UI.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _renderSortable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _renderSortable: function () {
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith this._uiSetSortable();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this._bindSortUI();
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Parses the current `sortBy` attribute into a normalized structure for the
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith `data` ModelList's `_compare` method. Also updates the column
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith configurations' `sortDir` properties.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _setSortBy
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _setSortBy: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var columns = this._displayColumns,
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy = this.get('sortBy') || [],
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortedClass = ' ' + this.getClassName('sorted'),
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith i, len, name, dir, field, column;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._sortBy = [];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // Purge current sort state from column configs
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (i = 0, len = columns.length; i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column = columns[i];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith delete column.sortDir;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (column.className) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // TODO: be more thorough
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column.className = column.className.replace(sortedClass, '');
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortBy = toArray(sortBy);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (i = 0, len = sortBy.length; i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith name = sortBy[i];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith dir = 1;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (isObject(name)) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith field = name;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // Have to use a for-in loop to process sort({ foo: -1 })
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (name in field) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (field.hasOwnProperty(name)) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith dir = dirMap[field[name]];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith break;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (name) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // Allow sorting of any model field and any column
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // FIXME: this isn't limited to model attributes, but there's no
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // convenient way to get a list of the attributes for a Model
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // subclass *including* the attributes of its superclasses.
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column = this.getColumn(name) || { _id: name, key: name };
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (column) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column.sortDir = dir;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (!column.className) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column.className = '';
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith column.className += sortedClass;
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._sortBy.push(column);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Array of column configuration objects of those columns that need UI setup
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith for user interaction.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @property _sortable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @type {Object[]}
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith //_sortable: null,
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Array of column configuration objects for those columns that are currently
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith being used to sort the data. Fake column objects are used for fields that
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith are not rendered as columns.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @property _sortBy
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @type {Object[]}
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith //_sortBy: null,
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Replacement `comparator` for the `data` ModelList that defers sorting logic
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith to the `_compare` method. The deferral is accomplished by returning `this`.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _sortComparator
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {Model} item The record being evaluated for sort position
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @return {Model} The record
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _sortComparator: function (item) {
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith // Defer sorting to ModelList's _compare
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return item;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith },
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Applies the appropriate classes to the `boundingBox` and column headers to
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith indicate sort state and sortability.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Also currently wraps the header content of sortable columns in a `<div>`
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith liner to give a CSS anchor for sort indicators.
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith _uiSetSortable: function () {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith var columns = this._sortable || [],
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith sortableClass = this.getClassName('sortable', 'column'),
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith ascClass = this.getClassName('sorted'),
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith descClass = this.getClassName('sorted', 'desc'),
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith linerClass = this.getClassName('sort', 'liner'),
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith i, len, col, node, content;
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.get('boundingBox').toggleClass(
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith this.getClassName('sortable'),
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith columns.length);
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith // TODO: this.head.render() + decorate cells?
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith this._theadNode.all('.' + sortableClass)
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith .removeClass(sortableClass)
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith .removeClass(ascClass)
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith .removeClass(descClass)
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith .each(function (th) {
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith var liner = th.one('.' + linerClass);
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith if (liner) {
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith liner.replace(liner.get('childNodes').toFrag());
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith }
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith });
8fff801a4a38e13d6ff8181ff097fb01d058d617Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith for (i = 0, len = columns.length; i < len; ++i) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith col = columns[i];
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith node = this._theadNode.one('#' + col._yuid);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (node) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith node.addClass(sortableClass);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (col.sortDir) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith node.addClass(ascClass);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith if (col.sortDir === -1) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith node.addClass(descClass);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith Y.Node.create('<div class="' + linerClass + '"></div>')
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith .append(node.get('childNodes').toFrag())
f5df3320c255ef9e7c007469613dc31b4f91a3d8Luke Smith .appendTo(node);
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith },
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Allows values `true`, `false`, "auto", or arrays of column names through.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _validateSortable
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {Any} val The input value to `set("sortable", VAL)`
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @return {Boolean}
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith _validateSortable: function (val) {
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith return val === 'auto' || isBoolean(val) || isArray(val);
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith },
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith /**
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith Allows strings, arrays of strings, objects, or arrays of objects.
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @method _validateSortBy
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @param {String|String[]|Object|Object[]} val The new `sortBy` value
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @return {Boolean}
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith @protected
f5443cec5378e1eba162c289f05b690b699c9c7bLuke Smith **/
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith _validateSortBy: function (val) {
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith return val === null ||
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith isString(val) ||
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith isObject(val, true) ||
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith (isArray(val) && (isString(val[0]) || isObject(val, true)));
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith }
32624ce45f113c04dfa5469b3cc77df42c4c46f4Luke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith}, true);
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke SmithY.DataTable.Sortable = Sortable;
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke Smith
4eafc0c9b36f7e8efc8808ab27dbed7ff8dc87abLuke SmithY.Base.mix(Y.DataTable, [Sortable]);