|
1 /* |
|
2 * File: ColReorderWithResize.js |
|
3 * Version: 1.0.7 |
|
4 * CVS: $Id$ |
|
5 * Description: Allow columns to be reordered in a DataTable |
|
6 * Author: Allan Jardine (www.sprymedia.co.uk) |
|
7 * Author: Christophe Battarel (www.altairis.fr) |
|
8 * Created: Wed Sep 15 18:23:29 BST 2010 |
|
9 * Modified: July 2011 by Christophe Battarel - christophe.battarel@altairis.fr (columns resizable) |
|
10 * Modified: February 2012 by Martin Marchetta - martin.marchetta@gmail.com |
|
11 * 1. Made the "hot area" for resizing a little wider (it was a little difficult to hit the exact border of a column for resizing) |
|
12 * 2. Resizing didn't work at all when using scroller (that plugin splits the table into 2 different tables: one for the header and another one for the body, so when you resized the header, the data columns didn't follow) |
|
13 * 3. Fixed collateral effects of sorting feature |
|
14 * 4. If sScrollX is enabled (i.e. horizontal scrolling), when resizing a column the width of the other columns is not changed, but the whole |
|
15 * table is resized to give an Excel-like behavior (good suggestion by Allan) |
|
16 * Modified: February 2012 by Christophe Battarel - christophe.battarel@altairis.fr (ColReorder v1.0.5 adaptation) |
|
17 * Modified: September 16th 2012 by Hassan Kamara - h@phrmc.com |
|
18 * Language: Javascript |
|
19 * License: GPL v2 or BSD 3 point style |
|
20 * Project: DataTables |
|
21 * Contact: www.sprymedia.co.uk/contact |
|
22 * |
|
23 * Copyright 2010-2011 Allan Jardine, all rights reserved. |
|
24 * |
|
25 * This source file is free software, under either the GPL v2 license or a |
|
26 * BSD style license, available at: |
|
27 * http://datatables.net/license_gpl2 |
|
28 * http://datatables.net/license_bsd |
|
29 * |
|
30 */ |
|
31 |
|
32 |
|
33 (function ($, window, document) { |
|
34 |
|
35 |
|
36 /** |
|
37 * Switch the key value pairing of an index array to be value key (i.e. the old value is now the |
|
38 * key). For example consider [ 2, 0, 1 ] this would be returned as [ 1, 2, 0 ]. |
|
39 * @method fnInvertKeyValues |
|
40 * @param array aIn Array to switch around |
|
41 * @returns array |
|
42 */ |
|
43 function fnInvertKeyValues(aIn) { |
|
44 var aRet = []; |
|
45 for (var i = 0, iLen = aIn.length; i < iLen; i++) { |
|
46 aRet[ aIn[i] ] = i; |
|
47 } |
|
48 return aRet; |
|
49 } |
|
50 |
|
51 |
|
52 /** |
|
53 * Modify an array by switching the position of two elements |
|
54 * @method fnArraySwitch |
|
55 * @param array aArray Array to consider, will be modified by reference (i.e. no return) |
|
56 * @param int iFrom From point |
|
57 * @param int iTo Insert point |
|
58 * @returns void |
|
59 */ |
|
60 function fnArraySwitch(aArray, iFrom, iTo) { |
|
61 var mStore = aArray.splice(iFrom, 1)[0]; |
|
62 aArray.splice(iTo, 0, mStore); |
|
63 } |
|
64 |
|
65 |
|
66 /** |
|
67 * Switch the positions of nodes in a parent node (note this is specifically designed for |
|
68 * table rows). Note this function considers all element nodes under the parent! |
|
69 * @method fnDomSwitch |
|
70 * @param string sTag Tag to consider |
|
71 * @param int iFrom Element to move |
|
72 * @param int Point to element the element to (before this point), can be null for append |
|
73 * @returns void |
|
74 */ |
|
75 function fnDomSwitch(nParent, iFrom, iTo) { |
|
76 var anTags = []; |
|
77 for (var i = 0, iLen = nParent.childNodes.length; i < iLen; i++) { |
|
78 if (nParent.childNodes[i].nodeType == 1) { |
|
79 anTags.push(nParent.childNodes[i]); |
|
80 } |
|
81 } |
|
82 var nStore = anTags[ iFrom ]; |
|
83 |
|
84 if (iTo !== null) { |
|
85 nParent.insertBefore(nStore, anTags[iTo]); |
|
86 } |
|
87 else { |
|
88 nParent.appendChild(nStore); |
|
89 } |
|
90 } |
|
91 |
|
92 |
|
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
94 * DataTables plug-in API functions |
|
95 * |
|
96 * This are required by ColReorder in order to perform the tasks required, and also keep this |
|
97 * code portable, to be used for other column reordering projects with DataTables, if needed. |
|
98 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
99 |
|
100 |
|
101 /** |
|
102 * Plug-in for DataTables which will reorder the internal column structure by taking the column |
|
103 * from one position (iFrom) and insert it into a given point (iTo). |
|
104 * @method $.fn.dataTableExt.oApi.fnColReorder |
|
105 * @param object oSettings DataTables settings object - automatically added by DataTables! |
|
106 * @param int iFrom Take the column to be repositioned from this point |
|
107 * @param int iTo and insert it into this point |
|
108 * @returns void |
|
109 */ |
|
110 $.fn.dataTableExt.oApi.fnColReorder = function (oSettings, iFrom, iTo) { |
|
111 var i, iLen, j, jLen, iCols = oSettings.aoColumns.length, nTrs, oCol; |
|
112 |
|
113 /* Sanity check in the input */ |
|
114 if (iFrom == iTo) { |
|
115 /* Pointless reorder */ |
|
116 return; |
|
117 } |
|
118 |
|
119 if (iFrom < 0 || iFrom >= iCols) { |
|
120 this.oApi._fnLog(oSettings, 1, "ColReorder 'from' index is out of bounds: " + iFrom); |
|
121 return; |
|
122 } |
|
123 |
|
124 if (iTo < 0 || iTo >= iCols) { |
|
125 this.oApi._fnLog(oSettings, 1, "ColReorder 'to' index is out of bounds: " + iTo); |
|
126 return; |
|
127 } |
|
128 |
|
129 /* |
|
130 * Calculate the new column array index, so we have a mapping between the old and new |
|
131 */ |
|
132 var aiMapping = []; |
|
133 for (i = 0, iLen = iCols; i < iLen; i++) { |
|
134 aiMapping[i] = i; |
|
135 } |
|
136 fnArraySwitch(aiMapping, iFrom, iTo); |
|
137 var aiInvertMapping = fnInvertKeyValues(aiMapping); |
|
138 |
|
139 |
|
140 /* |
|
141 * Convert all internal indexing to the new column order indexes |
|
142 */ |
|
143 /* Sorting */ |
|
144 for (i = 0, iLen = oSettings.aaSorting.length; i < iLen; i++) { |
|
145 oSettings.aaSorting[i][0] = aiInvertMapping[ oSettings.aaSorting[i][0] ]; |
|
146 } |
|
147 |
|
148 /* Fixed sorting */ |
|
149 if (oSettings.aaSortingFixed !== null) { |
|
150 for (i = 0, iLen = oSettings.aaSortingFixed.length; i < iLen; i++) { |
|
151 oSettings.aaSortingFixed[i][0] = aiInvertMapping[ oSettings.aaSortingFixed[i][0] ]; |
|
152 } |
|
153 } |
|
154 |
|
155 /* Data column sorting (the column which the sort for a given column should take place on) */ |
|
156 for (i = 0, iLen = iCols; i < iLen; i++) { |
|
157 oCol = oSettings.aoColumns[i]; |
|
158 for (j = 0, jLen = oCol.aDataSort.length; j < jLen; j++) { |
|
159 oCol.aDataSort[j] = aiInvertMapping[ oCol.aDataSort[j] ]; |
|
160 } |
|
161 } |
|
162 |
|
163 /* Update the Get and Set functions for each column */ |
|
164 for (i = 0, iLen = iCols; i < iLen; i++) { |
|
165 oCol = oSettings.aoColumns[i]; |
|
166 if (typeof oCol.mData == 'number') { |
|
167 oCol.mData = aiInvertMapping[ oCol.mData ]; |
|
168 oCol.fnGetData = oSettings.oApi._fnGetObjectDataFn(oCol.mData); |
|
169 oCol.fnSetData = oSettings.oApi._fnSetObjectDataFn(oCol.mData); |
|
170 } |
|
171 } |
|
172 |
|
173 |
|
174 /* |
|
175 * Move the DOM elements |
|
176 */ |
|
177 if (oSettings.aoColumns[iFrom].bVisible) { |
|
178 /* Calculate the current visible index and the point to insert the node before. The insert |
|
179 * before needs to take into account that there might not be an element to insert before, |
|
180 * in which case it will be null, and an appendChild should be used |
|
181 */ |
|
182 var iVisibleIndex = this.oApi._fnColumnIndexToVisible(oSettings, iFrom); |
|
183 var iInsertBeforeIndex = null; |
|
184 |
|
185 i = iTo < iFrom ? iTo : iTo + 1; |
|
186 while (iInsertBeforeIndex === null && i < iCols) { |
|
187 iInsertBeforeIndex = this.oApi._fnColumnIndexToVisible(oSettings, i); |
|
188 i++; |
|
189 } |
|
190 |
|
191 /* Header */ |
|
192 nTrs = oSettings.nTHead.getElementsByTagName('tr'); |
|
193 for (i = 0, iLen = nTrs.length; i < iLen; i++) { |
|
194 fnDomSwitch(nTrs[i], iVisibleIndex, iInsertBeforeIndex); |
|
195 } |
|
196 |
|
197 /* Footer */ |
|
198 if (oSettings.nTFoot !== null) { |
|
199 nTrs = oSettings.nTFoot.getElementsByTagName('tr'); |
|
200 for (i = 0, iLen = nTrs.length; i < iLen; i++) { |
|
201 fnDomSwitch(nTrs[i], iVisibleIndex, iInsertBeforeIndex); |
|
202 } |
|
203 } |
|
204 |
|
205 /* Body */ |
|
206 for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) { |
|
207 if (oSettings.aoData[i].nTr !== null) { |
|
208 fnDomSwitch(oSettings.aoData[i].nTr, iVisibleIndex, iInsertBeforeIndex); |
|
209 } |
|
210 } |
|
211 } |
|
212 |
|
213 |
|
214 /* |
|
215 * Move the internal array elements |
|
216 */ |
|
217 /* Columns */ |
|
218 fnArraySwitch(oSettings.aoColumns, iFrom, iTo); |
|
219 |
|
220 /* Search columns */ |
|
221 fnArraySwitch(oSettings.aoPreSearchCols, iFrom, iTo); |
|
222 |
|
223 /* Array array - internal data anodes cache */ |
|
224 for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) { |
|
225 if ($.isArray(oSettings.aoData[i]._aData)) { |
|
226 fnArraySwitch(oSettings.aoData[i]._aData, iFrom, iTo); |
|
227 } |
|
228 fnArraySwitch(oSettings.aoData[i]._anHidden, iFrom, iTo); |
|
229 } |
|
230 |
|
231 /* Reposition the header elements in the header layout array */ |
|
232 for (i = 0, iLen = oSettings.aoHeader.length; i < iLen; i++) { |
|
233 fnArraySwitch(oSettings.aoHeader[i], iFrom, iTo); |
|
234 } |
|
235 |
|
236 if (oSettings.aoFooter !== null) { |
|
237 for (i = 0, iLen = oSettings.aoFooter.length; i < iLen; i++) { |
|
238 fnArraySwitch(oSettings.aoFooter[i], iFrom, iTo); |
|
239 } |
|
240 } |
|
241 |
|
242 |
|
243 /* |
|
244 * Update DataTables' event handlers |
|
245 */ |
|
246 |
|
247 /* Sort listener */ |
|
248 for (i = 0, iLen = iCols; i < iLen; i++) { |
|
249 //Martin Marchetta: |
|
250 //Update this field which is the one used by DataTables for getting the column's data for sorting. |
|
251 oSettings.aoColumns[i].aDataSort = [i]; |
|
252 //Update the internal column index, since columns are actually being re-ordered in the internal structure |
|
253 oSettings.aoColumns[i]._ColReorder_iOrigCol = i; |
|
254 /////////////////////////////////// |
|
255 $(oSettings.aoColumns[i].nTh).unbind('click'); |
|
256 this.oApi._fnSortAttachListener(oSettings, oSettings.aoColumns[i].nTh, i); |
|
257 } |
|
258 |
|
259 |
|
260 /* |
|
261 * Any extra operations for the other plug-ins |
|
262 */ |
|
263 if (typeof ColVis != 'undefined') { |
|
264 ColVis.fnRebuild(oSettings.oInstance); |
|
265 } |
|
266 |
|
267 /* Fire an event so other plug-ins can update */ |
|
268 $(oSettings.oInstance).trigger('column-reorder', [ oSettings, { |
|
269 "iFrom": iFrom, |
|
270 "iTo": iTo, |
|
271 "aiInvertMapping": aiInvertMapping |
|
272 } ]); |
|
273 |
|
274 if (typeof oSettings.oInstance._oPluginFixedHeader != 'undefined') { |
|
275 oSettings.oInstance._oPluginFixedHeader.fnUpdate(); |
|
276 } |
|
277 }; |
|
278 |
|
279 |
|
280 /** |
|
281 * ColReorder provides column visiblity control for DataTables |
|
282 * @class ColReorder |
|
283 * @constructor |
|
284 * @param {object} DataTables settings object |
|
285 * @param {object} ColReorder options |
|
286 */ |
|
287 ColReorder = function (oDTSettings, oOpts) { |
|
288 /* Santiy check that we are a new instance */ |
|
289 if (!this.CLASS || this.CLASS != "ColReorder") { |
|
290 alert("Warning: ColReorder must be initialised with the keyword 'new'"); |
|
291 } |
|
292 |
|
293 if (typeof oOpts == 'undefined') { |
|
294 oOpts = {}; |
|
295 } |
|
296 |
|
297 |
|
298 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
299 * Public class variables |
|
300 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
301 |
|
302 /** |
|
303 * @namespace Settings object which contains customisable information for ColReorder instance |
|
304 */ |
|
305 this.s = { |
|
306 /** |
|
307 * DataTables settings object |
|
308 * @property dt |
|
309 * @type Object |
|
310 * @default null |
|
311 */ |
|
312 "dt": null, |
|
313 |
|
314 /** |
|
315 * Initialisation object used for this instance |
|
316 * @property init |
|
317 * @type object |
|
318 * @default {} |
|
319 */ |
|
320 "init": oOpts, |
|
321 |
|
322 /** |
|
323 * Allow Reorder functionnality |
|
324 * @property allowReorder |
|
325 * @type boolean |
|
326 * @default true |
|
327 */ |
|
328 "allowReorder": true, |
|
329 |
|
330 /** |
|
331 * Allow Resize functionnality |
|
332 * @property allowResize |
|
333 * @type boolean |
|
334 * @default true |
|
335 */ |
|
336 "allowResize": true, |
|
337 |
|
338 /** |
|
339 * Number of columns to fix (not allow to be reordered) |
|
340 * @property fixed |
|
341 * @type int |
|
342 * @default 0 |
|
343 */ |
|
344 "fixed": 0, |
|
345 |
|
346 /** |
|
347 * Callback function for once the reorder has been done |
|
348 * @property dropcallback |
|
349 * @type function |
|
350 * @default null |
|
351 */ |
|
352 "dropCallback": null, |
|
353 |
|
354 /** |
|
355 * @namespace Information used for the mouse drag |
|
356 */ |
|
357 "mouse": { |
|
358 "startX": -1, |
|
359 "startY": -1, |
|
360 "offsetX": -1, |
|
361 "offsetY": -1, |
|
362 "target": -1, |
|
363 "targetIndex": -1, |
|
364 "fromIndex": -1 |
|
365 }, |
|
366 |
|
367 /** |
|
368 * Information which is used for positioning the insert cusor and knowing where to do the |
|
369 * insert. Array of objects with the properties: |
|
370 * x: x-axis position |
|
371 * to: insert point |
|
372 * @property aoTargets |
|
373 * @type array |
|
374 * @default [] |
|
375 */ |
|
376 "aoTargets": [] |
|
377 }; |
|
378 |
|
379 |
|
380 /** |
|
381 * @namespace Common and useful DOM elements for the class instance |
|
382 */ |
|
383 this.dom = { |
|
384 /** |
|
385 * Dragging element (the one the mouse is moving) |
|
386 * @property drag |
|
387 * @type element |
|
388 * @default null |
|
389 */ |
|
390 "drag": null, |
|
391 |
|
392 /** |
|
393 * Resizing a column |
|
394 * @property drag |
|
395 * @type element |
|
396 * @default null |
|
397 */ |
|
398 "resize": null, |
|
399 |
|
400 /** |
|
401 * The insert cursor |
|
402 * @property pointer |
|
403 * @type element |
|
404 * @default null |
|
405 */ |
|
406 "pointer": null |
|
407 }; |
|
408 |
|
409 ///////////////// |
|
410 //Martin Marchetta: keep the current table's size in order to resize it if columns are resized and scrollX is enabled |
|
411 this.table_size = -1; |
|
412 ///////////////// |
|
413 |
|
414 /* Constructor logic */ |
|
415 this.s.dt = oDTSettings.oInstance.fnSettings(); |
|
416 this._fnConstruct(); |
|
417 |
|
418 /* Add destroy callback */ |
|
419 oDTSettings.oApi._fnCallbackReg(oDTSettings, 'aoDestroyCallback', jQuery.proxy(this._fnDestroy, this), 'ColReorder'); |
|
420 |
|
421 /* Store the instance for later use */ |
|
422 ColReorder.aoInstances.push(this); |
|
423 return this; |
|
424 }; |
|
425 |
|
426 |
|
427 ColReorder.prototype = { |
|
428 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
429 * Public methods |
|
430 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
431 |
|
432 "fnReset": function () { |
|
433 var a = []; |
|
434 for (var i = 0, iLen = this.s.dt.aoColumns.length; i < iLen; i++) { |
|
435 a.push(this.s.dt.aoColumns[i]._ColReorder_iOrigCol); |
|
436 } |
|
437 |
|
438 this._fnOrderColumns(a); |
|
439 }, |
|
440 |
|
441 |
|
442 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
443 * Private methods (they are of course public in JS, but recommended as private) |
|
444 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
445 |
|
446 /** |
|
447 * Constructor logic |
|
448 * @method _fnConstruct |
|
449 * @returns void |
|
450 * @private |
|
451 */ |
|
452 "_fnConstruct": function () { |
|
453 var that = this; |
|
454 var i, iLen; |
|
455 |
|
456 /* allow reorder */ |
|
457 if (typeof this.s.init.allowReorder != 'undefined') { |
|
458 this.s.allowReorder = this.s.init.allowReorder; |
|
459 } |
|
460 |
|
461 /* allow resize */ |
|
462 if (typeof this.s.init.allowResize != 'undefined') { |
|
463 this.s.allowResize = this.s.init.allowResize; |
|
464 } |
|
465 |
|
466 /* Columns discounted from reordering - counting left to right */ |
|
467 if (typeof this.s.init.iFixedColumns != 'undefined') { |
|
468 this.s.fixed = this.s.init.iFixedColumns; |
|
469 } |
|
470 |
|
471 /* Drop callback initialisation option */ |
|
472 if (typeof this.s.init.fnReorderCallback != 'undefined') { |
|
473 this.s.dropCallback = this.s.init.fnReorderCallback; |
|
474 } |
|
475 |
|
476 /* Add event handlers for the drag and drop, and also mark the original column order */ |
|
477 for (i = 0, iLen = this.s.dt.aoColumns.length; i < iLen; i++) { |
|
478 if (i > this.s.fixed - 1) { |
|
479 this._fnMouseListener(i, this.s.dt.aoColumns[i].nTh); |
|
480 } |
|
481 |
|
482 /* Mark the original column order for later reference */ |
|
483 this.s.dt.aoColumns[i]._ColReorder_iOrigCol = i; |
|
484 } |
|
485 |
|
486 /* State saving */ |
|
487 this.s.dt.oApi._fnCallbackReg(this.s.dt, 'aoStateSaveParams', function (oS, oData) { |
|
488 that._fnStateSave.call(that, oData); |
|
489 }, "ColReorder_State"); |
|
490 |
|
491 /* An initial column order has been specified */ |
|
492 var aiOrder = null; |
|
493 if (typeof this.s.init.aiOrder != 'undefined') { |
|
494 aiOrder = this.s.init.aiOrder.slice(); |
|
495 } |
|
496 |
|
497 /* State loading, overrides the column order given */ |
|
498 if (this.s.dt.oLoadedState && typeof this.s.dt.oLoadedState.ColReorder != 'undefined' && |
|
499 this.s.dt.oLoadedState.ColReorder.length == this.s.dt.aoColumns.length) { |
|
500 aiOrder = this.s.dt.oLoadedState.ColReorder; |
|
501 } |
|
502 |
|
503 /* If we have an order to apply - do so */ |
|
504 if (aiOrder) { |
|
505 /* We might be called during or after the DataTables initialisation. If before, then we need |
|
506 * to wait until the draw is done, if after, then do what we need to do right away |
|
507 */ |
|
508 if (!that.s.dt._bInitComplete) { |
|
509 var bDone = false; |
|
510 this.s.dt.aoDrawCallback.push({ |
|
511 "fn": function () { |
|
512 if (!that.s.dt._bInitComplete && !bDone) { |
|
513 bDone = true; |
|
514 var resort = fnInvertKeyValues(aiOrder); |
|
515 that._fnOrderColumns.call(that, resort); |
|
516 } |
|
517 }, |
|
518 "sName": "ColReorder_Pre" |
|
519 }); |
|
520 } |
|
521 else { |
|
522 var resort = fnInvertKeyValues(aiOrder); |
|
523 that._fnOrderColumns.call(that, resort); |
|
524 } |
|
525 } |
|
526 }, |
|
527 |
|
528 |
|
529 /** |
|
530 * Set the column order from an array |
|
531 * @method _fnOrderColumns |
|
532 * @param array a An array of integers which dictate the column order that should be applied |
|
533 * @returns void |
|
534 * @private |
|
535 */ |
|
536 "_fnOrderColumns": function (a) { |
|
537 if (a.length != this.s.dt.aoColumns.length) { |
|
538 this.s.dt.oInstance.oApi._fnLog(oDTSettings, 1, "ColReorder - array reorder does not " + |
|
539 "match known number of columns. Skipping."); |
|
540 return; |
|
541 } |
|
542 |
|
543 for (var i = 0, iLen = a.length; i < iLen; i++) { |
|
544 var currIndex = $.inArray(i, a); |
|
545 if (i != currIndex) { |
|
546 /* Reorder our switching array */ |
|
547 fnArraySwitch(a, currIndex, i); |
|
548 |
|
549 /* Do the column reorder in the table */ |
|
550 this.s.dt.oInstance.fnColReorder(currIndex, i); |
|
551 } |
|
552 } |
|
553 |
|
554 /* When scrolling we need to recalculate the column sizes to allow for the shift */ |
|
555 if (this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "") { |
|
556 this.s.dt.oInstance.fnAdjustColumnSizing(); |
|
557 } |
|
558 |
|
559 /* Save the state */ |
|
560 this.s.dt.oInstance.oApi._fnSaveState(this.s.dt); |
|
561 }, |
|
562 |
|
563 |
|
564 /** |
|
565 * Because we change the indexes of columns in the table, relative to their starting point |
|
566 * we need to reorder the state columns to what they are at the starting point so we can |
|
567 * then rearrange them again on state load! |
|
568 * @method _fnStateSave |
|
569 * @param object oState DataTables state |
|
570 * @returns string JSON encoded cookie string for DataTables |
|
571 * @private |
|
572 */ |
|
573 "_fnStateSave": function (oState) { |
|
574 var i, iLen, aCopy, iOrigColumn; |
|
575 var oSettings = this.s.dt; |
|
576 |
|
577 /* Sorting */ |
|
578 for (i = 0; i < oState.aaSorting.length; i++) { |
|
579 oState.aaSorting[i][0] = oSettings.aoColumns[ oState.aaSorting[i][0] ]._ColReorder_iOrigCol; |
|
580 } |
|
581 |
|
582 aSearchCopy = $.extend(true, [], oState.aoSearchCols); |
|
583 oState.ColReorder = []; |
|
584 |
|
585 for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) { |
|
586 iOrigColumn = oSettings.aoColumns[i]._ColReorder_iOrigCol; |
|
587 |
|
588 /* Column filter */ |
|
589 oState.aoSearchCols[ iOrigColumn ] = aSearchCopy[i]; |
|
590 |
|
591 /* Visibility */ |
|
592 oState.abVisCols[ iOrigColumn ] = oSettings.aoColumns[i].bVisible; |
|
593 |
|
594 /* Column reordering */ |
|
595 oState.ColReorder.push(iOrigColumn); |
|
596 } |
|
597 }, |
|
598 |
|
599 |
|
600 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
601 * Mouse drop and drag |
|
602 */ |
|
603 |
|
604 /** |
|
605 * Add a mouse down listener to a particluar TH element |
|
606 * @method _fnMouseListener |
|
607 * @param int i Column index |
|
608 * @param element nTh TH element clicked on |
|
609 * @returns void |
|
610 * @private |
|
611 */ |
|
612 "_fnMouseListener": function (i, nTh) { |
|
613 var that = this; |
|
614 |
|
615 //Martin Marchetta (rebind events since after column re-order they use wrong column indices) |
|
616 $(nTh).unbind('mousemove.ColReorder'); |
|
617 $(nTh).unbind('mousedown.ColReorder'); |
|
618 //////////////// |
|
619 |
|
620 // listen to mousemove event for resize |
|
621 if (this.s.allowResize) { |
|
622 $(nTh).bind('mousemove.ColReorder', function (e) { |
|
623 if (that.dom.drag === null && that.dom.resize === null) { |
|
624 /* Store information about the mouse position */ |
|
625 var nThTarget = e.target.nodeName == "TH" ? e.target : $(e.target).parents('TH')[0]; |
|
626 var offset = $(nThTarget).offset(); |
|
627 var nLength = $(nThTarget).innerWidth(); |
|
628 |
|
629 /* are we on the col border (if so, resize col) */ |
|
630 if (Math.abs(e.pageX - Math.round(offset.left + nLength)) <= 5) { |
|
631 $(nThTarget).css({'cursor': 'col-resize'}); |
|
632 } |
|
633 else |
|
634 $(nThTarget).css({'cursor': 'pointer'}); |
|
635 } |
|
636 }); |
|
637 } |
|
638 |
|
639 // listen to mousedown event |
|
640 $(nTh).bind('mousedown.ColReorder', function (e) { |
|
641 that._fnMouseDown.call(that, e, nTh, i); //Martin Marchetta: added the index of the column dragged or resized |
|
642 return false; |
|
643 }); |
|
644 }, |
|
645 |
|
646 |
|
647 /** |
|
648 * Mouse down on a TH element in the table header |
|
649 * @method _fnMouseDown |
|
650 * @param event e Mouse event |
|
651 * @param element nTh TH element to be dragged |
|
652 * @param i The column that's resized/dragged |
|
653 * @returns void |
|
654 * @private |
|
655 */ |
|
656 "_fnMouseDown": function (e, nTh, i) { |
|
657 var |
|
658 that = this, |
|
659 aoColumns = this.s.dt.aoColumns; |
|
660 |
|
661 /* are we resizing a column ? */ |
|
662 if ($(nTh).css('cursor') == 'col-resize') { |
|
663 this.s.mouse.startX = e.pageX; |
|
664 this.s.mouse.startWidth = $(nTh).width(); |
|
665 this.s.mouse.resizeElem = $(nTh); |
|
666 var nThNext = $(nTh).next(); |
|
667 this.s.mouse.nextStartWidth = $(nThNext).width(); |
|
668 that.dom.resize = true; |
|
669 //////////////////// |
|
670 //Martin Marchetta |
|
671 //a. Disable column sorting so as to avoid issues when finishing column resizing |
|
672 this.s.dt.aoColumns[i].bSortable = false; |
|
673 //b. Disable Autowidth feature (now the user is in charge of setting column width so keeping this enabled looses changes after operations) |
|
674 this.s.dt.oFeatures.bAutoWidth = false; |
|
675 //////////////////// |
|
676 } |
|
677 else if (this.s.allowReorder) { |
|
678 that.dom.resize = null; |
|
679 /* Store information about the mouse position */ |
|
680 var nThTarget = e.target.nodeName == "TH" ? e.target : $(e.target).parents('TH')[0]; |
|
681 var offset = $(nThTarget).offset(); |
|
682 this.s.mouse.startX = e.pageX; |
|
683 this.s.mouse.startY = e.pageY; |
|
684 this.s.mouse.offsetX = e.pageX - offset.left; |
|
685 this.s.mouse.offsetY = e.pageY - offset.top; |
|
686 this.s.mouse.target = nTh; |
|
687 this.s.mouse.targetIndex = $('th', nTh.parentNode).index(nTh); |
|
688 this.s.mouse.fromIndex = this.s.dt.oInstance.oApi._fnVisibleToColumnIndex(this.s.dt, |
|
689 this.s.mouse.targetIndex); |
|
690 |
|
691 /* Calculate a cached array with the points of the column inserts, and the 'to' points */ |
|
692 this.s.aoTargets.splice(0, this.s.aoTargets.length); |
|
693 |
|
694 this.s.aoTargets.push({ |
|
695 "x": $(this.s.dt.nTable).offset().left, |
|
696 "to": 0 |
|
697 }); |
|
698 |
|
699 var iToPoint = 0; |
|
700 for (var i = 0, iLen = aoColumns.length; i < iLen; i++) { |
|
701 /* For the column / header in question, we want it's position to remain the same if the |
|
702 * position is just to it's immediate left or right, so we only incremement the counter for |
|
703 * other columns |
|
704 */ |
|
705 if (i != this.s.mouse.fromIndex) { |
|
706 iToPoint++; |
|
707 } |
|
708 |
|
709 if (aoColumns[i].bVisible) { |
|
710 this.s.aoTargets.push({ |
|
711 "x": $(aoColumns[i].nTh).offset().left + $(aoColumns[i].nTh).outerWidth(), |
|
712 "to": iToPoint |
|
713 }); |
|
714 } |
|
715 } |
|
716 |
|
717 /* Disallow columns for being reordered by drag and drop, counting left to right */ |
|
718 if (this.s.fixed !== 0) { |
|
719 this.s.aoTargets.splice(0, this.s.fixed); |
|
720 } |
|
721 } |
|
722 |
|
723 /* Add event handlers to the document */ |
|
724 $(document).bind('mousemove.ColReorder', function (e) { |
|
725 that._fnMouseMove.call(that, e, i); //Martin Marchetta: Added index of the call being dragged or resized |
|
726 }); |
|
727 |
|
728 $(document).bind('mouseup.ColReorder', function (e) { |
|
729 //Martin Marcheta: Added this small delay in order to prevent collision with column sort feature (there must be a better |
|
730 //way of doing this, but I don't have more time to digg into it) |
|
731 setTimeout(function () { |
|
732 that._fnMouseUp.call(that, e, i); //Martin Marchetta: Added index of the call being dragged or resized |
|
733 }, 10); |
|
734 }); |
|
735 }, |
|
736 |
|
737 |
|
738 /** |
|
739 * Deal with a mouse move event while dragging a node |
|
740 * @method _fnMouseMove |
|
741 * @param event e Mouse event |
|
742 * @param colResized Index of the column that's being dragged or resized (index within the internal model, not the visible order) |
|
743 * @returns void |
|
744 * @private |
|
745 */ |
|
746 "_fnMouseMove": function (e, colResized) { |
|
747 var that = this; |
|
748 |
|
749 //////////////////// |
|
750 //Martin Marchetta: Determine if ScrollX is enabled |
|
751 var scrollXEnabled; |
|
752 |
|
753 scrollXEnabled = this.s.dt.oInit.sScrollX === "" ? false : true; |
|
754 |
|
755 //Keep the current table's width (used in case sScrollX is enabled to resize the whole table, giving an Excel-like behavior) |
|
756 if (this.table_size < 0 && scrollXEnabled && $('div.dataTables_scrollHead', this.s.dt.nTableWrapper) != undefined) { |
|
757 if ($('div.dataTables_scrollHead', this.s.dt.nTableWrapper).length > 0) |
|
758 this.table_size = $($('div.dataTables_scrollHead', this.s.dt.nTableWrapper)[0].childNodes[0].childNodes[0]).width(); |
|
759 } |
|
760 //////////////////// |
|
761 |
|
762 /* are we resizing a column ? */ |
|
763 if (this.dom.resize) { |
|
764 var nTh = this.s.mouse.resizeElem; |
|
765 var nThNext = $(nTh).next(); |
|
766 var moveLength = e.pageX - this.s.mouse.startX; |
|
767 if (moveLength != 0 && !scrollXEnabled) |
|
768 $(nThNext).width(this.s.mouse.nextStartWidth - moveLength); |
|
769 $(nTh).width(this.s.mouse.startWidth + moveLength); |
|
770 |
|
771 //Martin Marchetta: Resize the header too (if sScrollX is enabled) |
|
772 if (scrollXEnabled && $('div.dataTables_scrollHead', this.s.dt.nTableWrapper) != undefined) { |
|
773 if ($('div.dataTables_scrollHead', this.s.dt.nTableWrapper).length > 0) |
|
774 $($('div.dataTables_scrollHead', this.s.dt.nTableWrapper)[0].childNodes[0].childNodes[0]).width(this.table_size + moveLength); |
|
775 } |
|
776 |
|
777 //////////////////////// |
|
778 //Martin Marchetta: Fixed col resizing when the scroller is enabled. |
|
779 var visibleColumnIndex; |
|
780 //First determine if this plugin is being used along with the smart scroller... |
|
781 if ($('div.dataTables_scrollBody') != null) { |
|
782 //...if so, when resizing the header, also resize the table's body (when enabling the Scroller, the table's header and |
|
783 //body are split into different tables, so the column resizing doesn't work anymore) |
|
784 if ($('div.dataTables_scrollBody').length > 0) { |
|
785 //Since some columns might have been hidden, find the correct one to resize in the table's body |
|
786 var currentColumnIndex; |
|
787 visibleColumnIndex = -1; |
|
788 for (currentColumnIndex = -1; currentColumnIndex < this.s.dt.aoColumns.length - 1 && currentColumnIndex != colResized; currentColumnIndex++) { |
|
789 if (this.s.dt.aoColumns[currentColumnIndex + 1].bVisible) |
|
790 visibleColumnIndex++; |
|
791 } |
|
792 |
|
793 //Get the scroller's div |
|
794 tableScroller = $('div.dataTables_scrollBody', this.s.dt.nTableWrapper)[0]; |
|
795 |
|
796 //Get the table |
|
797 scrollingTableHead = $(tableScroller)[0].childNodes[0].childNodes[0].childNodes[0]; |
|
798 |
|
799 //Resize the columns |
|
800 if (moveLength != 0 && !scrollXEnabled) { |
|
801 $($(scrollingTableHead)[0].childNodes[visibleColumnIndex + 1]).width(this.s.mouse.nextStartWidth - moveLength); |
|
802 } |
|
803 $($(scrollingTableHead)[0].childNodes[visibleColumnIndex]).width(this.s.mouse.startWidth + moveLength); |
|
804 |
|
805 //Resize the table too |
|
806 if (scrollXEnabled) |
|
807 $($(tableScroller)[0].childNodes[0]).width(this.table_size + moveLength); |
|
808 } |
|
809 } |
|
810 //////////////////////// |
|
811 |
|
812 return; |
|
813 } |
|
814 else if (this.s.allowReorder) { |
|
815 if (this.dom.drag === null) { |
|
816 /* Only create the drag element if the mouse has moved a specific distance from the start |
|
817 * point - this allows the user to make small mouse movements when sorting and not have a |
|
818 * possibly confusing drag element showing up |
|
819 */ |
|
820 if (Math.pow( |
|
821 Math.pow(e.pageX - this.s.mouse.startX, 2) + |
|
822 Math.pow(e.pageY - this.s.mouse.startY, 2), 0.5) < 5) { |
|
823 return; |
|
824 } |
|
825 this._fnCreateDragNode(); |
|
826 } |
|
827 |
|
828 /* Position the element - we respect where in the element the click occured */ |
|
829 this.dom.drag.style.left = (e.pageX - this.s.mouse.offsetX) + "px"; |
|
830 this.dom.drag.style.top = (e.pageY - this.s.mouse.offsetY) + "px"; |
|
831 |
|
832 /* Based on the current mouse position, calculate where the insert should go */ |
|
833 var bSet = false; |
|
834 for (var i = 1, iLen = this.s.aoTargets.length; i < iLen; i++) { |
|
835 if (e.pageX < this.s.aoTargets[i - 1].x + ((this.s.aoTargets[i].x - this.s.aoTargets[i - 1].x) / 2)) { |
|
836 this.dom.pointer.style.left = this.s.aoTargets[i - 1].x + "px"; |
|
837 this.s.mouse.toIndex = this.s.aoTargets[i - 1].to; |
|
838 bSet = true; |
|
839 break; |
|
840 } |
|
841 } |
|
842 |
|
843 /* The insert element wasn't positioned in the array (less than operator), so we put it at |
|
844 * the end |
|
845 */ |
|
846 if (!bSet) { |
|
847 this.dom.pointer.style.left = this.s.aoTargets[this.s.aoTargets.length - 1].x + "px"; |
|
848 this.s.mouse.toIndex = this.s.aoTargets[this.s.aoTargets.length - 1].to; |
|
849 } |
|
850 } |
|
851 }, |
|
852 |
|
853 |
|
854 /** |
|
855 * Finish off the mouse drag and insert the column where needed |
|
856 * @method _fnMouseUp |
|
857 * @param event e Mouse event |
|
858 * @param colResized The index of the column that was just dragged or resized (index within the internal model, not the visible order). |
|
859 * @returns void |
|
860 * @private |
|
861 */ |
|
862 "_fnMouseUp": function (e, colResized) { |
|
863 var that = this; |
|
864 |
|
865 $(document).unbind('mousemove.ColReorder'); |
|
866 $(document).unbind('mouseup.ColReorder'); |
|
867 |
|
868 if (this.dom.drag !== null) { |
|
869 /* Remove the guide elements */ |
|
870 document.body.removeChild(this.dom.drag); |
|
871 document.body.removeChild(this.dom.pointer); |
|
872 this.dom.drag = null; |
|
873 this.dom.pointer = null; |
|
874 |
|
875 /* Actually do the reorder */ |
|
876 this.s.dt.oInstance.fnColReorder(this.s.mouse.fromIndex, this.s.mouse.toIndex); |
|
877 |
|
878 /* When scrolling we need to recalculate the column sizes to allow for the shift */ |
|
879 if (this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "") { |
|
880 this.s.dt.oInstance.fnAdjustColumnSizing(); |
|
881 } |
|
882 |
|
883 if (this.s.dropCallback !== null) { |
|
884 this.s.dropCallback.call(this); |
|
885 } |
|
886 |
|
887 //////////// |
|
888 //Martin Marchetta: Re-initialize so as to register the new column order |
|
889 //(otherwise the events remain bound to the original column indices) |
|
890 this._fnConstruct(); |
|
891 /////////// |
|
892 |
|
893 /* Save the state */ |
|
894 this.s.dt.oInstance.oApi._fnSaveState(this.s.dt); |
|
895 } |
|
896 /////////////////////////////////////////////////////// |
|
897 //Martin Marchetta |
|
898 else if (this.dom.resize !== null) { |
|
899 var i; |
|
900 var j; |
|
901 var currentColumn; |
|
902 var nextVisibleColumnIndex; |
|
903 var previousVisibleColumnIndex; |
|
904 var scrollXEnabled; |
|
905 |
|
906 //Re-enable column sorting |
|
907 this.s.dt.aoColumns[colResized].bSortable = true; |
|
908 |
|
909 //Save the new resized column's width |
|
910 this.s.dt.aoColumns[colResized].sWidth = $(this.s.mouse.resizeElem).innerWidth() + "px"; |
|
911 |
|
912 //If other columns might have changed their size, save their size too |
|
913 scrollXEnabled = this.s.dt.oInit.sScrollX === "" ? false : true; |
|
914 if (!scrollXEnabled) { |
|
915 //The colResized index (internal model) here might not match the visible index since some columns might have been hidden |
|
916 for (nextVisibleColumnIndex = colResized + 1; nextVisibleColumnIndex < this.s.dt.aoColumns.length; nextVisibleColumnIndex++) { |
|
917 if (this.s.dt.aoColumns[nextVisibleColumnIndex].bVisible) |
|
918 break; |
|
919 } |
|
920 |
|
921 for (previousVisibleColumnIndex = colResized - 1; previousVisibleColumnIndex >= 0; previousVisibleColumnIndex--) { |
|
922 if (this.s.dt.aoColumns[previousVisibleColumnIndex].bVisible) |
|
923 break; |
|
924 } |
|
925 |
|
926 if (this.s.dt.aoColumns.length > nextVisibleColumnIndex) |
|
927 this.s.dt.aoColumns[nextVisibleColumnIndex].sWidth = $(this.s.mouse.resizeElem).next().innerWidth() + "px"; |
|
928 else { //The column resized is the right-most, so save the sizes of all the columns at the left |
|
929 currentColumn = this.s.mouse.resizeElem; |
|
930 for (i = previousVisibleColumnIndex; i > 0; i--) { |
|
931 if (this.s.dt.aoColumns[i].bVisible) { |
|
932 currentColumn = $(currentColumn).prev(); |
|
933 this.s.dt.aoColumns[i].sWidth = $(currentColumn).innerWidth() + "px"; |
|
934 } |
|
935 } |
|
936 } |
|
937 } |
|
938 |
|
939 //Update the internal storage of the table's width (in case we changed it because the user resized some column and scrollX was enabled |
|
940 if (scrollXEnabled && $('div.dataTables_scrollHead', this.s.dt.nTableWrapper) != undefined) { |
|
941 if ($('div.dataTables_scrollHead', this.s.dt.nTableWrapper).length > 0) |
|
942 this.table_size = $($('div.dataTables_scrollHead', this.s.dt.nTableWrapper)[0].childNodes[0].childNodes[0]).width(); |
|
943 } |
|
944 |
|
945 //Save the state |
|
946 this.s.dt.oInstance.oApi._fnSaveState(this.s.dt); |
|
947 } |
|
948 /////////////////////////////////////////////////////// |
|
949 |
|
950 this.dom.resize = null; |
|
951 }, |
|
952 |
|
953 |
|
954 /** |
|
955 * Copy the TH element that is being drags so the user has the idea that they are actually |
|
956 * moving it around the page. |
|
957 * @method _fnCreateDragNode |
|
958 * @returns void |
|
959 * @private |
|
960 */ |
|
961 "_fnCreateDragNode": function () { |
|
962 var that = this; |
|
963 |
|
964 this.dom.drag = $(this.s.dt.nTHead.parentNode).clone(true)[0]; |
|
965 this.dom.drag.className += " DTCR_clonedTable"; |
|
966 while (this.dom.drag.getElementsByTagName('caption').length > 0) { |
|
967 this.dom.drag.removeChild(this.dom.drag.getElementsByTagName('caption')[0]); |
|
968 } |
|
969 while (this.dom.drag.getElementsByTagName('tbody').length > 0) { |
|
970 this.dom.drag.removeChild(this.dom.drag.getElementsByTagName('tbody')[0]); |
|
971 } |
|
972 while (this.dom.drag.getElementsByTagName('tfoot').length > 0) { |
|
973 this.dom.drag.removeChild(this.dom.drag.getElementsByTagName('tfoot')[0]); |
|
974 } |
|
975 |
|
976 $('thead tr:eq(0)', this.dom.drag).each(function () { |
|
977 $('th:not(:eq(' + that.s.mouse.targetIndex + '))', this).remove(); |
|
978 }); |
|
979 $('tr', this.dom.drag).height($('tr:eq(0)', that.s.dt.nTHead).height()); |
|
980 |
|
981 $('thead tr:gt(0)', this.dom.drag).remove(); |
|
982 |
|
983 $('thead th:eq(0)', this.dom.drag).each(function (i) { |
|
984 this.style.width = $('th:eq(' + that.s.mouse.targetIndex + ')', that.s.dt.nTHead).width() + "px"; |
|
985 }); |
|
986 |
|
987 this.dom.drag.style.position = "absolute"; |
|
988 this.dom.drag.style.zIndex = 1200; |
|
989 this.dom.drag.style.top = "0px"; |
|
990 this.dom.drag.style.left = "0px"; |
|
991 this.dom.drag.style.width = $('th:eq(' + that.s.mouse.targetIndex + ')', that.s.dt.nTHead).outerWidth() + "px"; |
|
992 |
|
993 |
|
994 this.dom.pointer = document.createElement('div'); |
|
995 this.dom.pointer.className = "DTCR_pointer"; |
|
996 this.dom.pointer.style.position = "absolute"; |
|
997 |
|
998 if (this.s.dt.oScroll.sX === "" && this.s.dt.oScroll.sY === "") { |
|
999 this.dom.pointer.style.top = $(this.s.dt.nTable).offset().top + "px"; |
|
1000 this.dom.pointer.style.height = $(this.s.dt.nTable).height() + "px"; |
|
1001 } |
|
1002 else { |
|
1003 this.dom.pointer.style.top = $('div.dataTables_scroll', this.s.dt.nTableWrapper).offset().top + "px"; |
|
1004 this.dom.pointer.style.height = $('div.dataTables_scroll', this.s.dt.nTableWrapper).height() + "px"; |
|
1005 } |
|
1006 |
|
1007 document.body.appendChild(this.dom.pointer); |
|
1008 document.body.appendChild(this.dom.drag); |
|
1009 }, |
|
1010 |
|
1011 /** |
|
1012 * Clean up ColReorder memory references and event handlers |
|
1013 * @method _fnDestroy |
|
1014 * @returns void |
|
1015 * @private |
|
1016 */ |
|
1017 "_fnDestroy": function () { |
|
1018 for (var i = 0, iLen = ColReorder.aoInstances.length; i < iLen; i++) { |
|
1019 if (ColReorder.aoInstances[i] === this) { |
|
1020 ColReorder.aoInstances.splice(i, 1); |
|
1021 break; |
|
1022 } |
|
1023 } |
|
1024 |
|
1025 $(this.s.dt.nTHead).find('*').unbind('.ColReorder'); |
|
1026 |
|
1027 this.s.dt.oInstance._oPluginColReorder = null; |
|
1028 this.s = null; |
|
1029 } |
|
1030 }; |
|
1031 |
|
1032 |
|
1033 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
1034 * Static parameters |
|
1035 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
1036 |
|
1037 /** |
|
1038 * Array of all ColReorder instances for later reference |
|
1039 * @property ColReorder.aoInstances |
|
1040 * @type array |
|
1041 * @default [] |
|
1042 * @static |
|
1043 */ |
|
1044 ColReorder.aoInstances = []; |
|
1045 |
|
1046 |
|
1047 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
1048 * Static functions |
|
1049 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
1050 |
|
1051 /** |
|
1052 * Reset the column ordering for a DataTables instance |
|
1053 * @method ColReorder.fnReset |
|
1054 * @param object oTable DataTables instance to consider |
|
1055 * @returns void |
|
1056 * @static |
|
1057 */ |
|
1058 ColReorder.fnReset = function (oTable) { |
|
1059 for (var i = 0, iLen = ColReorder.aoInstances.length; i < iLen; i++) { |
|
1060 if (ColReorder.aoInstances[i].s.dt.oInstance == oTable) { |
|
1061 ColReorder.aoInstances[i].fnReset(); |
|
1062 } |
|
1063 } |
|
1064 }; |
|
1065 |
|
1066 |
|
1067 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
1068 * Constants |
|
1069 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
1070 |
|
1071 /** |
|
1072 * Name of this class |
|
1073 * @constant CLASS |
|
1074 * @type String |
|
1075 * @default ColReorder |
|
1076 */ |
|
1077 ColReorder.prototype.CLASS = "ColReorder"; |
|
1078 |
|
1079 |
|
1080 /** |
|
1081 * ColReorder version |
|
1082 * @constant VERSION |
|
1083 * @type String |
|
1084 * @default As code |
|
1085 */ |
|
1086 ColReorder.VERSION = "1.0.7"; |
|
1087 ColReorder.prototype.VERSION = ColReorder.VERSION; |
|
1088 |
|
1089 |
|
1090 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
1091 * Initialisation |
|
1092 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
1093 |
|
1094 /* |
|
1095 * Register a new feature with DataTables |
|
1096 */ |
|
1097 if (typeof $.fn.dataTable == "function" && |
|
1098 typeof $.fn.dataTableExt.fnVersionCheck == "function" && |
|
1099 $.fn.dataTableExt.fnVersionCheck('1.9.3')) { |
|
1100 $.fn.dataTableExt.aoFeatures.push({ |
|
1101 "fnInit": function (oDTSettings) { |
|
1102 var oTable = oDTSettings.oInstance; |
|
1103 if (typeof oTable._oPluginColReorder == 'undefined') { |
|
1104 var opts = typeof oDTSettings.oInit.oColReorder != 'undefined' ? |
|
1105 oDTSettings.oInit.oColReorder : {}; |
|
1106 oTable._oPluginColReorder = new ColReorder(oDTSettings, opts); |
|
1107 } else { |
|
1108 oTable.oApi._fnLog(oDTSettings, 1, "ColReorder attempted to initialise twice. Ignoring second"); |
|
1109 } |
|
1110 |
|
1111 return null; |
|
1112 /* No node to insert */ |
|
1113 }, |
|
1114 "cFeature": "R", |
|
1115 "sFeature": "ColReorder" |
|
1116 }); |
|
1117 } |
|
1118 else { |
|
1119 alert("Warning: ColReorder requires DataTables 1.9.3 or greater - www.datatables.net/download"); |
|
1120 } |
|
1121 |
|
1122 })(jQuery, window, document); |