3
Copyright 2011 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
7
YUI.add('datatable-sort', function(Y) {
10
* Plugs DataTable with sorting functionality.
13
* @submodule datatable-sort
17
* Adds column sorting to DataTable.
18
* @class DataTableSort
19
* @extends Plugin.Base
21
var YgetClassName = Y.ClassNameManager.getClassName,
23
DATATABLE = "datatable",
28
//TODO: Don't use hrefs - use tab/arrow/enter
29
TEMPLATE = '<a class="{link_class}" title="{link_title}" href="{link_href}">{value}</a>';
32
function DataTableSort() {
33
DataTableSort.superclass.constructor.apply(this, arguments);
36
/////////////////////////////////////////////////////////////////////////////
40
/////////////////////////////////////////////////////////////////////////////
41
Y.mix(DataTableSort, {
43
* The namespace for the plugin. This will be the property on the host which
44
* references the plugin instance.
61
* @value "dataTableSort"
63
NAME: "dataTableSort",
65
/////////////////////////////////////////////////////////////////////////////
69
/////////////////////////////////////////////////////////////////////////////
73
* @description Defines the trigger that causes a column to be sorted:
74
* {event, selector}, where "event" is an event type and "selector" is
75
* is a node query selector.
77
* @default {event:"click", selector:"th"}
78
* @writeOnce "initOnly"
81
value: {event:"click", selector:"th"},
86
* @attribute lastSortedBy
87
* @description Describes last known sort state: {key,dir}, where
88
* "key" is column key and "dir" is either "asc" or "desc".
92
setter: "_setLastSortedBy",
98
* @description Tokenized markup template for TH sort element.
100
* @default '<a class="{link_class}" title="{link_title}" href="{link_href}">{value}</a>'
107
* Strings used in the UI elements.
109
* The strings used are defaulted from the datatable-sort language pack
110
* for the language identified in the YUI "lang" configuration (which
113
* Configurable strings are "sortBy" and "reverseSortBy", which are
114
* assigned to the sort link's title attribute.
120
valueFn: function () { return Y.Intl.get('datatable-sort'); }
125
/////////////////////////////////////////////////////////////////////////////
129
/////////////////////////////////////////////////////////////////////////////
130
Y.extend(DataTableSort, Y.Plugin.Base, {
132
/////////////////////////////////////////////////////////////////////////////
136
/////////////////////////////////////////////////////////////////////////////
140
* @method initializer
141
* @param config {Object} Config object.
144
initializer: function(config) {
145
var dt = this.get("host"),
146
trigger = this.get("trigger");
148
dt.get("recordset").plug(Y.Plugin.RecordsetSort, {dt: dt});
149
dt.get("recordset").sort.addTarget(dt);
151
// Wrap link around TH value
152
this.doBefore("_createTheadThNode", this._beforeCreateTheadThNode);
155
this.doBefore("_attachTheadThNode", this._beforeAttachTheadThNode);
156
this.doBefore("_attachTbodyTdNode", this._beforeAttachTbodyTdNode);
158
// Attach trigger handlers
159
dt.delegate(trigger.event, Y.bind(this._onEventSortColumn,this), trigger.selector);
162
dt.after("recordsetSort:sort", function() {
163
this._uiSetRecordset(this.get("recordset"));
165
this.on("lastSortedByChange", function(e) {
166
this._uiSetLastSortedBy(e.prevVal, e.newVal, dt);
170
//dt.after("recordset:mutation", function() {//reset lastSortedBy});
173
//add Column sortFn ATTR
175
// Update UI after the fact (render-then-plug case)
176
if(dt.get("rendered")) {
177
dt._uiSetColumnset(dt.get("columnset"));
178
this._uiSetLastSortedBy(null, this.get("lastSortedBy"), dt);
183
* @method _setLastSortedBy
184
* @description Normalizes lastSortedBy
185
* @param val {String | Object} {key, dir} or "key"
186
* @return {key, dir, notdir}
189
_setLastSortedBy: function(val) {
190
if (Y.Lang.isString(val)) {
191
val = { key: val, dir: "desc" };
195
return (val.dir === "desc") ?
196
{ key: val.key, dir: "desc", notdir: "asc" } :
197
{ key: val.key, dir: "asc", notdir:"desc" };
206
* @method _uiSetLastSortedBy
207
* @param val {Object} New lastSortedBy object {key,dir}.
208
* @param dt {Y.DataTable.Base} Host.
211
_uiSetLastSortedBy: function(prevVal, newVal, dt) {
212
var strings = this.get('strings'),
213
columnset = dt.get("columnset"),
214
prevKey = prevVal && prevVal.key,
215
newKey = newVal && newVal.key,
216
prevClass = prevVal && dt.getClassName(prevVal.dir),
217
newClass = newVal && dt.getClassName(newVal.dir),
218
prevColumn = columnset.keyHash[prevKey],
219
newColumn = columnset.keyHash[newKey],
220
tbodyNode = dt._tbodyNode,
221
fromTemplate = Y.Lang.sub,
222
th, sortArrow, sortLabel;
225
if (prevColumn && prevClass) {
226
th = prevColumn.thNode;
227
sortArrow = th.one('a');
230
sortArrow.set('title', fromTemplate(strings.sortBy, {
231
column: prevColumn.get('label')
235
th.removeClass(prevClass);
236
tbodyNode.all("." + YgetClassName(COLUMN, prevColumn.get("id")))
237
.removeClass(prevClass);
241
if (newColumn && newClass) {
242
th = newColumn.thNode;
243
sortArrow = th.one('a');
246
sortLabel = (newVal.dir === ASC) ? "reverseSortBy" : "sortBy";
248
sortArrow.set('title', fromTemplate(strings[sortLabel], {
249
column: newColumn.get('label')
253
th.addClass(newClass);
255
tbodyNode.all("." + YgetClassName(COLUMN, newColumn.get("id")))
261
* Before header cell element is created, inserts link markup around {value}.
263
* @method _beforeCreateTheadThNode
264
* @param o {Object} {value, column, tr}.
267
_beforeCreateTheadThNode: function(o) {
268
var sortedBy, sortLabel;
270
if (o.column.get("sortable")) {
271
sortedBy = this.get('lastSortedBy');
273
sortLabel = (sortedBy && sortedBy.dir === ASC &&
274
sortedBy.key === o.column.get('key')) ?
275
"reverseSortBy" : "sortBy";
277
o.value = Y.Lang.sub(this.get("template"), {
278
link_class: o.link_class || "",
279
link_title: Y.Lang.sub(this.get('strings.' + sortLabel), {
280
column: o.column.get('label')
289
* Before header cell element is attached, sets applicable class names.
291
* @method _beforeAttachTheadThNode
292
* @param o {Object} {value, column, tr}.
295
_beforeAttachTheadThNode: function(o) {
296
var lastSortedBy = this.get("lastSortedBy"),
297
key = lastSortedBy && lastSortedBy.key,
298
dir = lastSortedBy && lastSortedBy.dir,
299
notdir = lastSortedBy && lastSortedBy.notdir;
301
// This Column is sortable
302
if(o.column.get("sortable")) {
303
o.th.addClass(YgetClassName(DATATABLE, "sortable"));
305
// This Column is currently sorted
306
if(key && (key === o.column.get("key"))) {
307
o.th.replaceClass(YgetClassName(DATATABLE, notdir), YgetClassName(DATATABLE, dir));
312
* Before header cell element is attached, sets applicable class names.
314
* @method _beforeAttachTbodyTdNode
315
* @param o {Object} {record, column, tr, headers, classnames, value}.
318
_beforeAttachTbodyTdNode: function(o) {
319
var lastSortedBy = this.get("lastSortedBy"),
320
key = lastSortedBy && lastSortedBy.key,
321
dir = lastSortedBy && lastSortedBy.dir,
322
notdir = lastSortedBy && lastSortedBy.notdir;
324
// This Column is sortable
325
if(o.column.get("sortable")) {
326
o.td.addClass(YgetClassName(DATATABLE, "sortable"));
328
// This Column is currently sorted
329
if(key && (key === o.column.get("key"))) {
330
o.td.replaceClass(YgetClassName(DATATABLE, notdir), YgetClassName(DATATABLE, dir));
334
* In response to the "trigger" event, sorts the underlying Recordset and
335
* updates the lastSortedBy attribute.
337
* @method _onEventSortColumn
338
* @param o {Object} {value, column, tr}.
341
_onEventSortColumn: function(e) {
343
//TODO: normalize e.currentTarget to TH
344
var table = this.get("host"),
345
column = table.get("columnset").idHash[e.currentTarget.get("id")],
346
key, field, lastSort, desc, sorter;
348
if (column.get("sortable")) {
349
key = column.get("key");
350
field = column.get("field");
351
lastSort = this.get("lastSortedBy") || {};
352
desc = (lastSort.key === key && lastSort.dir === ASC);
353
sorter = column.get("sortFn");
355
table.get("recordset").sort.sort(field, desc, sorter);
357
this.set("lastSortedBy", {
359
dir: (desc) ? DESC : ASC
365
Y.namespace("Plugin").DataTableSort = DataTableSort;
371
}, '3.4.1' ,{requires:['datatable-base','plugin','recordset-sort'], lang:['en']});