1 | define([ |
---|
2 | "dojo/_base/declare", |
---|
3 | "dojo/_base/array", |
---|
4 | "dojo/_base/lang", |
---|
5 | "dojo/_base/sniff", |
---|
6 | "dojo/_base/html", |
---|
7 | "dojo/_base/json", |
---|
8 | "dojo/_base/window", |
---|
9 | "dojo/_base/unload", |
---|
10 | "dojo/cookie", |
---|
11 | "../_Plugin", |
---|
12 | "../../_RowSelector", |
---|
13 | "../../EnhancedGrid", |
---|
14 | "../../cells/_base" |
---|
15 | ], function(declare, array, lang, has, html, json, win, unload, cookie, _Plugin, _RowSelector, EnhancedGrid){ |
---|
16 | |
---|
17 | var gridCells = lang.getObject("dojox.grid.cells"); |
---|
18 | |
---|
19 | // Generate a cookie key for the given grid. |
---|
20 | var _cookieKeyBuilder = function(grid){ |
---|
21 | return window.location + "/" + grid.id; |
---|
22 | }; |
---|
23 | |
---|
24 | //Utilities: |
---|
25 | var _getCellsFromStructure = function(structure){ |
---|
26 | var cells = []; |
---|
27 | if(!lang.isArray(structure)){ |
---|
28 | structure = [structure]; |
---|
29 | } |
---|
30 | array.forEach(structure,function(viewDef){ |
---|
31 | if(lang.isArray(viewDef)){ |
---|
32 | viewDef = {"cells" : viewDef}; |
---|
33 | } |
---|
34 | var rows = viewDef.rows || viewDef.cells; |
---|
35 | if(lang.isArray(rows)){ |
---|
36 | if(!lang.isArray(rows[0])){ |
---|
37 | rows = [rows]; |
---|
38 | } |
---|
39 | array.forEach(rows, function(row){ |
---|
40 | if(lang.isArray(row)){ |
---|
41 | array.forEach(row, function(cell){ |
---|
42 | cells.push(cell); |
---|
43 | }); |
---|
44 | } |
---|
45 | }); |
---|
46 | } |
---|
47 | }); |
---|
48 | return cells; |
---|
49 | }; |
---|
50 | |
---|
51 | // Persist column width |
---|
52 | var _loadColWidth = function(colWidths, grid){ |
---|
53 | if(lang.isArray(colWidths)){ |
---|
54 | var oldFunc = grid._setStructureAttr; |
---|
55 | grid._setStructureAttr = function(structure){ |
---|
56 | if(!grid._colWidthLoaded){ |
---|
57 | grid._colWidthLoaded = true; |
---|
58 | var cells = _getCellsFromStructure(structure); |
---|
59 | for(var i = cells.length - 1; i >= 0; --i){ |
---|
60 | if(typeof colWidths[i] == "number"){ |
---|
61 | cells[i].width = colWidths[i] + "px"; |
---|
62 | }else if(colWidths[i] == 'hidden'){ |
---|
63 | cells[i].hidden = true; |
---|
64 | } |
---|
65 | } |
---|
66 | } |
---|
67 | oldFunc.call(grid, structure); |
---|
68 | grid._setStructureAttr = oldFunc; |
---|
69 | }; |
---|
70 | } |
---|
71 | }; |
---|
72 | |
---|
73 | |
---|
74 | var _saveColWidth = function(grid){ |
---|
75 | return array.map(array.filter(grid.layout.cells, function(cell){ |
---|
76 | return !(cell.isRowSelector || cell instanceof gridCells.RowIndex); |
---|
77 | }), function(cell){ |
---|
78 | return cell.hidden ? 'hidden' : html[has('webkit') ? "marginBox" : "contentBox"](cell.getHeaderNode()).w; |
---|
79 | }); |
---|
80 | }; |
---|
81 | |
---|
82 | // Persist column order |
---|
83 | var _loadColumnOrder = function(colOrder, grid){ |
---|
84 | if(colOrder && array.every(colOrder, function(viewInfo){ |
---|
85 | return lang.isArray(viewInfo) && array.every(viewInfo, function(subrowInfo){ |
---|
86 | return lang.isArray(subrowInfo) && subrowInfo.length > 0; |
---|
87 | }); |
---|
88 | })){ |
---|
89 | var oldFunc = grid._setStructureAttr; |
---|
90 | var isCell = function(def){ |
---|
91 | return ("name" in def || "field" in def || "get" in def); |
---|
92 | }; |
---|
93 | var isView = function(def){ |
---|
94 | return (def !== null && lang.isObject(def) && |
---|
95 | ("cells" in def || "rows" in def || ("type" in def && !isCell(def)))); |
---|
96 | }; |
---|
97 | grid._setStructureAttr = function(structure){ |
---|
98 | if(!grid._colOrderLoaded){ |
---|
99 | grid._colOrderLoaded = true; |
---|
100 | grid._setStructureAttr = oldFunc; |
---|
101 | structure = lang.clone(structure); |
---|
102 | if(lang.isArray(structure) && !array.some(structure, isView)){ |
---|
103 | structure = [{ cells: structure }]; |
---|
104 | }else if(isView(structure)){ |
---|
105 | structure = [structure]; |
---|
106 | } |
---|
107 | var cells = _getCellsFromStructure(structure); |
---|
108 | array.forEach(lang.isArray(structure) ? structure : [structure], function(viewDef, viewIdx){ |
---|
109 | var cellArray = viewDef; |
---|
110 | if(lang.isArray(viewDef)){ |
---|
111 | viewDef.splice(0, viewDef.length); |
---|
112 | }else{ |
---|
113 | delete viewDef.rows; |
---|
114 | cellArray = viewDef.cells = []; |
---|
115 | } |
---|
116 | array.forEach(colOrder[viewIdx], function(subrow){ |
---|
117 | array.forEach(subrow, function(cellInfo){ |
---|
118 | var i, cell; |
---|
119 | for(i = 0; i < cells.length; ++i){ |
---|
120 | cell = cells[i]; |
---|
121 | if(json.toJson({'name':cell.name,'field':cell.field}) == json.toJson(cellInfo)){ |
---|
122 | break; |
---|
123 | } |
---|
124 | } |
---|
125 | if(i < cells.length){ |
---|
126 | cellArray.push(cell); |
---|
127 | } |
---|
128 | }); |
---|
129 | }); |
---|
130 | }); |
---|
131 | } |
---|
132 | oldFunc.call(grid, structure); |
---|
133 | }; |
---|
134 | } |
---|
135 | }; |
---|
136 | |
---|
137 | var _saveColumnOrder = function(grid){ |
---|
138 | var colOrder = array.map(array.filter(grid.views.views, function(view){ |
---|
139 | return !(view instanceof _RowSelector); |
---|
140 | }), function(view){ |
---|
141 | return array.map(view.structure.cells, function(subrow){ |
---|
142 | return array.map(array.filter(subrow, function(cell){ |
---|
143 | return !(cell.isRowSelector || cell instanceof gridCells.RowIndex); |
---|
144 | }), function(cell){ |
---|
145 | return { |
---|
146 | "name": cell.name, |
---|
147 | "field": cell.field |
---|
148 | }; |
---|
149 | }); |
---|
150 | }); |
---|
151 | }); |
---|
152 | return colOrder; |
---|
153 | }; |
---|
154 | |
---|
155 | // Persist sorting order |
---|
156 | var _loadSortOrder = function(sortOrder, grid){ |
---|
157 | try{ |
---|
158 | if(sortOrder && lang.isObject(sortOrder)){ |
---|
159 | grid.setSortIndex(sortOrder.idx, sortOrder.asc); |
---|
160 | } |
---|
161 | }catch(e){ |
---|
162 | //setSortIndex will finally call _fetch, some exceptions will be throw |
---|
163 | //'cause the grid hasn't be fully loaded now. Just ignore them. |
---|
164 | } |
---|
165 | }; |
---|
166 | |
---|
167 | var _saveSortOrder = function(grid){ |
---|
168 | return { |
---|
169 | idx: grid.getSortIndex(), |
---|
170 | asc: grid.getSortAsc() |
---|
171 | }; |
---|
172 | }; |
---|
173 | |
---|
174 | if(!has('ie')){ |
---|
175 | // Now in non-IE, widgets are no longer destroyed on page unload, |
---|
176 | // so we have to destroy it manually to trigger saving cookie. |
---|
177 | unload.addOnWindowUnload(function(){ |
---|
178 | array.forEach(dijit.findWidgets(win.body()), function(widget){ |
---|
179 | if(widget instanceof EnhancedGrid && !widget._destroyed){ |
---|
180 | widget.destroyRecursive(); |
---|
181 | } |
---|
182 | }); |
---|
183 | }); |
---|
184 | } |
---|
185 | |
---|
186 | var Cookie = declare("dojox.grid.enhanced.plugins.Cookie", _Plugin, { |
---|
187 | // summary: |
---|
188 | // This plugin provides a way to persist some grid features in cookie. |
---|
189 | // Default persistable features are: |
---|
190 | // column width: "columnWidth" (handler name) |
---|
191 | // column order: "columnOrder" |
---|
192 | // sorting order: "sortOrder" |
---|
193 | // |
---|
194 | // Grid users can define new persistable features |
---|
195 | // by calling the following before grid is initialized (that is, during "preInit"); |
---|
196 | // | grid.addCookieHandler({ |
---|
197 | // | name: "a name for the new persistable feature", |
---|
198 | // | onLoad: function(savedObject, grid){ |
---|
199 | // | //load the cookie. |
---|
200 | // | }, |
---|
201 | // | onSave: function(grid){ |
---|
202 | // | //save the cookie. |
---|
203 | // | } |
---|
204 | // | }); |
---|
205 | |
---|
206 | // name: String |
---|
207 | // Plugin name |
---|
208 | name: "cookie", |
---|
209 | |
---|
210 | _cookieEnabled: true, |
---|
211 | |
---|
212 | constructor: function(grid, args){ |
---|
213 | this.grid = grid; |
---|
214 | args = (args && lang.isObject(args)) ? args : {}; |
---|
215 | this.cookieProps = args.cookieProps; |
---|
216 | this._cookieHandlers = []; |
---|
217 | this._mixinGrid(); |
---|
218 | |
---|
219 | //Column width & simple sorting & column reorder are base grid features, so they must be supported. |
---|
220 | this.addCookieHandler({ |
---|
221 | name: "columnWidth", |
---|
222 | onLoad: _loadColWidth, |
---|
223 | onSave: _saveColWidth |
---|
224 | }); |
---|
225 | this.addCookieHandler({ |
---|
226 | name: "columnOrder", |
---|
227 | onLoad: _loadColumnOrder, |
---|
228 | onSave: _saveColumnOrder |
---|
229 | }); |
---|
230 | this.addCookieHandler({ |
---|
231 | name: "sortOrder", |
---|
232 | onLoad: _loadSortOrder, |
---|
233 | onSave: _saveSortOrder |
---|
234 | }); |
---|
235 | |
---|
236 | array.forEach(this._cookieHandlers, function(handler){ |
---|
237 | if(args[handler.name] === false){ |
---|
238 | handler.enable = false; |
---|
239 | } |
---|
240 | }, this); |
---|
241 | }, |
---|
242 | destroy:function(){ |
---|
243 | this._saveCookie(); |
---|
244 | this._cookieHandlers = null; |
---|
245 | this.inherited(arguments); |
---|
246 | }, |
---|
247 | _mixinGrid: function(){ |
---|
248 | var g = this.grid; |
---|
249 | g.addCookieHandler = lang.hitch(this, "addCookieHandler"); |
---|
250 | g.removeCookie = lang.hitch(this, "removeCookie"); |
---|
251 | g.setCookieEnabled = lang.hitch(this, "setCookieEnabled"); |
---|
252 | g.getCookieEnabled = lang.hitch(this, "getCookieEnabled"); |
---|
253 | }, |
---|
254 | _saveCookie: function(){ |
---|
255 | if(this.getCookieEnabled()){ |
---|
256 | var ck = {}, |
---|
257 | chs = this._cookieHandlers, |
---|
258 | cookieProps = this.cookieProps, |
---|
259 | cookieKey = _cookieKeyBuilder(this.grid); |
---|
260 | for(var i = chs.length-1; i >= 0; --i){ |
---|
261 | if(chs[i].enabled){ |
---|
262 | //Do the real saving work here. |
---|
263 | ck[chs[i].name] = chs[i].onSave(this.grid); |
---|
264 | } |
---|
265 | } |
---|
266 | cookieProps = lang.isObject(this.cookieProps) ? this.cookieProps : {}; |
---|
267 | cookie(cookieKey, json.toJson(ck), cookieProps); |
---|
268 | }else{ |
---|
269 | this.removeCookie(); |
---|
270 | } |
---|
271 | }, |
---|
272 | onPreInit: function(){ |
---|
273 | var grid = this.grid, |
---|
274 | chs = this._cookieHandlers, |
---|
275 | cookieKey = _cookieKeyBuilder(grid), |
---|
276 | ck = cookie(cookieKey); |
---|
277 | if(ck){ |
---|
278 | ck = json.fromJson(ck); |
---|
279 | for(var i = 0; i < chs.length; ++i){ |
---|
280 | if(chs[i].name in ck && chs[i].enabled){ |
---|
281 | //Do the real loading work here. |
---|
282 | chs[i].onLoad(ck[chs[i].name], grid); |
---|
283 | } |
---|
284 | } |
---|
285 | } |
---|
286 | this._cookie = ck || {}; |
---|
287 | this._cookieStartedup = true; |
---|
288 | }, |
---|
289 | addCookieHandler: function(args){ |
---|
290 | // summary: |
---|
291 | // If a grid plugin wants cookie service, call this. |
---|
292 | // This must be called during preInit. |
---|
293 | // args: Object |
---|
294 | // An object with the following structure: |
---|
295 | // | { |
---|
296 | // | name: "some-string", |
---|
297 | // | onLoad: /* void */ function(/* object */partOfCookie, /* EDG */grid){...}, |
---|
298 | // | onSave: /* object */ function(/* EDG */grid){...} |
---|
299 | // | } |
---|
300 | if(args.name){ |
---|
301 | var dummy = function(){}; |
---|
302 | args.onLoad = args.onLoad || dummy; |
---|
303 | args.onSave = args.onSave || dummy; |
---|
304 | if(!("enabled" in args)){ |
---|
305 | args.enabled = true; |
---|
306 | } |
---|
307 | for(var i = this._cookieHandlers.length - 1; i >= 0; --i){ |
---|
308 | if(this._cookieHandlers[i].name == args.name){ |
---|
309 | this._cookieHandlers.splice(i, 1); |
---|
310 | } |
---|
311 | } |
---|
312 | this._cookieHandlers.push(args); |
---|
313 | if(this._cookieStartedup && args.name in this._cookie){ |
---|
314 | args.onLoad(this._cookie[args.name], this.grid); |
---|
315 | } |
---|
316 | } |
---|
317 | }, |
---|
318 | removeCookie: function(){ |
---|
319 | // summary: |
---|
320 | // Remove cookie for this grid. |
---|
321 | var key = _cookieKeyBuilder(this.grid); |
---|
322 | cookie(key, null, {expires: -1}); |
---|
323 | }, |
---|
324 | setCookieEnabled: function(cookieName, enabled){ |
---|
325 | // summary: |
---|
326 | // A setter to enable|disable cookie support for a particular Grid feature. |
---|
327 | // cookieName: String? |
---|
328 | // Name of a cookie handler if provided, otherwise for all cookies. |
---|
329 | // enabled: Boolean |
---|
330 | if(typeof cookieName == 'string'){ |
---|
331 | var chs = this._cookieHandlers; |
---|
332 | for(var i = chs.length - 1; i >= 0; --i){ |
---|
333 | if(chs[i].name === cookieName){ |
---|
334 | chs[i].enabled = !!enabled; |
---|
335 | } |
---|
336 | } |
---|
337 | }else{ |
---|
338 | this._cookieEnabled = !!cookieName; |
---|
339 | if(!this._cookieEnabled){ this.removeCookie(); } |
---|
340 | } |
---|
341 | }, |
---|
342 | getCookieEnabled: function(cookieName){ |
---|
343 | // summary: |
---|
344 | // A getter to check cookie support of a particular Grid feature. |
---|
345 | // cookieName: String? |
---|
346 | // Name of a cookie handler if provided, otherwise for all cookies. |
---|
347 | if(lang.isString(cookieName)){ |
---|
348 | var chs = this._cookieHandlers; |
---|
349 | for(var i = chs.length - 1; i >= 0; --i){ |
---|
350 | if(chs[i].name == cookieName){ return chs[i].enabled; } |
---|
351 | } |
---|
352 | return false; |
---|
353 | } |
---|
354 | return this._cookieEnabled; |
---|
355 | } |
---|
356 | }); |
---|
357 | |
---|
358 | EnhancedGrid.registerPlugin(Cookie, {"preInit": true}); |
---|
359 | |
---|
360 | return Cookie; |
---|
361 | }); |
---|