|
1 /*! ColVis 1.1.0 |
|
2 * ©2010-2014 SpryMedia Ltd - datatables.net/license |
|
3 */ |
|
4 |
|
5 /** |
|
6 * @summary ColVis |
|
7 * @description Controls for column visibility in DataTables |
|
8 * @version 1.1.0 |
|
9 * @file dataTables.colReorder.js |
|
10 * @author SpryMedia Ltd (www.sprymedia.co.uk) |
|
11 * @contact www.sprymedia.co.uk/contact |
|
12 * @copyright Copyright 2010-2014 SpryMedia Ltd. |
|
13 * |
|
14 * This source file is free software, available under the following license: |
|
15 * MIT license - http://datatables.net/license/mit |
|
16 * |
|
17 * This source file is distributed in the hope that it will be useful, but |
|
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. |
|
20 * |
|
21 * For details please refer to: http://www.datatables.net |
|
22 */ |
|
23 |
|
24 (function (window, document, undefined) { |
|
25 |
|
26 |
|
27 var factory = function ($, DataTable) { |
|
28 "use strict"; |
|
29 |
|
30 /** |
|
31 * ColVis provides column visibility control for DataTables |
|
32 * |
|
33 * @class ColVis |
|
34 * @constructor |
|
35 * @param {object} DataTables settings object. With DataTables 1.10 this can |
|
36 * also be and API instance, table node, jQuery collection or jQuery selector. |
|
37 * @param {object} ColVis configuration options |
|
38 */ |
|
39 var ColVis = function (oDTSettings, oInit) { |
|
40 /* Santiy check that we are a new instance */ |
|
41 if (!this.CLASS || this.CLASS != "ColVis") { |
|
42 alert("Warning: ColVis must be initialised with the keyword 'new'"); |
|
43 } |
|
44 |
|
45 if (typeof oInit == 'undefined') { |
|
46 oInit = {}; |
|
47 } |
|
48 |
|
49 if ($.fn.dataTable.camelToHungarian) { |
|
50 $.fn.dataTable.camelToHungarian(ColVis.defaults, oInit); |
|
51 } |
|
52 |
|
53 |
|
54 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
55 * Public class variables |
|
56 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
57 |
|
58 /** |
|
59 * @namespace Settings object which contains customisable information for |
|
60 * ColVis instance. Augmented by ColVis.defaults |
|
61 */ |
|
62 this.s = { |
|
63 /** |
|
64 * DataTables settings object |
|
65 * @property dt |
|
66 * @type Object |
|
67 * @default null |
|
68 */ |
|
69 "dt": null, |
|
70 |
|
71 /** |
|
72 * Customisation object |
|
73 * @property oInit |
|
74 * @type Object |
|
75 * @default passed in |
|
76 */ |
|
77 "oInit": oInit, |
|
78 |
|
79 /** |
|
80 * Flag to say if the collection is hidden |
|
81 * @property hidden |
|
82 * @type boolean |
|
83 * @default true |
|
84 */ |
|
85 "hidden": true, |
|
86 |
|
87 /** |
|
88 * Store the original visibility settings so they could be restored |
|
89 * @property abOriginal |
|
90 * @type Array |
|
91 * @default [] |
|
92 */ |
|
93 "abOriginal": [] |
|
94 }; |
|
95 |
|
96 |
|
97 /** |
|
98 * @namespace Common and useful DOM elements for the class instance |
|
99 */ |
|
100 this.dom = { |
|
101 /** |
|
102 * Wrapper for the button - given back to DataTables as the node to insert |
|
103 * @property wrapper |
|
104 * @type Node |
|
105 * @default null |
|
106 */ |
|
107 "wrapper": null, |
|
108 |
|
109 /** |
|
110 * Activation button |
|
111 * @property button |
|
112 * @type Node |
|
113 * @default null |
|
114 */ |
|
115 "button": null, |
|
116 |
|
117 /** |
|
118 * Collection list node |
|
119 * @property collection |
|
120 * @type Node |
|
121 * @default null |
|
122 */ |
|
123 "collection": null, |
|
124 |
|
125 /** |
|
126 * Background node used for shading the display and event capturing |
|
127 * @property background |
|
128 * @type Node |
|
129 * @default null |
|
130 */ |
|
131 "background": null, |
|
132 |
|
133 /** |
|
134 * Element to position over the activation button to catch mouse events when using mouseover |
|
135 * @property catcher |
|
136 * @type Node |
|
137 * @default null |
|
138 */ |
|
139 "catcher": null, |
|
140 |
|
141 /** |
|
142 * List of button elements |
|
143 * @property buttons |
|
144 * @type Array |
|
145 * @default [] |
|
146 */ |
|
147 "buttons": [], |
|
148 |
|
149 /** |
|
150 * List of group button elements |
|
151 * @property groupButtons |
|
152 * @type Array |
|
153 * @default [] |
|
154 */ |
|
155 "groupButtons": [], |
|
156 |
|
157 /** |
|
158 * Restore button |
|
159 * @property restore |
|
160 * @type Node |
|
161 * @default null |
|
162 */ |
|
163 "restore": null |
|
164 }; |
|
165 |
|
166 /* Store global reference */ |
|
167 ColVis.aInstances.push(this); |
|
168 |
|
169 /* Constructor logic */ |
|
170 this.s.dt = $.fn.dataTable.Api ? |
|
171 new $.fn.dataTable.Api(oDTSettings).settings()[0] : |
|
172 oDTSettings; |
|
173 |
|
174 this._fnConstruct(oInit); |
|
175 return this; |
|
176 }; |
|
177 |
|
178 |
|
179 ColVis.prototype = { |
|
180 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
181 * Public methods |
|
182 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
183 |
|
184 /** |
|
185 * Get the ColVis instance's control button so it can be injected into the |
|
186 * DOM |
|
187 * @method button |
|
188 * @returns {node} ColVis button |
|
189 */ |
|
190 button: function () { |
|
191 return this.dom.wrapper; |
|
192 }, |
|
193 |
|
194 /** |
|
195 * Alias of `rebuild` for backwards compatibility |
|
196 * @method fnRebuild |
|
197 */ |
|
198 "fnRebuild": function () { |
|
199 this.rebuild(); |
|
200 }, |
|
201 |
|
202 /** |
|
203 * Rebuild the list of buttons for this instance (i.e. if there is a column |
|
204 * header update) |
|
205 * @method fnRebuild |
|
206 */ |
|
207 rebuild: function () { |
|
208 /* Remove the old buttons */ |
|
209 for (var i = this.dom.buttons.length - 1; i >= 0; i--) { |
|
210 this.dom.collection.removeChild(this.dom.buttons[i]); |
|
211 } |
|
212 this.dom.buttons.splice(0, this.dom.buttons.length); |
|
213 |
|
214 if (this.dom.restore) { |
|
215 this.dom.restore.parentNode(this.dom.restore); |
|
216 } |
|
217 |
|
218 /* Re-add them (this is not the optimal way of doing this, it is fast and effective) */ |
|
219 this._fnAddGroups(); |
|
220 this._fnAddButtons(); |
|
221 |
|
222 /* Update the checkboxes */ |
|
223 this._fnDrawCallback(); |
|
224 }, |
|
225 |
|
226 |
|
227 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
228 * Private methods (they are of course public in JS, but recommended as private) |
|
229 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
230 |
|
231 /** |
|
232 * Constructor logic |
|
233 * @method _fnConstruct |
|
234 * @returns void |
|
235 * @private |
|
236 */ |
|
237 "_fnConstruct": function (init) { |
|
238 this._fnApplyCustomisation(init); |
|
239 |
|
240 var that = this; |
|
241 var i, iLen; |
|
242 this.dom.wrapper = document.createElement('div'); |
|
243 this.dom.wrapper.className = "ColVis"; |
|
244 |
|
245 this.dom.button = $('<button />', { |
|
246 'class': !this.s.dt.bJUI ? |
|
247 "ColVis_Button ColVis_MasterButton" : |
|
248 "ColVis_Button ColVis_MasterButton ui-button ui-state-default" |
|
249 }) |
|
250 .append('<span>' + this.s.buttonText + '</span>') |
|
251 .bind(this.s.activate == "mouseover" ? "mouseover" : "click", function (e) { |
|
252 e.preventDefault(); |
|
253 that._fnCollectionShow(); |
|
254 }) |
|
255 .appendTo(this.dom.wrapper)[0]; |
|
256 |
|
257 this.dom.catcher = this._fnDomCatcher(); |
|
258 this.dom.collection = this._fnDomCollection(); |
|
259 this.dom.background = this._fnDomBackground(); |
|
260 |
|
261 this._fnAddGroups(); |
|
262 this._fnAddButtons(); |
|
263 |
|
264 /* Store the original visibility information */ |
|
265 for (i = 0, iLen = this.s.dt.aoColumns.length; i < iLen; i++) { |
|
266 this.s.abOriginal.push(this.s.dt.aoColumns[i].bVisible); |
|
267 } |
|
268 |
|
269 /* Update on each draw */ |
|
270 this.s.dt.aoDrawCallback.push({ |
|
271 "fn": function () { |
|
272 that._fnDrawCallback.call(that); |
|
273 }, |
|
274 "sName": "ColVis" |
|
275 }); |
|
276 |
|
277 /* If columns are reordered, then we need to update our exclude list and |
|
278 * rebuild the displayed list |
|
279 */ |
|
280 $(this.s.dt.oInstance).bind('column-reorder', function (e, oSettings, oReorder) { |
|
281 for (i = 0, iLen = that.s.aiExclude.length; i < iLen; i++) { |
|
282 that.s.aiExclude[i] = oReorder.aiInvertMapping[ that.s.aiExclude[i] ]; |
|
283 } |
|
284 |
|
285 var mStore = that.s.abOriginal.splice(oReorder.iFrom, 1)[0]; |
|
286 that.s.abOriginal.splice(oReorder.iTo, 0, mStore); |
|
287 |
|
288 that.fnRebuild(); |
|
289 }); |
|
290 |
|
291 // Set the initial state |
|
292 this._fnDrawCallback(); |
|
293 }, |
|
294 |
|
295 |
|
296 /** |
|
297 * Apply any customisation to the settings from the DataTables initialisation |
|
298 * @method _fnApplyCustomisation |
|
299 * @returns void |
|
300 * @private |
|
301 */ |
|
302 "_fnApplyCustomisation": function (init) { |
|
303 $.extend(true, this.s, ColVis.defaults, init); |
|
304 |
|
305 // Slightly messy overlap for the camelCase notation |
|
306 if (!this.s.showAll && this.s.bShowAll) { |
|
307 this.s.showAll = this.s.sShowAll; |
|
308 } |
|
309 |
|
310 if (!this.s.restore && this.s.bRestore) { |
|
311 this.s.restore = this.s.sRestore; |
|
312 } |
|
313 |
|
314 // CamelCase to Hungarian for the column groups |
|
315 var groups = this.s.groups; |
|
316 var hungarianGroups = this.s.aoGroups; |
|
317 if (groups) { |
|
318 for (var i = 0, ien = groups.length; i < ien; i++) { |
|
319 if (groups[i].title) { |
|
320 hungarianGroups[i].sTitle = groups[i].title; |
|
321 } |
|
322 if (groups[i].columns) { |
|
323 hungarianGroups[i].aiColumns = groups[i].columns; |
|
324 } |
|
325 } |
|
326 } |
|
327 }, |
|
328 |
|
329 |
|
330 /** |
|
331 * On each table draw, check the visibility checkboxes as needed. This allows any process to |
|
332 * update the table's column visibility and ColVis will still be accurate. |
|
333 * @method _fnDrawCallback |
|
334 * @returns void |
|
335 * @private |
|
336 */ |
|
337 "_fnDrawCallback": function () { |
|
338 var columns = this.s.dt.aoColumns; |
|
339 var buttons = this.dom.buttons; |
|
340 var groups = this.s.aoGroups; |
|
341 var button; |
|
342 |
|
343 for (var i = 0, ien = buttons.length; i < ien; i++) { |
|
344 button = buttons[i]; |
|
345 |
|
346 if (button.__columnIdx !== undefined) { |
|
347 $('input', button).prop('checked', columns[ button.__columnIdx ].bVisible); |
|
348 } |
|
349 } |
|
350 |
|
351 var allVisible = function (columnIndeces) { |
|
352 for (var k = 0, kLen = columnIndeces.length; k < kLen; k++) { |
|
353 if (columns[columnIndeces[k]].bVisible === false) { |
|
354 return false; |
|
355 } |
|
356 } |
|
357 return true; |
|
358 }; |
|
359 var allHidden = function (columnIndeces) { |
|
360 for (var m = 0 , mLen = columnIndeces.length; m < mLen; m++) { |
|
361 if (columns[columnIndeces[m]].bVisible === true) { |
|
362 return false; |
|
363 } |
|
364 } |
|
365 return true; |
|
366 }; |
|
367 |
|
368 for (var j = 0, jLen = groups.length; j < jLen; j++) { |
|
369 if (allVisible(groups[j].aiColumns)) { |
|
370 $('input', this.dom.groupButtons[j]).prop('checked', true); |
|
371 $('input', this.dom.groupButtons[j]).prop('indeterminate', false); |
|
372 } |
|
373 else if (allHidden(groups[j].aiColumns)) { |
|
374 $('input', this.dom.groupButtons[j]).prop('checked', false); |
|
375 $('input', this.dom.groupButtons[j]).prop('indeterminate', false); |
|
376 } |
|
377 else { |
|
378 $('input', this.dom.groupButtons[j]).prop('indeterminate', true); |
|
379 } |
|
380 } |
|
381 }, |
|
382 |
|
383 |
|
384 /** |
|
385 * Loop through the groups (provided in the settings) and create a button for each. |
|
386 * @method _fnAddgroups |
|
387 * @returns void |
|
388 * @private |
|
389 */ |
|
390 "_fnAddGroups": function () { |
|
391 var nButton; |
|
392 |
|
393 if (typeof this.s.aoGroups != 'undefined') { |
|
394 for (var i = 0, iLen = this.s.aoGroups.length; i < iLen; i++) { |
|
395 nButton = this._fnDomGroupButton(i); |
|
396 this.dom.groupButtons.push(nButton); |
|
397 this.dom.buttons.push(nButton); |
|
398 this.dom.collection.appendChild(nButton); |
|
399 } |
|
400 } |
|
401 }, |
|
402 |
|
403 |
|
404 /** |
|
405 * Loop through the columns in the table and as a new button for each one. |
|
406 * @method _fnAddButtons |
|
407 * @returns void |
|
408 * @private |
|
409 */ |
|
410 "_fnAddButtons": function () { |
|
411 var |
|
412 nButton, |
|
413 columns = this.s.dt.aoColumns; |
|
414 |
|
415 if ($.inArray('all', this.s.aiExclude) === -1) { |
|
416 for (var i = 0, iLen = columns.length; i < iLen; i++) { |
|
417 if ($.inArray(i, this.s.aiExclude) === -1) { |
|
418 nButton = this._fnDomColumnButton(i); |
|
419 nButton.__columnIdx = i; |
|
420 this.dom.buttons.push(nButton); |
|
421 } |
|
422 } |
|
423 } |
|
424 |
|
425 if (this.s.order === 'alpha') { |
|
426 this.dom.buttons.sort(function (a, b) { |
|
427 var titleA = columns[ a.__columnIdx ].sTitle; |
|
428 var titleB = columns[ b.__columnIdx ].sTitle; |
|
429 |
|
430 return titleA === titleB ? |
|
431 0 : |
|
432 titleA < titleB ? |
|
433 -1 : |
|
434 1; |
|
435 }); |
|
436 } |
|
437 |
|
438 if (this.s.restore) { |
|
439 nButton = this._fnDomRestoreButton(); |
|
440 nButton.className += " ColVis_Restore"; |
|
441 this.dom.buttons.push(nButton); |
|
442 } |
|
443 |
|
444 if (this.s.showAll) { |
|
445 nButton = this._fnDomShowAllButton(); |
|
446 nButton.className += " ColVis_ShowAll"; |
|
447 this.dom.buttons.push(nButton); |
|
448 } |
|
449 |
|
450 $(this.dom.collection).append(this.dom.buttons); |
|
451 }, |
|
452 |
|
453 |
|
454 /** |
|
455 * Create a button which allows a "restore" action |
|
456 * @method _fnDomRestoreButton |
|
457 * @returns {Node} Created button |
|
458 * @private |
|
459 */ |
|
460 "_fnDomRestoreButton": function () { |
|
461 var |
|
462 that = this, |
|
463 dt = this.s.dt; |
|
464 |
|
465 return $( |
|
466 '<li class="ColVis_Special ' + (dt.bJUI ? 'ui-button ui-state-default' : '') + '">' + |
|
467 this.s.restore + |
|
468 '</li>' |
|
469 ) |
|
470 .click(function (e) { |
|
471 for (var i = 0, iLen = that.s.abOriginal.length; i < iLen; i++) { |
|
472 that.s.dt.oInstance.fnSetColumnVis(i, that.s.abOriginal[i], false); |
|
473 } |
|
474 that._fnAdjustOpenRows(); |
|
475 that.s.dt.oInstance.fnAdjustColumnSizing(false); |
|
476 that.s.dt.oInstance.fnDraw(false); |
|
477 })[0]; |
|
478 }, |
|
479 |
|
480 |
|
481 /** |
|
482 * Create a button which allows a "show all" action |
|
483 * @method _fnDomShowAllButton |
|
484 * @returns {Node} Created button |
|
485 * @private |
|
486 */ |
|
487 "_fnDomShowAllButton": function () { |
|
488 var |
|
489 that = this, |
|
490 dt = this.s.dt; |
|
491 |
|
492 return $( |
|
493 '<li class="ColVis_Special ' + (dt.bJUI ? 'ui-button ui-state-default' : '') + '">' + |
|
494 this.s.showAll + |
|
495 '</li>' |
|
496 ) |
|
497 .click(function (e) { |
|
498 for (var i = 0, iLen = that.s.abOriginal.length; i < iLen; i++) { |
|
499 if (that.s.aiExclude.indexOf(i) === -1) { |
|
500 that.s.dt.oInstance.fnSetColumnVis(i, true, false); |
|
501 } |
|
502 } |
|
503 that._fnAdjustOpenRows(); |
|
504 that.s.dt.oInstance.fnAdjustColumnSizing(false); |
|
505 that.s.dt.oInstance.fnDraw(false); |
|
506 })[0]; |
|
507 }, |
|
508 |
|
509 |
|
510 /** |
|
511 * Create the DOM for a show / hide group button |
|
512 * @method _fnDomGroupButton |
|
513 * @param {int} i Group in question, order based on that provided in settings |
|
514 * @returns {Node} Created button |
|
515 * @private |
|
516 */ |
|
517 "_fnDomGroupButton": function (i) { |
|
518 var |
|
519 that = this, |
|
520 dt = this.s.dt, |
|
521 oGroup = this.s.aoGroups[i]; |
|
522 |
|
523 return $( |
|
524 '<li class="ColVis_Special ' + (dt.bJUI ? 'ui-button ui-state-default' : '') + '">' + |
|
525 '<label>' + |
|
526 '<input type="checkbox" />' + |
|
527 '<span>' + oGroup.sTitle + '</span>' + |
|
528 '</label>' + |
|
529 '</li>' |
|
530 ) |
|
531 .click(function (e) { |
|
532 var showHide = !$('input', this).is(":checked"); |
|
533 if (e.target.nodeName.toLowerCase() !== "li") { |
|
534 showHide = !showHide; |
|
535 } |
|
536 |
|
537 for (var j = 0; j < oGroup.aiColumns.length; j++) { |
|
538 that.s.dt.oInstance.fnSetColumnVis(oGroup.aiColumns[j], showHide); |
|
539 } |
|
540 })[0]; |
|
541 }, |
|
542 |
|
543 |
|
544 /** |
|
545 * Create the DOM for a show / hide button |
|
546 * @method _fnDomColumnButton |
|
547 * @param {int} i Column in question |
|
548 * @returns {Node} Created button |
|
549 * @private |
|
550 */ |
|
551 "_fnDomColumnButton": function (i) { |
|
552 var |
|
553 that = this, |
|
554 column = this.s.dt.aoColumns[i], |
|
555 dt = this.s.dt; |
|
556 |
|
557 var title = this.s.fnLabel === null ? |
|
558 column.sTitle : |
|
559 this.s.fnLabel(i, column.sTitle, column.nTh); |
|
560 |
|
561 return $( |
|
562 '<li ' + (dt.bJUI ? 'class="ui-button ui-state-default"' : '') + '>' + |
|
563 '<label>' + |
|
564 '<input type="checkbox" />' + |
|
565 '<span>' + title + '</span>' + |
|
566 '</label>' + |
|
567 '</li>' |
|
568 ) |
|
569 .click(function (e) { |
|
570 var showHide = !$('input', this).is(":checked"); |
|
571 if (e.target.nodeName.toLowerCase() !== "li") { |
|
572 showHide = !showHide; |
|
573 } |
|
574 |
|
575 /* Need to consider the case where the initialiser created more than one table - change the |
|
576 * API index that DataTables is using |
|
577 */ |
|
578 var oldIndex = $.fn.dataTableExt.iApiIndex; |
|
579 $.fn.dataTableExt.iApiIndex = that._fnDataTablesApiIndex.call(that); |
|
580 |
|
581 // Optimisation for server-side processing when scrolling - don't do a full redraw |
|
582 if (dt.oFeatures.bServerSide) { |
|
583 that.s.dt.oInstance.fnSetColumnVis(i, showHide, false); |
|
584 that.s.dt.oInstance.fnAdjustColumnSizing(false); |
|
585 if (dt.oScroll.sX !== "" || dt.oScroll.sY !== "") { |
|
586 that.s.dt.oInstance.oApi._fnScrollDraw(that.s.dt); |
|
587 } |
|
588 that._fnDrawCallback(); |
|
589 } |
|
590 else { |
|
591 that.s.dt.oInstance.fnSetColumnVis(i, showHide); |
|
592 } |
|
593 |
|
594 $.fn.dataTableExt.iApiIndex = oldIndex; |
|
595 /* Restore */ |
|
596 |
|
597 if (that.s.fnStateChange !== null) { |
|
598 that.s.fnStateChange.call(that, i, showHide); |
|
599 } |
|
600 })[0]; |
|
601 }, |
|
602 |
|
603 |
|
604 /** |
|
605 * Get the position in the DataTables instance array of the table for this |
|
606 * instance of ColVis |
|
607 * @method _fnDataTablesApiIndex |
|
608 * @returns {int} Index |
|
609 * @private |
|
610 */ |
|
611 "_fnDataTablesApiIndex": function () { |
|
612 for (var i = 0, iLen = this.s.dt.oInstance.length; i < iLen; i++) { |
|
613 if (this.s.dt.oInstance[i] == this.s.dt.nTable) { |
|
614 return i; |
|
615 } |
|
616 } |
|
617 return 0; |
|
618 }, |
|
619 |
|
620 |
|
621 /** |
|
622 * Create the element used to contain list the columns (it is shown and |
|
623 * hidden as needed) |
|
624 * @method _fnDomCollection |
|
625 * @returns {Node} div container for the collection |
|
626 * @private |
|
627 */ |
|
628 "_fnDomCollection": function () { |
|
629 var that = this; |
|
630 return $('<ul />', { |
|
631 'class': !that.s.dt.bJUI ? |
|
632 "ColVis_collection" : |
|
633 "ColVis_collection ui-buttonset ui-buttonset-multi" |
|
634 }) |
|
635 .css({ |
|
636 'display': 'none', |
|
637 'opacity': 0, |
|
638 'position': !that.s.bCssPosition ? |
|
639 'absolute' : |
|
640 '' |
|
641 })[0]; |
|
642 }, |
|
643 |
|
644 |
|
645 /** |
|
646 * An element to be placed on top of the activate button to catch events |
|
647 * @method _fnDomCatcher |
|
648 * @returns {Node} div container for the collection |
|
649 * @private |
|
650 */ |
|
651 "_fnDomCatcher": function () { |
|
652 var |
|
653 that = this, |
|
654 nCatcher = document.createElement('div'); |
|
655 nCatcher.className = "ColVis_catcher"; |
|
656 |
|
657 $(nCatcher).click(function () { |
|
658 that._fnCollectionHide.call(that, null, null); |
|
659 }); |
|
660 |
|
661 return nCatcher; |
|
662 }, |
|
663 |
|
664 |
|
665 /** |
|
666 * Create the element used to shade the background, and capture hide events (it is shown and |
|
667 * hidden as needed) |
|
668 * @method _fnDomBackground |
|
669 * @returns {Node} div container for the background |
|
670 * @private |
|
671 */ |
|
672 "_fnDomBackground": function () { |
|
673 var that = this; |
|
674 |
|
675 var background = $('<div></div>') |
|
676 .addClass('ColVis_collectionBackground') |
|
677 .css('opacity', 0) |
|
678 .click(function () { |
|
679 that._fnCollectionHide.call(that, null, null); |
|
680 }); |
|
681 |
|
682 /* When considering a mouse over action for the activation, we also consider a mouse out |
|
683 * which is the same as a mouse over the background - without all the messing around of |
|
684 * bubbling events. Use the catcher element to avoid messing around with bubbling |
|
685 */ |
|
686 if (this.s.activate == "mouseover") { |
|
687 background.mouseover(function () { |
|
688 that.s.overcollection = false; |
|
689 that._fnCollectionHide.call(that, null, null); |
|
690 }); |
|
691 } |
|
692 |
|
693 return background[0]; |
|
694 }, |
|
695 |
|
696 |
|
697 /** |
|
698 * Show the show / hide list and the background |
|
699 * @method _fnCollectionShow |
|
700 * @returns void |
|
701 * @private |
|
702 */ |
|
703 "_fnCollectionShow": function () { |
|
704 var that = this, i, iLen, iLeft; |
|
705 var oPos = $(this.dom.button).offset(); |
|
706 var nHidden = this.dom.collection; |
|
707 var nBackground = this.dom.background; |
|
708 var iDivX = parseInt(oPos.left, 10); |
|
709 var iDivY = parseInt(oPos.top + $(this.dom.button).outerHeight(), 10); |
|
710 |
|
711 if (!this.s.bCssPosition) { |
|
712 nHidden.style.top = iDivY + "px"; |
|
713 nHidden.style.left = iDivX + "px"; |
|
714 } |
|
715 |
|
716 $(nHidden).css({ |
|
717 'display': 'block', |
|
718 'opacity': 0 |
|
719 }); |
|
720 |
|
721 // nBackground.style.bottom ='0px'; |
|
722 // nBackground.style.right = '0px'; |
|
723 |
|
724 // var oStyle = this.dom.catcher.style; |
|
725 // oStyle.height = $(this.dom.button).outerHeight()+"px"; |
|
726 // oStyle.width = $(this.dom.button).outerWidth()+"px"; |
|
727 // oStyle.top = oPos.top+"px"; |
|
728 // oStyle.left = iDivX+"px"; |
|
729 |
|
730 document.body.appendChild(nBackground); |
|
731 document.body.appendChild(nHidden); |
|
732 document.body.appendChild(this.dom.catcher); |
|
733 |
|
734 /* This results in a very small delay for the end user but it allows the animation to be |
|
735 * much smoother. If you don't want the animation, then the setTimeout can be removed |
|
736 */ |
|
737 $(nHidden).animate({"opacity": 1}, that.s.iOverlayFade); |
|
738 $(nBackground).animate({"opacity": 0.1}, that.s.iOverlayFade, 'linear', function () { |
|
739 /* In IE6 if you set the checked attribute of a hidden checkbox, then this is not visually |
|
740 * reflected. As such, we need to do it here, once it is visible. Unbelievable. |
|
741 */ |
|
742 if ($.browser && $.browser.msie && $.browser.version == "6.0") { |
|
743 that._fnDrawCallback(); |
|
744 } |
|
745 }); |
|
746 |
|
747 /* Visual corrections to try and keep the collection visible */ |
|
748 if (!this.s.bCssPosition) { |
|
749 iLeft = ( this.s.sAlign == "left" ) ? |
|
750 iDivX : |
|
751 iDivX - $(nHidden).outerWidth() + $(this.dom.button).outerWidth(); |
|
752 |
|
753 nHidden.style.left = iLeft + "px"; |
|
754 |
|
755 var iDivWidth = $(nHidden).outerWidth(); |
|
756 var iDivHeight = $(nHidden).outerHeight(); |
|
757 var iDocWidth = $(document).width(); |
|
758 |
|
759 if (iLeft + iDivWidth > iDocWidth) { |
|
760 nHidden.style.left = (iDocWidth - iDivWidth) + "px"; |
|
761 } |
|
762 } |
|
763 |
|
764 this.s.hidden = false; |
|
765 }, |
|
766 |
|
767 |
|
768 /** |
|
769 * Hide the show / hide list and the background |
|
770 * @method _fnCollectionHide |
|
771 * @returns void |
|
772 * @private |
|
773 */ |
|
774 "_fnCollectionHide": function () { |
|
775 var that = this; |
|
776 |
|
777 if (!this.s.hidden && this.dom.collection !== null) { |
|
778 this.s.hidden = true; |
|
779 |
|
780 $(this.dom.collection).animate({"opacity": 0}, that.s.iOverlayFade, function (e) { |
|
781 this.style.display = "none"; |
|
782 }); |
|
783 |
|
784 $(this.dom.background).animate({"opacity": 0}, that.s.iOverlayFade, function (e) { |
|
785 document.body.removeChild(that.dom.background); |
|
786 document.body.removeChild(that.dom.catcher); |
|
787 }); |
|
788 } |
|
789 }, |
|
790 |
|
791 |
|
792 /** |
|
793 * Alter the colspan on any fnOpen rows |
|
794 */ |
|
795 "_fnAdjustOpenRows": function () { |
|
796 var aoOpen = this.s.dt.aoOpenRows; |
|
797 var iVisible = this.s.dt.oApi._fnVisbleColumns(this.s.dt); |
|
798 |
|
799 for (var i = 0, iLen = aoOpen.length; i < iLen; i++) { |
|
800 aoOpen[i].nTr.getElementsByTagName('td')[0].colSpan = iVisible; |
|
801 } |
|
802 } |
|
803 }; |
|
804 |
|
805 |
|
806 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
807 * Static object methods |
|
808 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
809 |
|
810 /** |
|
811 * Rebuild the collection for a given table, or all tables if no parameter given |
|
812 * @method ColVis.fnRebuild |
|
813 * @static |
|
814 * @param object oTable DataTable instance to consider - optional |
|
815 * @returns void |
|
816 */ |
|
817 ColVis.fnRebuild = function (oTable) { |
|
818 var nTable = null; |
|
819 if (typeof oTable != 'undefined') { |
|
820 nTable = oTable.fnSettings().nTable; |
|
821 } |
|
822 |
|
823 for (var i = 0, iLen = ColVis.aInstances.length; i < iLen; i++) { |
|
824 if (typeof oTable == 'undefined' || nTable == ColVis.aInstances[i].s.dt.nTable) { |
|
825 ColVis.aInstances[i].fnRebuild(); |
|
826 } |
|
827 } |
|
828 }; |
|
829 |
|
830 |
|
831 ColVis.defaults = { |
|
832 /** |
|
833 * Mode of activation. Can be 'click' or 'mouseover' |
|
834 * @property activate |
|
835 * @type string |
|
836 * @default click |
|
837 */ |
|
838 active: 'click', |
|
839 |
|
840 /** |
|
841 * Text used for the button |
|
842 * @property buttonText |
|
843 * @type string |
|
844 * @default Show / hide columns |
|
845 */ |
|
846 buttonText: 'Show / hide columns', |
|
847 |
|
848 /** |
|
849 * List of columns (integers) which should be excluded from the list |
|
850 * @property aiExclude |
|
851 * @type array |
|
852 * @default [] |
|
853 */ |
|
854 aiExclude: [], |
|
855 |
|
856 /** |
|
857 * Show restore button |
|
858 * @property bRestore |
|
859 * @type boolean |
|
860 * @default false |
|
861 */ |
|
862 bRestore: false, |
|
863 |
|
864 /** |
|
865 * Restore button text |
|
866 * @property sRestore |
|
867 * @type string |
|
868 * @default Restore original |
|
869 */ |
|
870 sRestore: 'Restore original', |
|
871 |
|
872 /** |
|
873 * Show Show-All button |
|
874 * @property bShowAll |
|
875 * @type boolean |
|
876 * @default false |
|
877 */ |
|
878 bShowAll: false, |
|
879 |
|
880 /** |
|
881 * Show All button text |
|
882 * @property sShowAll |
|
883 * @type string |
|
884 * @default Restore original |
|
885 */ |
|
886 sShowAll: 'Show All', |
|
887 |
|
888 /** |
|
889 * Position of the collection menu when shown - align "left" or "right" |
|
890 * @property sAlign |
|
891 * @type string |
|
892 * @default left |
|
893 */ |
|
894 sAlign: 'left', |
|
895 |
|
896 /** |
|
897 * Callback function to tell the user when the state has changed |
|
898 * @property fnStateChange |
|
899 * @type function |
|
900 * @default null |
|
901 */ |
|
902 fnStateChange: null, |
|
903 |
|
904 /** |
|
905 * Overlay animation duration in mS |
|
906 * @property iOverlayFade |
|
907 * @type integer|false |
|
908 * @default 500 |
|
909 */ |
|
910 iOverlayFade: 500, |
|
911 |
|
912 /** |
|
913 * Label callback for column names. Takes three parameters: 1. the |
|
914 * column index, 2. the column title detected by DataTables and 3. the |
|
915 * TH node for the column |
|
916 * @property fnLabel |
|
917 * @type function |
|
918 * @default null |
|
919 */ |
|
920 fnLabel: null, |
|
921 |
|
922 /** |
|
923 * Indicate if the column list should be positioned by Javascript, |
|
924 * visually below the button or allow CSS to do the positioning |
|
925 * @property bCssPosition |
|
926 * @type boolean |
|
927 * @default false |
|
928 */ |
|
929 bCssPosition: false, |
|
930 |
|
931 /** |
|
932 * Group buttons |
|
933 * @property aoGroups |
|
934 * @type array |
|
935 * @default [] |
|
936 */ |
|
937 aoGroups: [], |
|
938 |
|
939 /** |
|
940 * Button ordering - 'alpha' (alphabetical) or 'column' (table column |
|
941 * order) |
|
942 * @property order |
|
943 * @type string |
|
944 * @default column |
|
945 */ |
|
946 order: 'column' |
|
947 }; |
|
948 |
|
949 |
|
950 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
951 * Static object properties |
|
952 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
953 |
|
954 /** |
|
955 * Collection of all ColVis instances |
|
956 * @property ColVis.aInstances |
|
957 * @static |
|
958 * @type Array |
|
959 * @default [] |
|
960 */ |
|
961 ColVis.aInstances = []; |
|
962 |
|
963 |
|
964 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
965 * Constants |
|
966 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
967 |
|
968 /** |
|
969 * Name of this class |
|
970 * @constant CLASS |
|
971 * @type String |
|
972 * @default ColVis |
|
973 */ |
|
974 ColVis.prototype.CLASS = "ColVis"; |
|
975 |
|
976 |
|
977 /** |
|
978 * ColVis version |
|
979 * @constant VERSION |
|
980 * @type String |
|
981 * @default See code |
|
982 */ |
|
983 ColVis.VERSION = "1.1.0"; |
|
984 ColVis.prototype.VERSION = ColVis.VERSION; |
|
985 |
|
986 |
|
987 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
988 * Initialisation |
|
989 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
990 |
|
991 /* |
|
992 * Register a new feature with DataTables |
|
993 */ |
|
994 if (typeof $.fn.dataTable == "function" && |
|
995 typeof $.fn.dataTableExt.fnVersionCheck == "function" && |
|
996 $.fn.dataTableExt.fnVersionCheck('1.7.0')) { |
|
997 $.fn.dataTableExt.aoFeatures.push({ |
|
998 "fnInit": function (oDTSettings) { |
|
999 var init = oDTSettings.oInit; |
|
1000 var colvis = new ColVis(oDTSettings, init.colVis || init.oColVis || {}); |
|
1001 return colvis.button(); |
|
1002 }, |
|
1003 "cFeature": "C", |
|
1004 "sFeature": "ColVis" |
|
1005 }); |
|
1006 } |
|
1007 else { |
|
1008 alert("Warning: ColVis requires DataTables 1.7 or greater - www.datatables.net/download"); |
|
1009 } |
|
1010 |
|
1011 |
|
1012 // Make ColVis accessible from the DataTables instance |
|
1013 $.fn.dataTable.ColVis = ColVis; |
|
1014 $.fn.DataTable.ColVis = ColVis; |
|
1015 |
|
1016 |
|
1017 return ColVis; |
|
1018 }; // /factory |
|
1019 |
|
1020 |
|
1021 factory(jQuery, jQuery.fn.dataTable); |
|
1022 |
|
1023 |
|
1024 })(window, document); |
|
1025 |