]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/datatable/datatable-sort.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / datatable / datatable-sort.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('datatable-sort', function(Y) {
9
10 /**
11  * Plugs DataTable with sorting functionality.
12  *
13  * @module datatable
14  * @submodule datatable-sort
15  */
16
17 /**
18  * Adds column sorting to DataTable.
19  * @class DataTableSort
20  * @extends Plugin.Base
21  */
22 var YgetClassName = Y.ClassNameManager.getClassName,
23
24     DATATABLE = "datatable",
25     COLUMN = "column",
26     ASC = "asc",
27     DESC = "desc",
28
29     //TODO: Don't use hrefs - use tab/arrow/enter
30     TEMPLATE = '<a class="{link_class}" title="{link_title}" href="{link_href}">{value}</a>';
31
32
33 function DataTableSort() {
34     DataTableSort.superclass.constructor.apply(this, arguments);
35 }
36
37 /////////////////////////////////////////////////////////////////////////////
38 //
39 // STATIC PROPERTIES
40 //
41 /////////////////////////////////////////////////////////////////////////////
42 Y.mix(DataTableSort, {
43     /**
44      * The namespace for the plugin. This will be the property on the host which
45      * references the plugin instance.
46      *
47      * @property NS
48      * @type String
49      * @static
50      * @final
51      * @value "sort"
52      */
53     NS: "sort",
54
55     /**
56      * Class name.
57      *
58      * @property NAME
59      * @type String
60      * @static
61      * @final
62      * @value "dataTableSort"
63      */
64     NAME: "dataTableSort",
65
66 /////////////////////////////////////////////////////////////////////////////
67 //
68 // ATTRIBUTES
69 //
70 /////////////////////////////////////////////////////////////////////////////
71     ATTRS: {
72         /**
73         * @attribute trigger
74         * @description Defines the trigger that causes a column to be sorted:
75         * {event, selector}, where "event" is an event type and "selector" is
76         * is a node query selector.
77         * @type Object
78         * @default {event:"click", selector:"th"}
79         * @writeOnce "initOnly"
80         */
81         trigger: {
82             value: {event:"click", selector:"th"},
83             writeOnce: "initOnly"
84         },
85         
86         /**
87         * @attribute lastSortedBy
88         * @description Describes last known sort state: {key,dir}, where
89         * "key" is column key and "dir" is either "asc" or "desc".
90         * @type Object
91         */
92         lastSortedBy: {
93             setter: "_setLastSortedBy",
94             lazyAdd: false
95         },
96         
97         /**
98         * @attribute template
99         * @description Tokenized markup template for TH sort element.
100         * @type String
101         * @default '<a class="{link_class}" title="{link_title}" href="{link_href}">{value}</a>'
102         */
103         template: {
104             value: TEMPLATE
105         }
106     }
107 });
108
109 /////////////////////////////////////////////////////////////////////////////
110 //
111 // PROTOTYPE
112 //
113 /////////////////////////////////////////////////////////////////////////////
114 Y.extend(DataTableSort, Y.Plugin.Base, {
115
116     /////////////////////////////////////////////////////////////////////////////
117     //
118     // METHODS
119     //
120     /////////////////////////////////////////////////////////////////////////////
121     /**
122     * Initializer.
123     *
124     * @method initializer
125     * @param config {Object} Config object.
126     * @private
127     */
128     initializer: function(config) {
129         var dt = this.get("host"),
130             trigger = this.get("trigger");
131             
132         dt.get("recordset").plug(Y.Plugin.RecordsetSort, {dt: dt});
133         dt.get("recordset").sort.addTarget(dt);
134         
135         // Wrap link around TH value
136         this.doBefore("_createTheadThNode", this._beforeCreateTheadThNode);
137         
138         // Add class
139         this.doBefore("_attachTheadThNode", this._beforeAttachTheadThNode);
140         this.doBefore("_attachTbodyTdNode", this._beforeAttachTbodyTdNode);
141
142         // Attach trigger handlers
143         dt.delegate(trigger.event, Y.bind(this._onEventSortColumn,this), trigger.selector);
144
145         // Attach UI hooks
146         dt.after("recordsetSort:sort", function() {
147             this._uiSetRecordset(this.get("recordset"));
148         });
149         this.on("lastSortedByChange", function(e) {
150             this._uiSetLastSortedBy(e.prevVal, e.newVal, dt);
151         });
152
153         //TODO
154         //dt.after("recordset:mutation", function() {//reset lastSortedBy});
155         
156         //TODO
157         //add Column sortFn ATTR
158         
159         // Update UI after the fact (render-then-plug case)
160         if(dt.get("rendered")) {
161             dt._uiSetColumnset(dt.get("columnset"));
162             this._uiSetLastSortedBy(null, this.get("lastSortedBy"), dt);
163         }
164     },
165
166     /**
167     * @method _setLastSortedBy
168     * @description Normalizes lastSortedBy
169     * @param val {String | Object} {key, dir} or "key"
170     * @returns {key, dir, notdir}
171     * @private
172     */
173     _setLastSortedBy: function(val) {
174         if(Y.Lang.isString(val)) {
175             return {key:val, dir:"asc", notdir:"desc"};
176         }
177         else if (val && val.key) {
178             if(val.dir === "desc") {
179                 return {key:val.key, dir:"desc", notdir:"asc"};
180             }
181             else {
182                 return {key:val.key, dir:"asc", notdir:"desc"};
183             }
184         }
185         else {
186             return null;
187         }
188     },
189
190     /**
191      * Updates sort UI.
192      *
193      * @method _uiSetLastSortedBy
194      * @param val {Object} New lastSortedBy object {key,dir}.
195      * @param dt {Y.DataTable.Base} Host.
196      * @protected
197      */
198     _uiSetLastSortedBy: function(prevVal, newVal, dt) {
199         var prevKey = prevVal && prevVal.key,
200             prevDir = prevVal && prevVal.dir,
201             newKey = newVal && newVal.key,
202             newDir = newVal && newVal.dir,
203             cs = dt.get("columnset"),
204             prevColumn = cs.keyHash[prevKey],
205             newColumn = cs.keyHash[newKey],
206             tbodyNode = dt._tbodyNode,
207             prevRowList, newRowList;
208
209         // Clear previous UI
210         if(prevColumn) {
211             prevColumn.thNode.removeClass(YgetClassName(DATATABLE, prevDir));
212             prevRowList = tbodyNode.all("."+YgetClassName(COLUMN, prevColumn.get("id")));
213             prevRowList.removeClass(YgetClassName(DATATABLE, prevDir));
214         }
215
216         // Add new sort UI
217         if(newColumn) {
218             newColumn.thNode.addClass(YgetClassName(DATATABLE, newDir));
219             newRowList = tbodyNode.all("."+YgetClassName(COLUMN, newColumn.get("id")));
220             newRowList.addClass(YgetClassName(DATATABLE, newDir));
221         }
222     },
223
224     /**
225     * Before header cell element is created, inserts link markup around {value}.
226     *
227     * @method _beforeCreateTheadThNode
228     * @param o {Object} {value, column, tr}.
229     * @protected
230     */
231     _beforeCreateTheadThNode: function(o) {
232         if(o.column.get("sortable")) {
233             o.value = Y.substitute(this.get("template"), {
234                 link_class: o.link_class || "",
235                 link_title: "title",
236                 link_href: "#",
237                 value: o.value
238             });
239         }
240     },
241
242     /**
243     * Before header cell element is attached, sets applicable class names.
244     *
245     * @method _beforeAttachTheadThNode
246     * @param o {Object} {value, column, tr}.
247     * @protected
248     */
249     _beforeAttachTheadThNode: function(o) {
250         var lastSortedBy = this.get("lastSortedBy"),
251             key = lastSortedBy && lastSortedBy.key,
252             dir = lastSortedBy && lastSortedBy.dir,
253             notdir = lastSortedBy && lastSortedBy.notdir;
254
255         // This Column is sortable
256         if(o.column.get("sortable")) {
257             o.th.addClass(YgetClassName(DATATABLE, "sortable"));
258         }
259         // This Column is currently sorted
260         if(key && (key === o.column.get("key"))) {
261             o.th.replaceClass(YgetClassName(DATATABLE, notdir), YgetClassName(DATATABLE, dir));
262         }
263     },
264
265     /**
266     * Before header cell element is attached, sets applicable class names.
267     *
268     * @method _before_beforeAttachTbodyTdNode
269     * @param o {Object} {record, column, tr, headers, classnames, value}.
270     * @protected
271     */
272     _beforeAttachTbodyTdNode: function(o) {
273         var lastSortedBy = this.get("lastSortedBy"),
274             key = lastSortedBy && lastSortedBy.key,
275             dir = lastSortedBy && lastSortedBy.dir,
276             notdir = lastSortedBy && lastSortedBy.notdir;
277
278         // This Column is sortable
279         if(o.column.get("sortable")) {
280             o.td.addClass(YgetClassName(DATATABLE, "sortable"));
281         }
282         // This Column is currently sorted
283         if(key && (key === o.column.get("key"))) {
284             o.td.replaceClass(YgetClassName(DATATABLE, notdir), YgetClassName(DATATABLE, dir));
285         }
286     },
287     /**
288     * In response to the "trigger" event, sorts the underlying Recordset and
289     * updates the lastSortedBy attribute.
290     *
291     * @method _onEventSortColumn
292     * @param o {Object} {value, column, tr}.
293     * @protected
294     */
295     _onEventSortColumn: function(e) {
296         e.halt();
297         //TODO: normalize e.currentTarget to TH
298         var dt = this.get("host"),
299             column = dt.get("columnset").idHash[e.currentTarget.get("id")],
300             key = column.get("key"),
301             field = column.get("field"),
302             lastSortedBy = this.get("lastSortedBy"),
303             dir = (lastSortedBy &&
304                 lastSortedBy.key === key &&
305                 lastSortedBy.dir === ASC) ? DESC : ASC,
306             sorter = column.get("sortFn");
307         if(column.get("sortable")) {
308             dt.get("recordset").sort.sort(field, dir === DESC, sorter);
309             this.set("lastSortedBy", {key: key, dir: dir});
310         }
311     }
312 });
313
314 Y.namespace("Plugin").DataTableSort = DataTableSort;
315
316
317
318
319
320
321 }, '3.3.0' ,{lang:['en'], requires:['datatable-base','plugin','recordset-sort']});