sort.js revision b2c3f7ee9595487fa2c245134423177b4421db5d
2362N/AAdds support for sorting the table data by API methods `table.sort(...)` or 0N/A`table.toggleSort(...)` or by clicking on column headers in the rendered UI. 0N/ASorting by the API is enabled automatically when this module is `use()`d. To 0N/Aenable UI triggered sorting, set the DataTable's `sortable` attribute to 0N/Avar table = new Y.DataTable({ 0N/A columns: [ 'id', 'username', 'name', 'birthdate' ], 0N/Atable.render('#table'); 0N/ASetting `sortable` to `true` will enable UI sorting for all columns. To enable 0N/AUI sorting for certain columns only, set `sortable` to an array of column keys, 2362N/Aor just add `sortable: true` to the respective column configuration objects. 2362N/AThis uses the default setting of `sortable: auto` for the DataTable instance. 0N/Avar table = new Y.DataTable({ 0N/A { key: 'username', sortable: true }, 0N/A { key: 'name', sortable: true }, 0N/A { key: 'birthdate', sortable: true } 0N/A // sortable: 'auto' is the default 0N/Avar table = new Y.DataTable({ 0N/A columns: [ 'id', 'username', 'name', 'birthdate' ], 0N/A sortable: [ 'username', 'name', 'birthdate' ] 0N/ATo disable UI sorting for all columns, set `sortable` to `false`. This still 0N/Apermits sorting via the API methods. 0N/AAs new records are inserted into the table's `data` ModelList, they will be inserted at the correct index to preserve the sort order. 0N/AThe current sort order is stored in the `sortBy` attribute. Assigning this value at instantiation will automatically sort your data. 0N/ASorting is done by a simple value comparison using < and > on the field 0N/Avalue. If you need custom sorting, add a sort function in the column's 0N/A`sortFn` property. Columns whose content is generated by formatters, but don't 0N/Arelate to a single `key`, require a `sortFn` to be sortable. 0N/Afunction nameSort(a, b) { 0N/A var aa = a.get('lastName'), 0N/A bb = a.get('lastName'); 0N/A aa = a.get('firstName'); 0N/A bb = b.get('firstName'); 0N/A return (aa > bb) ? 1 : (aa < bb) ? -1 : 0; 0N/Avar table = new Y.DataTable({ 0N/A columns: [ 'id', 'username', { key: name, sortFn: nameSort }, 'birthdate' ], 0N/A sortable: [ 'username', 'name', 'birthdate' ] 0N/ASee the user guide for more details. 0N/A@module datatable-sort 0N/A@class DataTable.Sortable // Which columns in the UI should suggest and respond to sorting interaction // pass an empty array if no UI columns should show sortable, but you want the Controls which column headers can trigger sorting by user clicks. * "auto" - (default) looks for `sortable: true` in the column configurations * `true` - all columns are enabled * `false - no UI sortable is enabled * {String[]} - array of key names to give sortable headers @type {String|String[]|Boolean} The current sort configuration to maintain in the data. Accepts column `key` strings or objects with a single property, the column `key`, with a value of 1, -1, "asc", or "desc". E.g. `{ username: 'asc' }`. String values are assumed to be ascending. * `"username"` - sort by the data's `username` field or the `key` associated to a column with that `name`. * `{ username: "desc" }` - sort by `username` in descending order. Alternately, use values "asc", 1 (same as "asc"), or -1 (same as "desc"). * `["lastName", "firstName"]` - ascending sort by `lastName`, but for records with the same `lastName`, ascending subsort by `firstName`. Array can have as many items as you want. * `[{ lastName: -1 }, "firstName"]` - descending sort by `lastName`, ascending subsort by `firstName`. Mixed types are ok. @type {String|String[]|Object|Object[]} Strings containing language for sorting tooltips. @default (strings for current lang configured in the YUI instance config) Sort the data in the `data` ModelList and refresh the table with the new Acceptable values for `fields` are `key` strings or objects with a single property, the column `key`, with a value of 1, -1, "asc", or "desc". E.g. `{ username: 'asc' }`. String values are assumed to be ascending. * `"username"` - sort by the data's `username` field or the `key` associated to a column with that `name`. * `{ username: "desc" }` - sort by `username` in descending order. Alternately, use values "asc", 1 (same as "asc"), or -1 (same as "desc"). * `["lastName", "firstName"]` - ascending sort by `lastName`, but for records with the same `lastName`, ascending subsort by `firstName`. Array can have as many items as you want. * `[{ lastName: -1 }, "firstName"]` - descending sort by `lastName`, ascending subsort by `firstName`. Mixed types are ok. @param {String|String[]|Object|Object[]} fields The field(s) to sort by @param {Object} [payload] Extra `sort` event payload you want to send along Template for the node that will wrap the header content for sortable @property SORT_INDICATOR_TEMPLATE @value '<span class="{className}"></span>' Reverse the current sort direction of one or more fields currently being Pass the `key` of the column or columns you want the sort order reversed @param {String|String[]} fields The field(s) to reverse sort order for @param {Object} [payload] Extra `sort` event payload you want to send along // To avoid updating column configs or sortBy directly //-------------------------------------------------------------------------- // Protected properties and methods //-------------------------------------------------------------------------- Creates the element that is responsible for displaying the sort arrow, and inserts it into the provided node. @method _addSortIndicator @param {Node} header The node to decorate with the sort indicator Sorts the `data` ModelList based on the new `sortBy` configuration. @method _afterSortByChange @param {EventFacade} e The `sortByChange` event // Can't use a setter because it's a chicken and egg problem. The // columns need to be set up to translate, but columns are initialized // from Core's initializer. So construction-time assignment would // Don't sort unless sortBy has been set Applies the sorting logic to the new ModelList if the `newVal` is a new @method _afterSortDataChange @param {EventFacade} e the `dataChange` event // object values always trigger a change event, but we only want to // call _initSortFn if the value passed to the `data` attribute was a // new ModelList, not a set of new data as an array, or even the same Checks if any of the fields in the modified record are fields that are currently being sorted by, and if so, resorts the `data` ModelList. @method _afterSortRecordChange @param {EventFacade} e The Model's `change` event Subscribes to state changes that warrant updating the UI, and adds the click handler for triggering the sort operation from the UI. this.
after([
'sortableChange',
'sortByChange',
'columnsChange'],
Y.
bind(
'_uiSetSortable',
this));
Y.
rbind(
'_onUITriggerSort',
this),
Sets the `sortBy` attribute from the `sort` event's `e.sortBy` value. @param {EventFacade} e The `sort` event Removes the click subscription from the header for sorting. Getter for the `sortBy` attribute. Supports the special subattribute "sortBy.state" to get a normalized JSON version of the current sort state. Otherwise, returns the last assigned <pre><code>var table = new Y.DataTable({ table.get('sortBy'); // 'username' table.get('sortBy.state'); // { key: 'username', dir: 1 } table.sort(['lastName', { firstName: "desc" }]); table.get('sortBy'); // ['lastName', { firstName: "desc" }] table.get('sortBy.state'); // [{ key: "lastName", dir: 1 }, { key: "firstName", dir: -1 }] @param {String|String[]|Object|Object[]} val The current sortBy value @param {String} detail String passed to `get(HERE)`. to parse subattributes // "sortBy." is 7 characters. Used to catch // TODO: table.get('sortBy.asObject')? table.get('sortBy.json')? // TODO: Always return an array? Sets up the initial sort state and instance properties. Publishes events and subscribes to attribute change events to maintain internal state. "*:change" : Y.
bind(
'_afterSortRecordChange',
this)
Creates a `_compare` function for the `data` ModelList to allow custom sorting by multiple fields. // TODO: This should be a ModelList extension. // FIXME: Modifying a component of the host seems a little smelly // FIXME: Declaring inline override to leverage closure vs // binding the _compare implementation to this, resulting in an // extra function hop during sorting. Lesser of three evils? // FIXME? Requires columns without sortFns to have key // TODO: is this necessary? Should it be elsewhere? // Leave the _compare method in place to avoid having to set it Add the sort related strings to the `strings` map. // Not a valueFn because other class extensions will want to add to it this.
set(
'strings', Y.
mix((
this.
get(
'strings') || {}),
Fires the `sort` event in response to user clicks on sortable column @param {DOMEventFacade} e The `click` event // In case a headerTemplate injected a link // TODO: Is this overreaching? Normalizes the possible input values for the `sortable` attribute, storing the results in the `_sortable` property. // isArray is called because arrays are objects, but will rely // on getColumn to nullify them for the subsequent if (col) Initial application of the sortable UI. Parses the current `sortBy` attribute into a normalized structure for the `data` ModelList's `_compare` method. Also updates the column configurations' `sortDir` properties. // Purge current sort state from column configs // TODO: be more thorough // Have to use a for-in loop to process sort({ foo: -1 }) // Allow sorting of any model field and any column // FIXME: this isn't limited to model attributes, but there's no // convenient way to get a list of the attributes for a Model // subclass *including* the attributes of its superclasses. Array of column configuration objects of those columns that need UI setup Array of column configuration objects for those columns that are currently being used to sort the data. Fake column objects are used for fields that are not rendered as columns. Replacement `comparator` for the `data` ModelList that defers sorting logic to the `_compare` method. The deferral is accomplished by returning `this`. @param {Model} item The record being evaluated for sort position @return {Model} The record // Defer sorting to ModelList's _compare Applies the appropriate classes to the `boundingBox` and column headers to indicate sort state and sortability. Also currently wraps the header content of sortable columns in a `<div>` liner to give a CSS anchor for sort indicators. // TODO: this.head.render() + decorate cells? 'descending' :
'ascending');
(
col.
sortDir ===
1) ?
'reverseSortBy' :
'sortBy'), {
// To combat VoiceOver from reading the sort title as the Allows values `true`, `false`, "auto", or arrays of column names through. @method _validateSortable @param {Any} val The input value to `set("sortable", VAL)` Allows strings, arrays of strings, objects, or arrays of objects. @param {String|String[]|Object|Object[]} val The new `sortBy` value