Blame | Letzte Änderung | Log anzeigen | RSS feed
/*! TableTools 2.2.3* 2009-2014 SpryMedia Ltd - datatables.net/license** ZeroClipboard 1.0.4* Author: Joseph Huckaby - MIT licensed*//*** @summary TableTools* @description Tools and buttons for DataTables* @version 2.2.3* @file dataTables.tableTools.js* @author SpryMedia Ltd (www.sprymedia.co.uk)* @contact www.sprymedia.co.uk/contact* @copyright Copyright 2009-2014 SpryMedia Ltd.** This source file is free software, available under the following license:* MIT license - http://datatables.net/license/mit** This source file is distributed in the hope that it will be useful, but* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.** For details please refer to: http://www.datatables.net*//* Global scope for TableTools for backwards compatibility.* Will be removed in 2.3*/var TableTools;(function(window, document, undefined) {var factory = function( $, DataTable ) {"use strict";//include ZeroClipboard.js/* ZeroClipboard 1.0.4* Author: Joseph Huckaby*/var ZeroClipboard_TableTools = {version: "1.0.4-TableTools2",clients: {}, // registered upload clients on page, indexed by idmoviePath: '', // URL to movienextId: 1, // ID of next movie$: function(thingy) {// simple DOM lookup utility functionif (typeof(thingy) == 'string') {thingy = document.getElementById(thingy);}if (!thingy.addClass) {// extend element with a few useful methodsthingy.hide = function() { this.style.display = 'none'; };thingy.show = function() { this.style.display = ''; };thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };thingy.removeClass = function(name) {this.className = this.className.replace( new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, '');};thingy.hasClass = function(name) {return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );};}return thingy;},setMoviePath: function(path) {// set path to ZeroClipboard.swfthis.moviePath = path;},dispatch: function(id, eventName, args) {// receive event from flash movie, send to clientvar client = this.clients[id];if (client) {client.receiveEvent(eventName, args);}},register: function(id, client) {// register new client to receive eventsthis.clients[id] = client;},getDOMObjectPosition: function(obj) {// get absolute coordinates for dom elementvar info = {left: 0,top: 0,width: obj.width ? obj.width : obj.offsetWidth,height: obj.height ? obj.height : obj.offsetHeight};if ( obj.style.width !== "" ) {info.width = obj.style.width.replace("px","");}if ( obj.style.height !== "" ) {info.height = obj.style.height.replace("px","");}while (obj) {info.left += obj.offsetLeft;info.top += obj.offsetTop;obj = obj.offsetParent;}return info;},Client: function(elem) {// constructor for new simple upload clientthis.handlers = {};// unique IDthis.id = ZeroClipboard_TableTools.nextId++;this.movieId = 'ZeroClipboard_TableToolsMovie_' + this.id;// register client with singleton to receive flash eventsZeroClipboard_TableTools.register(this.id, this);// create movieif (elem) {this.glue(elem);}}};ZeroClipboard_TableTools.Client.prototype = {id: 0, // unique ID for usready: false, // whether movie is ready to receive events or notmovie: null, // reference to movie objectclipText: '', // text to copy to clipboardfileName: '', // default file save nameaction: 'copy', // action to performhandCursorEnabled: true, // whether to show hand cursor, or default pointer cursorcssEffects: true, // enable CSS mouse effects on dom containerhandlers: null, // user event handlerssized: false,glue: function(elem, title) {// glue to DOM element// elem can be ID or actual DOM element objectthis.domElement = ZeroClipboard_TableTools.$(elem);// float just above object, or zIndex 99 if dom element isn't setvar zIndex = 99;if (this.domElement.style.zIndex) {zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;}// find X/Y position of domElementvar box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);// create floating DIV above elementthis.div = document.createElement('div');var style = this.div.style;style.position = 'absolute';style.left = '0px';style.top = '0px';style.width = (box.width) + 'px';style.height = box.height + 'px';style.zIndex = zIndex;if ( typeof title != "undefined" && title !== "" ) {this.div.title = title;}if ( box.width !== 0 && box.height !== 0 ) {this.sized = true;}// style.backgroundColor = '#f00'; // debugif ( this.domElement ) {this.domElement.appendChild(this.div);this.div.innerHTML = this.getHTML( box.width, box.height ).replace(/&/g, '&');}},positionElement: function() {var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);var style = this.div.style;style.position = 'absolute';//style.left = (this.domElement.offsetLeft)+'px';//style.top = this.domElement.offsetTop+'px';style.width = box.width + 'px';style.height = box.height + 'px';if ( box.width !== 0 && box.height !== 0 ) {this.sized = true;} else {return;}var flash = this.div.childNodes[0];flash.width = box.width;flash.height = box.height;},getHTML: function(width, height) {// return HTML for movievar html = '';var flashvars = 'id=' + this.id +'&width=' + width +'&height=' + height;if (navigator.userAgent.match(/MSIE/)) {// IE gets an OBJECT tagvar protocol = location.href.match(/^https/i) ? 'https://' : 'http://';html += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard_TableTools.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>';}else {// all other browsers get an EMBED taghtml += '<embed id="'+this.movieId+'" src="'+ZeroClipboard_TableTools.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />';}return html;},hide: function() {// temporarily hide floater offscreenif (this.div) {this.div.style.left = '-2000px';}},show: function() {// show ourselves after a call to hide()this.reposition();},destroy: function() {// destroy control and floaterif (this.domElement && this.div) {this.hide();this.div.innerHTML = '';var body = document.getElementsByTagName('body')[0];try { body.removeChild( this.div ); } catch(e) {}this.domElement = null;this.div = null;}},reposition: function(elem) {// reposition our floating div, optionally to new container// warning: container CANNOT change size, only positionif (elem) {this.domElement = ZeroClipboard_TableTools.$(elem);if (!this.domElement) {this.hide();}}if (this.domElement && this.div) {var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);var style = this.div.style;style.left = '' + box.left + 'px';style.top = '' + box.top + 'px';}},clearText: function() {// clear the text to be copy / savedthis.clipText = '';if (this.ready) {this.movie.clearText();}},appendText: function(newText) {// append text to that which is to be copied / savedthis.clipText += newText;if (this.ready) { this.movie.appendText(newText) ;}},setText: function(newText) {// set text to be copied to be copied / savedthis.clipText = newText;if (this.ready) { this.movie.setText(newText) ;}},setCharSet: function(charSet) {// set the character set (UTF16LE or UTF8)this.charSet = charSet;if (this.ready) { this.movie.setCharSet(charSet) ;}},setBomInc: function(bomInc) {// set if the BOM should be included or notthis.incBom = bomInc;if (this.ready) { this.movie.setBomInc(bomInc) ;}},setFileName: function(newText) {// set the file namethis.fileName = newText;if (this.ready) {this.movie.setFileName(newText);}},setAction: function(newText) {// set action (save or copy)this.action = newText;if (this.ready) {this.movie.setAction(newText);}},addEventListener: function(eventName, func) {// add user event listener for event// event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, canceleventName = eventName.toString().toLowerCase().replace(/^on/, '');if (!this.handlers[eventName]) {this.handlers[eventName] = [];}this.handlers[eventName].push(func);},setHandCursor: function(enabled) {// enable hand cursor (true), or default arrow cursor (false)this.handCursorEnabled = enabled;if (this.ready) {this.movie.setHandCursor(enabled);}},setCSSEffects: function(enabled) {// enable or disable CSS effects on DOM containerthis.cssEffects = !!enabled;},receiveEvent: function(eventName, args) {var self;// receive event from flasheventName = eventName.toString().toLowerCase().replace(/^on/, '');// special behavior for certain eventsswitch (eventName) {case 'load':// movie claims it is ready, but in IE this isn't always the case...// bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional functionthis.movie = document.getElementById(this.movieId);if (!this.movie) {self = this;setTimeout( function() { self.receiveEvent('load', null); }, 1 );return;}// firefox on pc needs a "kick" in order to set these in certain casesif (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {self = this;setTimeout( function() { self.receiveEvent('load', null); }, 100 );this.ready = true;return;}this.ready = true;this.movie.clearText();this.movie.appendText( this.clipText );this.movie.setFileName( this.fileName );this.movie.setAction( this.action );this.movie.setCharSet( this.charSet );this.movie.setBomInc( this.incBom );this.movie.setHandCursor( this.handCursorEnabled );break;case 'mouseover':if (this.domElement && this.cssEffects) {//this.domElement.addClass('hover');if (this.recoverActive) {this.domElement.addClass('active');}}break;case 'mouseout':if (this.domElement && this.cssEffects) {this.recoverActive = false;if (this.domElement.hasClass('active')) {this.domElement.removeClass('active');this.recoverActive = true;}//this.domElement.removeClass('hover');}break;case 'mousedown':if (this.domElement && this.cssEffects) {this.domElement.addClass('active');}break;case 'mouseup':if (this.domElement && this.cssEffects) {this.domElement.removeClass('active');this.recoverActive = false;}break;} // switch eventNameif (this.handlers[eventName]) {for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {var func = this.handlers[eventName][idx];if (typeof(func) == 'function') {// actual function referencefunc(this, args);}else if ((typeof(func) == 'object') && (func.length == 2)) {// PHP style object + method, i.e. [myObject, 'myMethod']func[0][ func[1] ](this, args);}else if (typeof(func) == 'string') {// name of functionwindow[func](this, args);}} // foreach event handler defined} // user defined handler for event}};// For the Flash binding to work, ZeroClipboard_TableTools must be on the global// object listwindow.ZeroClipboard_TableTools = ZeroClipboard_TableTools;//include TableTools.js/* TableTools* 2009-2014 SpryMedia Ltd - datatables.net/license*//*globals TableTools,ZeroClipboard_TableTools*/(function($, window, document) {/*** TableTools provides flexible buttons and other tools for a DataTables enhanced table* @class TableTools* @constructor* @param {Object} oDT DataTables instance. When using DataTables 1.10 this can* also be a jQuery collection, jQuery selector, table node, DataTables API* instance or DataTables settings object.* @param {Object} oOpts TableTools options* @param {String} oOpts.sSwfPath ZeroClipboard SWF path* @param {String} oOpts.sRowSelect Row selection options - 'none', 'single', 'multi' or 'os'* @param {Function} oOpts.fnPreRowSelect Callback function just prior to row selection* @param {Function} oOpts.fnRowSelected Callback function just after row selection* @param {Function} oOpts.fnRowDeselected Callback function when row is deselected* @param {Array} oOpts.aButtons List of buttons to be used*/TableTools = function( oDT, oOpts ){/* Santiy check that we are a new instance */if ( ! this instanceof TableTools ){alert( "Warning: TableTools must be initialised with the keyword 'new'" );}// In 1.10 we can use the API to get the settings object from a number of// sourcesvar dtSettings = $.fn.dataTable.Api ?new $.fn.dataTable.Api( oDT ).settings()[0] :oDT.fnSettings();/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Public class variables* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//*** @namespace Settings object which contains customisable information for TableTools instance*/this.s = {/*** Store 'this' so the instance can be retrieved from the settings object* @property that* @type object* @default this*/"that": this,/*** DataTables settings objects* @property dt* @type object* @default <i>From the oDT init option</i>*/"dt": dtSettings,/*** @namespace Print specific information*/"print": {/*** DataTables draw 'start' point before the printing display was shown* @property saveStart* @type int* @default -1*/"saveStart": -1,/*** DataTables draw 'length' point before the printing display was shown* @property saveLength* @type int* @default -1*/"saveLength": -1,/*** Page scrolling point before the printing display was shown so it can be restored* @property saveScroll* @type int* @default -1*/"saveScroll": -1,/*** Wrapped function to end the print display (to maintain scope)* @property funcEnd* @type Function* @default function () {}*/"funcEnd": function () {}},/*** A unique ID is assigned to each button in each instance* @property buttonCounter* @type int* @default 0*/"buttonCounter": 0,/*** @namespace Select rows specific information*/"select": {/*** Select type - can be 'none', 'single' or 'multi'* @property type* @type string* @default ""*/"type": "",/*** Array of nodes which are currently selected* @property selected* @type array* @default []*/"selected": [],/*** Function to run before the selection can take place. Will cancel the select if the* function returns false* @property preRowSelect* @type Function* @default null*/"preRowSelect": null,/*** Function to run when a row is selected* @property postSelected* @type Function* @default null*/"postSelected": null,/*** Function to run when a row is deselected* @property postDeselected* @type Function* @default null*/"postDeselected": null,/*** Indicate if all rows are selected (needed for server-side processing)* @property all* @type boolean* @default false*/"all": false,/*** Class name to add to selected TR nodes* @property selectedClass* @type String* @default ""*/"selectedClass": ""},/*** Store of the user input customisation object* @property custom* @type object* @default {}*/"custom": {},/*** SWF movie path* @property swfPath* @type string* @default ""*/"swfPath": "",/*** Default button set* @property buttonSet* @type array* @default []*/"buttonSet": [],/*** When there is more than one TableTools instance for a DataTable, there must be a* master which controls events (row selection etc)* @property master* @type boolean* @default false*/"master": false,/*** Tag names that are used for creating collections and buttons* @namesapce*/"tags": {}};/*** @namespace Common and useful DOM elements for the class instance*/this.dom = {/*** DIV element that is create and all TableTools buttons (and their children) put into* @property container* @type node* @default null*/"container": null,/*** The table node to which TableTools will be applied* @property table* @type node* @default null*/"table": null,/*** @namespace Nodes used for the print display*/"print": {/*** Nodes which have been removed from the display by setting them to display none* @property hidden* @type array* @default []*/"hidden": [],/*** The information display saying telling the user about the print display* @property message* @type node* @default null*/"message": null},/*** @namespace Nodes used for a collection display. This contains the currently used collection*/"collection": {/*** The div wrapper containing the buttons in the collection (i.e. the menu)* @property collection* @type node* @default null*/"collection": null,/*** Background display to provide focus and capture events* @property background* @type node* @default null*/"background": null}};/*** @namespace Name space for the classes that this TableTools instance will use* @extends TableTools.classes*/this.classes = $.extend( true, {}, TableTools.classes );if ( this.s.dt.bJUI ){$.extend( true, this.classes, TableTools.classes_themeroller );}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Public class methods* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//*** Retreieve the settings object from an instance* @method fnSettings* @returns {object} TableTools settings object*/this.fnSettings = function () {return this.s;};/* Constructor logic */if ( typeof oOpts == 'undefined' ){oOpts = {};}TableTools._aInstances.push( this );this._fnConstruct( oOpts );return this;};TableTools.prototype = {/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Public methods* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//*** Retreieve the settings object from an instance* @returns {array} List of TR nodes which are currently selected* @param {boolean} [filtered=false] Get only selected rows which are* available given the filtering applied to the table. By default* this is false - i.e. all rows, regardless of filtering areselected.*/"fnGetSelected": function ( filtered ){varout = [],data = this.s.dt.aoData,displayed = this.s.dt.aiDisplay,i, iLen;if ( filtered ){// Only consider filtered rowsfor ( i=0, iLen=displayed.length ; i<iLen ; i++ ){if ( data[ displayed[i] ]._DTTT_selected ){out.push( data[ displayed[i] ].nTr );}}}else{// Use all rowsfor ( i=0, iLen=data.length ; i<iLen ; i++ ){if ( data[i]._DTTT_selected ){out.push( data[i].nTr );}}}return out;},/*** Get the data source objects/arrays from DataTables for the selected rows (same as* fnGetSelected followed by fnGetData on each row from the table)* @returns {array} Data from the TR nodes which are currently selected*/"fnGetSelectedData": function (){var out = [];var data=this.s.dt.aoData;var i, iLen;for ( i=0, iLen=data.length ; i<iLen ; i++ ){if ( data[i]._DTTT_selected ){out.push( this.s.dt.oInstance.fnGetData(i) );}}return out;},/*** Get the indexes of the selected rows* @returns {array} List of row indexes* @param {boolean} [filtered=false] Get only selected rows which are* available given the filtering applied to the table. By default* this is false - i.e. all rows, regardless of filtering areselected.*/"fnGetSelectedIndexes": function ( filtered ){varout = [],data = this.s.dt.aoData,displayed = this.s.dt.aiDisplay,i, iLen;if ( filtered ){// Only consider filtered rowsfor ( i=0, iLen=displayed.length ; i<iLen ; i++ ){if ( data[ displayed[i] ]._DTTT_selected ){out.push( displayed[i] );}}}else{// Use all rowsfor ( i=0, iLen=data.length ; i<iLen ; i++ ){if ( data[i]._DTTT_selected ){out.push( i );}}}return out;},/*** Check to see if a current row is selected or not* @param {Node} n TR node to check if it is currently selected or not* @returns {Boolean} true if select, false otherwise*/"fnIsSelected": function ( n ){var pos = this.s.dt.oInstance.fnGetPosition( n );return (this.s.dt.aoData[pos]._DTTT_selected===true) ? true : false;},/*** Select all rows in the table* @param {boolean} [filtered=false] Select only rows which are available* given the filtering applied to the table. By default this is false -* i.e. all rows, regardless of filtering are selected.*/"fnSelectAll": function ( filtered ){this._fnRowSelect( filtered ?this.s.dt.aiDisplay :this.s.dt.aoData);},/*** Deselect all rows in the table* @param {boolean} [filtered=false] Deselect only rows which are available* given the filtering applied to the table. By default this is false -* i.e. all rows, regardless of filtering are deselected.*/"fnSelectNone": function ( filtered ){this._fnRowDeselect( this.fnGetSelectedIndexes(filtered) );},/*** Select row(s)* @param {node|object|array} n The row(s) to select. Can be a single DOM* TR node, an array of TR nodes or a jQuery object.*/"fnSelect": function ( n ){if ( this.s.select.type == "single" ){this.fnSelectNone();this._fnRowSelect( n );}else{this._fnRowSelect( n );}},/*** Deselect row(s)* @param {node|object|array} n The row(s) to deselect. Can be a single DOM* TR node, an array of TR nodes or a jQuery object.*/"fnDeselect": function ( n ){this._fnRowDeselect( n );},/*** Get the title of the document - useful for file names. The title is retrieved from either* the configuration object's 'title' parameter, or the HTML document title* @param {Object} oConfig Button configuration object* @returns {String} Button title*/"fnGetTitle": function( oConfig ){var sTitle = "";if ( typeof oConfig.sTitle != 'undefined' && oConfig.sTitle !== "" ) {sTitle = oConfig.sTitle;} else {var anTitle = document.getElementsByTagName('title');if ( anTitle.length > 0 ){sTitle = anTitle[0].innerHTML;}}/* Strip characters which the OS will object to - checking for UTF8 support in the scripting* engine*/if ( "\u00A1".toString().length < 4 ) {return sTitle.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");} else {return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g, "");}},/*** Calculate a unity array with the column width by proportion for a set of columns to be* included for a button. This is particularly useful for PDF creation, where we can use the* column widths calculated by the browser to size the columns in the PDF.* @param {Object} oConfig Button configuration object* @returns {Array} Unity array of column ratios*/"fnCalcColRatios": function ( oConfig ){varaoCols = this.s.dt.aoColumns,aColumnsInc = this._fnColumnTargets( oConfig.mColumns ),aColWidths = [],iWidth = 0, iTotal = 0, i, iLen;for ( i=0, iLen=aColumnsInc.length ; i<iLen ; i++ ){if ( aColumnsInc[i] ){iWidth = aoCols[i].nTh.offsetWidth;iTotal += iWidth;aColWidths.push( iWidth );}}for ( i=0, iLen=aColWidths.length ; i<iLen ; i++ ){aColWidths[i] = aColWidths[i] / iTotal;}return aColWidths.join('\t');},/*** Get the information contained in a table as a string* @param {Object} oConfig Button configuration object* @returns {String} Table data as a string*/"fnGetTableData": function ( oConfig ){/* In future this could be used to get data from a plain HTML source as well as DataTables */if ( this.s.dt ){return this._fnGetDataTablesData( oConfig );}},/*** Pass text to a flash button instance, which will be used on the button's click handler* @param {Object} clip Flash button object* @param {String} text Text to set*/"fnSetText": function ( clip, text ){this._fnFlashSetText( clip, text );},/*** Resize the flash elements of the buttons attached to this TableTools instance - this is* useful for when initialising TableTools when it is hidden (display:none) since sizes can't* be calculated at that time.*/"fnResizeButtons": function (){for ( var cli in ZeroClipboard_TableTools.clients ){if ( cli ){var client = ZeroClipboard_TableTools.clients[cli];if ( typeof client.domElement != 'undefined' &&client.domElement.parentNode ){client.positionElement();}}}},/*** Check to see if any of the ZeroClipboard client's attached need to be resized*/"fnResizeRequired": function (){for ( var cli in ZeroClipboard_TableTools.clients ){if ( cli ){var client = ZeroClipboard_TableTools.clients[cli];if ( typeof client.domElement != 'undefined' &&client.domElement.parentNode == this.dom.container &&client.sized === false ){return true;}}}return false;},/*** Programmatically enable or disable the print view* @param {boolean} [bView=true] Show the print view if true or not given. If false, then* terminate the print view and return to normal.* @param {object} [oConfig={}] Configuration for the print view* @param {boolean} [oConfig.bShowAll=false] Show all rows in the table if true* @param {string} [oConfig.sInfo] Information message, displayed as an overlay to the* user to let them know what the print view is.* @param {string} [oConfig.sMessage] HTML string to show at the top of the document - will* be included in the printed document.*/"fnPrint": function ( bView, oConfig ){if ( oConfig === undefined ){oConfig = {};}if ( bView === undefined || bView ){this._fnPrintStart( oConfig );}else{this._fnPrintEnd();}},/*** Show a message to the end user which is nicely styled* @param {string} message The HTML string to show to the user* @param {int} time The duration the message is to be shown on screen for (mS)*/"fnInfo": function ( message, time ) {var info = $('<div/>').addClass( this.classes.print.info ).html( message ).appendTo( 'body' );setTimeout( function() {info.fadeOut( "normal", function() {info.remove();} );}, time );},/*** Get the container element of the instance for attaching to the DOM* @returns {node} DOM node*/"fnContainer": function () {return this.dom.container;},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Private methods (they are of course public in JS, but recommended as private)* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//*** Constructor logic* @method _fnConstruct* @param {Object} oOpts Same as TableTools constructor* @returns void* @private*/"_fnConstruct": function ( oOpts ){var that = this;this._fnCustomiseSettings( oOpts );/* Container element */this.dom.container = document.createElement( this.s.tags.container );this.dom.container.className = this.classes.container;/* Row selection config */if ( this.s.select.type != 'none' ){this._fnRowSelectConfig();}/* Buttons */this._fnButtonDefinations( this.s.buttonSet, this.dom.container );/* Destructor */this.s.dt.aoDestroyCallback.push( {"sName": "TableTools","fn": function () {$(that.s.dt.nTBody).off( 'click.DTTT_Select', 'tr' );$(that.dom.container).empty();// Remove the instancevar idx = $.inArray( that, TableTools._aInstances );if ( idx !== -1 ) {TableTools._aInstances.splice( idx, 1 );}}} );},/*** Take the user defined settings and the default settings and combine them.* @method _fnCustomiseSettings* @param {Object} oOpts Same as TableTools constructor* @returns void* @private*/"_fnCustomiseSettings": function ( oOpts ){/* Is this the master control instance or not? */if ( typeof this.s.dt._TableToolsInit == 'undefined' ){this.s.master = true;this.s.dt._TableToolsInit = true;}/* We can use the table node from comparisons to group controls */this.dom.table = this.s.dt.nTable;/* Clone the defaults and then the user options */this.s.custom = $.extend( {}, TableTools.DEFAULTS, oOpts );/* Flash file location */this.s.swfPath = this.s.custom.sSwfPath;if ( typeof ZeroClipboard_TableTools != 'undefined' ){ZeroClipboard_TableTools.moviePath = this.s.swfPath;}/* Table row selecting */this.s.select.type = this.s.custom.sRowSelect;this.s.select.preRowSelect = this.s.custom.fnPreRowSelect;this.s.select.postSelected = this.s.custom.fnRowSelected;this.s.select.postDeselected = this.s.custom.fnRowDeselected;// Backwards compatibility - allow the user to specify a custom class in the initialiserif ( this.s.custom.sSelectedClass ){this.classes.select.row = this.s.custom.sSelectedClass;}this.s.tags = this.s.custom.oTags;/* Button set */this.s.buttonSet = this.s.custom.aButtons;},/*** Take the user input arrays and expand them to be fully defined, and then add them to a given* DOM element* @method _fnButtonDefinations* @param {array} buttonSet Set of user defined buttons* @param {node} wrapper Node to add the created buttons to* @returns void* @private*/"_fnButtonDefinations": function ( buttonSet, wrapper ){var buttonDef;for ( var i=0, iLen=buttonSet.length ; i<iLen ; i++ ){if ( typeof buttonSet[i] == "string" ){if ( typeof TableTools.BUTTONS[ buttonSet[i] ] == 'undefined' ){alert( "TableTools: Warning - unknown button type: "+buttonSet[i] );continue;}buttonDef = $.extend( {}, TableTools.BUTTONS[ buttonSet[i] ], true );}else{if ( typeof TableTools.BUTTONS[ buttonSet[i].sExtends ] == 'undefined' ){alert( "TableTools: Warning - unknown button type: "+buttonSet[i].sExtends );continue;}var o = $.extend( {}, TableTools.BUTTONS[ buttonSet[i].sExtends ], true );buttonDef = $.extend( o, buttonSet[i], true );}var button = this._fnCreateButton(buttonDef,$(wrapper).hasClass(this.classes.collection.container));if ( button ) {wrapper.appendChild( button );}}},/*** Create and configure a TableTools button* @method _fnCreateButton* @param {Object} oConfig Button configuration object* @returns {Node} Button element* @private*/"_fnCreateButton": function ( oConfig, bCollectionButton ){var nButton = this._fnButtonBase( oConfig, bCollectionButton );if ( oConfig.sAction.match(/flash/) ){if ( ! this._fnHasFlash() ) {return false;}this._fnFlashConfig( nButton, oConfig );}else if ( oConfig.sAction == "text" ){this._fnTextConfig( nButton, oConfig );}else if ( oConfig.sAction == "div" ){this._fnTextConfig( nButton, oConfig );}else if ( oConfig.sAction == "collection" ){this._fnTextConfig( nButton, oConfig );this._fnCollectionConfig( nButton, oConfig );}if ( this.s.dt.iTabIndex !== -1 ) {$(nButton).attr( 'tabindex', this.s.dt.iTabIndex ).attr( 'aria-controls', this.s.dt.sTableId ).on( 'keyup.DTTT', function (e) {// Trigger the click event on return key when focused.// Note that for Flash buttons this has no effect since we// can't programmatically trigger the Flash exportif ( e.keyCode === 13 ) {e.stopPropagation();$(this).trigger( 'click' );}} ).on( 'mousedown.DTTT', function (e) {// On mousedown we want to stop the focus occurring on the// button, focus is used only for the keyboard navigation.// But using preventDefault for the flash buttons stops the// flash action. However, it is not the button that gets// focused but the flash element for flash buttons, so this// worksif ( ! oConfig.sAction.match(/flash/) ) {e.preventDefault();}} );}return nButton;},/*** Create the DOM needed for the button and apply some base properties. All buttons start here* @method _fnButtonBase* @param {o} oConfig Button configuration object* @returns {Node} DIV element for the button* @private*/"_fnButtonBase": function ( o, bCollectionButton ){var sTag, sLiner, sClass;if ( bCollectionButton ){sTag = o.sTag && o.sTag !== "default" ? o.sTag : this.s.tags.collection.button;sLiner = o.sLinerTag && o.sLinerTag !== "default" ? o.sLiner : this.s.tags.collection.liner;sClass = this.classes.collection.buttons.normal;}else{sTag = o.sTag && o.sTag !== "default" ? o.sTag : this.s.tags.button;sLiner = o.sLinerTag && o.sLinerTag !== "default" ? o.sLiner : this.s.tags.liner;sClass = this.classes.buttons.normal;}varnButton = document.createElement( sTag ),nSpan = document.createElement( sLiner ),masterS = this._fnGetMasterSettings();nButton.className = sClass+" "+o.sButtonClass;nButton.setAttribute('id', "ToolTables_"+this.s.dt.sInstance+"_"+masterS.buttonCounter );nButton.appendChild( nSpan );nSpan.innerHTML = o.sButtonText;masterS.buttonCounter++;return nButton;},/*** Get the settings object for the master instance. When more than one TableTools instance is* assigned to a DataTable, only one of them can be the 'master' (for the select rows). As such,* we will typically want to interact with that master for global properties.* @method _fnGetMasterSettings* @returns {Object} TableTools settings object* @private*/"_fnGetMasterSettings": function (){if ( this.s.master ){return this.s;}else{/* Look for the master which has the same DT as this one */var instances = TableTools._aInstances;for ( var i=0, iLen=instances.length ; i<iLen ; i++ ){if ( this.dom.table == instances[i].s.dt.nTable ){return instances[i].s;}}}},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Button collection functions*//*** Create a collection button, when activated will present a drop down list of other buttons* @param {Node} nButton Button to use for the collection activation* @param {Object} oConfig Button configuration object* @returns void* @private*/"_fnCollectionConfig": function ( nButton, oConfig ){var nHidden = document.createElement( this.s.tags.collection.container );nHidden.style.display = "none";nHidden.className = this.classes.collection.container;oConfig._collection = nHidden;document.body.appendChild( nHidden );this._fnButtonDefinations( oConfig.aButtons, nHidden );},/*** Show a button collection* @param {Node} nButton Button to use for the collection* @param {Object} oConfig Button configuration object* @returns void* @private*/"_fnCollectionShow": function ( nButton, oConfig ){varthat = this,oPos = $(nButton).offset(),nHidden = oConfig._collection,iDivX = oPos.left,iDivY = oPos.top + $(nButton).outerHeight(),iWinHeight = $(window).height(), iDocHeight = $(document).height(),iWinWidth = $(window).width(), iDocWidth = $(document).width();nHidden.style.position = "absolute";nHidden.style.left = iDivX+"px";nHidden.style.top = iDivY+"px";nHidden.style.display = "block";$(nHidden).css('opacity',0);var nBackground = document.createElement('div');nBackground.style.position = "absolute";nBackground.style.left = "0px";nBackground.style.top = "0px";nBackground.style.height = ((iWinHeight>iDocHeight)? iWinHeight : iDocHeight) +"px";nBackground.style.width = ((iWinWidth>iDocWidth)? iWinWidth : iDocWidth) +"px";nBackground.className = this.classes.collection.background;$(nBackground).css('opacity',0);document.body.appendChild( nBackground );document.body.appendChild( nHidden );/* Visual corrections to try and keep the collection visible */var iDivWidth = $(nHidden).outerWidth();var iDivHeight = $(nHidden).outerHeight();if ( iDivX + iDivWidth > iDocWidth ){nHidden.style.left = (iDocWidth-iDivWidth)+"px";}if ( iDivY + iDivHeight > iDocHeight ){nHidden.style.top = (iDivY-iDivHeight-$(nButton).outerHeight())+"px";}this.dom.collection.collection = nHidden;this.dom.collection.background = nBackground;/* This results in a very small delay for the end user but it allows the animation to be* much smoother. If you don't want the animation, then the setTimeout can be removed*/setTimeout( function () {$(nHidden).animate({"opacity": 1}, 500);$(nBackground).animate({"opacity": 0.25}, 500);}, 10 );/* Resize the buttons to the Flash contents fit */this.fnResizeButtons();/* Event handler to remove the collection display */$(nBackground).click( function () {that._fnCollectionHide.call( that, null, null );} );},/*** Hide a button collection* @param {Node} nButton Button to use for the collection* @param {Object} oConfig Button configuration object* @returns void* @private*/"_fnCollectionHide": function ( nButton, oConfig ){if ( oConfig !== null && oConfig.sExtends == 'collection' ){return;}if ( this.dom.collection.collection !== null ){$(this.dom.collection.collection).animate({"opacity": 0}, 500, function (e) {this.style.display = "none";} );$(this.dom.collection.background).animate({"opacity": 0}, 500, function (e) {this.parentNode.removeChild( this );} );this.dom.collection.collection = null;this.dom.collection.background = null;}},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Row selection functions*//*** Add event handlers to a table to allow for row selection* @method _fnRowSelectConfig* @returns void* @private*/"_fnRowSelectConfig": function (){if ( this.s.master ){varthat = this,i, iLen,dt = this.s.dt,aoOpenRows = this.s.dt.aoOpenRows;$(dt.nTable).addClass( this.classes.select.table );// When using OS style selection, we want to cancel the shift text// selection, but only when the shift key is used (so you can// actually still select text in the table)if ( this.s.select.type === 'os' ) {$(dt.nTBody).on( 'mousedown.DTTT_Select', 'tr', function(e) {if ( e.shiftKey ) {$(dt.nTBody).css( '-moz-user-select', 'none' ).one('selectstart.DTTT_Select', 'tr', function () {return false;} );}} );$(dt.nTBody).on( 'mouseup.DTTT_Select', 'tr', function(e) {$(dt.nTBody).css( '-moz-user-select', '' );} );}// Row selection$(dt.nTBody).on( 'click.DTTT_Select', this.s.custom.sRowSelector, function(e) {var row = this.nodeName.toLowerCase() === 'tr' ?this :$(this).parents('tr')[0];var select = that.s.select;var pos = that.s.dt.oInstance.fnGetPosition( row );/* Sub-table must be ignored (odd that the selector won't do this with >) */if ( row.parentNode != dt.nTBody ) {return;}/* Check that we are actually working with a DataTables controlled row */if ( dt.oInstance.fnGetData(row) === null ) {return;}// Shift click, ctrl click and simple click handling to make// row selection a lot like a file system in desktop OSsif ( select.type == 'os' ) {if ( e.ctrlKey || e.metaKey ) {// Add or remove from the selectionif ( that.fnIsSelected( row ) ) {that._fnRowDeselect( row, e );}else {that._fnRowSelect( row, e );}}else if ( e.shiftKey ) {// Add a range of rows, from the last selected row to// this onevar rowIdxs = that.s.dt.aiDisplay.slice(); // visible rowsvar idx1 = $.inArray( select.lastRow, rowIdxs );var idx2 = $.inArray( pos, rowIdxs );if ( that.fnGetSelected().length === 0 || idx1 === -1 ) {// select from top to here - slightly odd, but both// Windows and Mac OS do thisrowIdxs.splice( $.inArray( pos, rowIdxs )+1, rowIdxs.length );}else {// reverse so we can shift click 'up' as well as downif ( idx1 > idx2 ) {var tmp = idx2;idx2 = idx1;idx1 = tmp;}rowIdxs.splice( idx2+1, rowIdxs.length );rowIdxs.splice( 0, idx1 );}if ( ! that.fnIsSelected( row ) ) {// Select rangethat._fnRowSelect( rowIdxs, e );}else {// Deselect range - need to keep the clicked on row selectedrowIdxs.splice( $.inArray( pos, rowIdxs ), 1 );that._fnRowDeselect( rowIdxs, e );}}else {// No cmd or shift click. Deselect current if selected,// or select this row onlyif ( that.fnIsSelected( row ) && that.fnGetSelected().length === 1 ) {that._fnRowDeselect( row, e );}else {that.fnSelectNone();that._fnRowSelect( row, e );}}}else if ( that.fnIsSelected( row ) ) {that._fnRowDeselect( row, e );}else if ( select.type == "single" ) {that.fnSelectNone();that._fnRowSelect( row, e );}else if ( select.type == "multi" ) {that._fnRowSelect( row, e );}select.lastRow = pos;} );//.on('selectstart', function () { return false; } );// Bind a listener to the DataTable for when new rows are created.// This allows rows to be visually selected when they should be and// deferred rendering is used.dt.oApi._fnCallbackReg( dt, 'aoRowCreatedCallback', function (tr, data, index) {if ( dt.aoData[index]._DTTT_selected ) {$(tr).addClass( that.classes.select.row );}}, 'TableTools-SelectAll' );}},/*** Select rows* @param {*} src Rows to select - see _fnSelectData for a description of valid inputs* @private*/"_fnRowSelect": function ( src, e ){varthat = this,data = this._fnSelectData( src ),firstTr = data.length===0 ? null : data[0].nTr,anSelected = [],i, len;// Get all the rows that will be selectedfor ( i=0, len=data.length ; i<len ; i++ ){if ( data[i].nTr ){anSelected.push( data[i].nTr );}}// User defined pre-selection functionif ( this.s.select.preRowSelect !== null && !this.s.select.preRowSelect.call(this, e, anSelected, true) ){return;}// Mark them as selectedfor ( i=0, len=data.length ; i<len ; i++ ){data[i]._DTTT_selected = true;if ( data[i].nTr ){$(data[i].nTr).addClass( that.classes.select.row );}}// Post-selection functionif ( this.s.select.postSelected !== null ){this.s.select.postSelected.call( this, anSelected );}TableTools._fnEventDispatch( this, 'select', anSelected, true );},/*** Deselect rows* @param {*} src Rows to deselect - see _fnSelectData for a description of valid inputs* @private*/"_fnRowDeselect": function ( src, e ){varthat = this,data = this._fnSelectData( src ),firstTr = data.length===0 ? null : data[0].nTr,anDeselectedTrs = [],i, len;// Get all the rows that will be deselectedfor ( i=0, len=data.length ; i<len ; i++ ){if ( data[i].nTr ){anDeselectedTrs.push( data[i].nTr );}}// User defined pre-selection functionif ( this.s.select.preRowSelect !== null && !this.s.select.preRowSelect.call(this, e, anDeselectedTrs, false) ){return;}// Mark them as deselectedfor ( i=0, len=data.length ; i<len ; i++ ){data[i]._DTTT_selected = false;if ( data[i].nTr ){$(data[i].nTr).removeClass( that.classes.select.row );}}// Post-deselection functionif ( this.s.select.postDeselected !== null ){this.s.select.postDeselected.call( this, anDeselectedTrs );}TableTools._fnEventDispatch( this, 'select', anDeselectedTrs, false );},/*** Take a data source for row selection and convert it into aoData points for the DT* @param {*} src Can be a single DOM TR node, an array of TR nodes (including a* a jQuery object), a single aoData point from DataTables, an array of aoData* points or an array of aoData indexes* @returns {array} An array of aoData points*/"_fnSelectData": function ( src ){var out = [], pos, i, iLen;if ( src.nodeName ){// Single nodepos = this.s.dt.oInstance.fnGetPosition( src );out.push( this.s.dt.aoData[pos] );}else if ( typeof src.length !== 'undefined' ){// jQuery object or an array of nodes, or aoData pointsfor ( i=0, iLen=src.length ; i<iLen ; i++ ){if ( src[i].nodeName ){pos = this.s.dt.oInstance.fnGetPosition( src[i] );out.push( this.s.dt.aoData[pos] );}else if ( typeof src[i] === 'number' ){out.push( this.s.dt.aoData[ src[i] ] );}else{out.push( src[i] );}}return out;}else{// A single aoData pointout.push( src );}return out;},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Text button functions*//*** Configure a text based button for interaction events* @method _fnTextConfig* @param {Node} nButton Button element which is being considered* @param {Object} oConfig Button configuration object* @returns void* @private*/"_fnTextConfig": function ( nButton, oConfig ){var that = this;if ( oConfig.fnInit !== null ){oConfig.fnInit.call( this, nButton, oConfig );}if ( oConfig.sToolTip !== "" ){nButton.title = oConfig.sToolTip;}$(nButton).hover( function () {if ( oConfig.fnMouseover !== null ){oConfig.fnMouseover.call( this, nButton, oConfig, null );}}, function () {if ( oConfig.fnMouseout !== null ){oConfig.fnMouseout.call( this, nButton, oConfig, null );}} );if ( oConfig.fnSelect !== null ){TableTools._fnEventListen( this, 'select', function (n) {oConfig.fnSelect.call( that, nButton, oConfig, n );} );}$(nButton).click( function (e) {//e.preventDefault();if ( oConfig.fnClick !== null ){oConfig.fnClick.call( that, nButton, oConfig, null, e );}/* Provide a complete function to match the behaviour of the flash elements */if ( oConfig.fnComplete !== null ){oConfig.fnComplete.call( that, nButton, oConfig, null, null );}that._fnCollectionHide( nButton, oConfig );} );},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Flash button functions*//*** Check if the Flash plug-in is available* @method _fnHasFlash* @returns {boolean} `true` if Flash available, `false` otherwise* @private*/"_fnHasFlash": function (){try {var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');if (fo) {return true;}}catch (e) {if (navigator.mimeTypes &&navigator.mimeTypes['application/x-shockwave-flash'] !== undefined &&navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {return true;}}return false;},/*** Configure a flash based button for interaction events* @method _fnFlashConfig* @param {Node} nButton Button element which is being considered* @param {o} oConfig Button configuration object* @returns void* @private*/"_fnFlashConfig": function ( nButton, oConfig ){var that = this;var flash = new ZeroClipboard_TableTools.Client();if ( oConfig.fnInit !== null ){oConfig.fnInit.call( this, nButton, oConfig );}flash.setHandCursor( true );if ( oConfig.sAction == "flash_save" ){flash.setAction( 'save' );flash.setCharSet( (oConfig.sCharSet=="utf16le") ? 'UTF16LE' : 'UTF8' );flash.setBomInc( oConfig.bBomInc );flash.setFileName( oConfig.sFileName.replace('*', this.fnGetTitle(oConfig)) );}else if ( oConfig.sAction == "flash_pdf" ){flash.setAction( 'pdf' );flash.setFileName( oConfig.sFileName.replace('*', this.fnGetTitle(oConfig)) );}else{flash.setAction( 'copy' );}flash.addEventListener('mouseOver', function(client) {if ( oConfig.fnMouseover !== null ){oConfig.fnMouseover.call( that, nButton, oConfig, flash );}} );flash.addEventListener('mouseOut', function(client) {if ( oConfig.fnMouseout !== null ){oConfig.fnMouseout.call( that, nButton, oConfig, flash );}} );flash.addEventListener('mouseDown', function(client) {if ( oConfig.fnClick !== null ){oConfig.fnClick.call( that, nButton, oConfig, flash );}} );flash.addEventListener('complete', function (client, text) {if ( oConfig.fnComplete !== null ){oConfig.fnComplete.call( that, nButton, oConfig, flash, text );}that._fnCollectionHide( nButton, oConfig );} );this._fnFlashGlue( flash, nButton, oConfig.sToolTip );},/*** Wait until the id is in the DOM before we "glue" the swf. Note that this function will call* itself (using setTimeout) until it completes successfully* @method _fnFlashGlue* @param {Object} clip Zero clipboard object* @param {Node} node node to glue swf to* @param {String} text title of the flash movie* @returns void* @private*/"_fnFlashGlue": function ( flash, node, text ){var that = this;var id = node.getAttribute('id');if ( document.getElementById(id) ){flash.glue( node, text );}else{setTimeout( function () {that._fnFlashGlue( flash, node, text );}, 100 );}},/*** Set the text for the flash clip to deal with** This function is required for large information sets. There is a limit on the* amount of data that can be transferred between Javascript and Flash in a single call, so* we use this method to build up the text in Flash by sending over chunks. It is estimated* that the data limit is around 64k, although it is undocumented, and appears to be different* between different flash versions. We chunk at 8KiB.* @method _fnFlashSetText* @param {Object} clip the ZeroClipboard object* @param {String} sData the data to be set* @returns void* @private*/"_fnFlashSetText": function ( clip, sData ){var asData = this._fnChunkData( sData, 8192 );clip.clearText();for ( var i=0, iLen=asData.length ; i<iLen ; i++ ){clip.appendText( asData[i] );}},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Data retrieval functions*//*** Convert the mixed columns variable into a boolean array the same size as the columns, which* indicates which columns we want to include* @method _fnColumnTargets* @param {String|Array} mColumns The columns to be included in data retrieval. If a string* then it can take the value of "visible" or "hidden" (to include all visible or* hidden columns respectively). Or an array of column indexes* @returns {Array} A boolean array the length of the columns of the table, which each value* indicating if the column is to be included or not* @private*/"_fnColumnTargets": function ( mColumns ){var aColumns = [];var dt = this.s.dt;var i, iLen;var columns = dt.aoColumns;var columnCount = columns.length;if ( typeof mColumns == "function" ){var a = mColumns.call( this, dt );for ( i=0, iLen=columnCount ; i<iLen ; i++ ){aColumns.push( $.inArray( i, a ) !== -1 ? true : false );}}else if ( typeof mColumns == "object" ){for ( i=0, iLen=columnCount ; i<iLen ; i++ ){aColumns.push( false );}for ( i=0, iLen=mColumns.length ; i<iLen ; i++ ){aColumns[ mColumns[i] ] = true;}}else if ( mColumns == "visible" ){for ( i=0, iLen=columnCount ; i<iLen ; i++ ){aColumns.push( columns[i].bVisible ? true : false );}}else if ( mColumns == "hidden" ){for ( i=0, iLen=columnCount ; i<iLen ; i++ ){aColumns.push( columns[i].bVisible ? false : true );}}else if ( mColumns == "sortable" ){for ( i=0, iLen=columnCount ; i<iLen ; i++ ){aColumns.push( columns[i].bSortable ? true : false );}}else /* all */{for ( i=0, iLen=columnCount ; i<iLen ; i++ ){aColumns.push( true );}}return aColumns;},/*** New line character(s) depend on the platforms* @method method* @param {Object} oConfig Button configuration object - only interested in oConfig.sNewLine* @returns {String} Newline character*/"_fnNewline": function ( oConfig ){if ( oConfig.sNewLine == "auto" ){return navigator.userAgent.match(/Windows/) ? "\r\n" : "\n";}else{return oConfig.sNewLine;}},/*** Get data from DataTables' internals and format it for output* @method _fnGetDataTablesData* @param {Object} oConfig Button configuration object* @param {String} oConfig.sFieldBoundary Field boundary for the data cells in the string* @param {String} oConfig.sFieldSeperator Field separator for the data cells* @param {String} oConfig.sNewline New line options* @param {Mixed} oConfig.mColumns Which columns should be included in the output* @param {Boolean} oConfig.bHeader Include the header* @param {Boolean} oConfig.bFooter Include the footer* @param {Boolean} oConfig.bSelectedOnly Include only the selected rows in the output* @returns {String} Concatenated string of data* @private*/"_fnGetDataTablesData": function ( oConfig ){var i, iLen, j, jLen;var aRow, aData=[], sLoopData='', arr;var dt = this.s.dt, tr, child;var regex = new RegExp(oConfig.sFieldBoundary, "g"); /* Do it here for speed */var aColumnsInc = this._fnColumnTargets( oConfig.mColumns );var bSelectedOnly = (typeof oConfig.bSelectedOnly != 'undefined') ? oConfig.bSelectedOnly : false;/** Header*/if ( oConfig.bHeader ){aRow = [];for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ ){if ( aColumnsInc[i] ){sLoopData = dt.aoColumns[i].sTitle.replace(/\n/g," ").replace( /<.*?>/g, "" ).replace(/^\s+|\s+$/g,"");sLoopData = this._fnHtmlDecode( sLoopData );aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );}}aData.push( aRow.join(oConfig.sFieldSeperator) );}bSelectedOnly = true;/** Body*/var aDataIndex;var aSelected = this.fnGetSelectedIndexes();bSelectedOnly = this.s.select.type !== "none" && bSelectedOnly && aSelected.length !== 0;if ( bSelectedOnly ) {// Use the selected indexesaDataIndex = aSelected;}else if ( DataTable.Api ) {// 1.10+ styleaDataIndex = new DataTable.Api( dt ).rows( oConfig.oSelectorOpts ).indexes().flatten().toArray();}else {// 1.9- styleaDataIndex = dt.oInstance.$('tr', oConfig.oSelectorOpts).map( function (id, row) {return dt.oInstance.fnGetPosition( row );} ).get();}for ( j=0, jLen=aDataIndex.length ; j<jLen ; j++ ){tr = dt.aoData[ aDataIndex[j] ].nTr;aRow = [];/* Columns */for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ ){if ( aColumnsInc[i] ){/* Convert to strings (with small optimisation) */var mTypeData = dt.oApi._fnGetCellData( dt, aDataIndex[j], i, 'display' );if ( oConfig.fnCellRender ){sLoopData = oConfig.fnCellRender( mTypeData, i, tr, aDataIndex[j] )+"";}else if ( typeof mTypeData == "string" ){/* Strip newlines, replace img tags with alt attr. and finally strip html... */sLoopData = mTypeData.replace(/\n/g," ");sLoopData =sLoopData.replace(/<img.*?\s+alt\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+)).*?>/gi,'$1$2$3');sLoopData = sLoopData.replace( /<.*?>/g, "" );}else{sLoopData = mTypeData+"";}/* Trim and clean the data */sLoopData = sLoopData.replace(/^\s+/, '').replace(/\s+$/, '');sLoopData = this._fnHtmlDecode( sLoopData );/* Bound it and add it to the total data */aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );}}aData.push( aRow.join(oConfig.sFieldSeperator) );/* Details rows from fnOpen */if ( oConfig.bOpenRows ){arr = $.grep(dt.aoOpenRows, function(o) { return o.nParent === tr; });if ( arr.length === 1 ){sLoopData = this._fnBoundData( $('td', arr[0].nTr).html(), oConfig.sFieldBoundary, regex );aData.push( sLoopData );}}}/** Footer*/if ( oConfig.bFooter && dt.nTFoot !== null ){aRow = [];for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ ){if ( aColumnsInc[i] && dt.aoColumns[i].nTf !== null ){sLoopData = dt.aoColumns[i].nTf.innerHTML.replace(/\n/g," ").replace( /<.*?>/g, "" );sLoopData = this._fnHtmlDecode( sLoopData );aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );}}aData.push( aRow.join(oConfig.sFieldSeperator) );}var _sLastData = aData.join( this._fnNewline(oConfig) );return _sLastData;},/*** Wrap data up with a boundary string* @method _fnBoundData* @param {String} sData data to bound* @param {String} sBoundary bounding char(s)* @param {RegExp} regex search for the bounding chars - constructed outside for efficiency* in the loop* @returns {String} bound data* @private*/"_fnBoundData": function ( sData, sBoundary, regex ){if ( sBoundary === "" ){return sData;}else{return sBoundary + sData.replace(regex, sBoundary+sBoundary) + sBoundary;}},/*** Break a string up into an array of smaller strings* @method _fnChunkData* @param {String} sData data to be broken up* @param {Int} iSize chunk size* @returns {Array} String array of broken up text* @private*/"_fnChunkData": function ( sData, iSize ){var asReturn = [];var iStrlen = sData.length;for ( var i=0 ; i<iStrlen ; i+=iSize ){if ( i+iSize < iStrlen ){asReturn.push( sData.substring( i, i+iSize ) );}else{asReturn.push( sData.substring( i, iStrlen ) );}}return asReturn;},/*** Decode HTML entities* @method _fnHtmlDecode* @param {String} sData encoded string* @returns {String} decoded string* @private*/"_fnHtmlDecode": function ( sData ){if ( sData.indexOf('&') === -1 ){return sData;}var n = document.createElement('div');return sData.replace( /&([^\s]*?);/g, function( match, match2 ) {if ( match.substr(1, 1) === '#' ){return String.fromCharCode( Number(match2.substr(1)) );}else{n.innerHTML = match;return n.childNodes[0].nodeValue;}} );},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Printing functions*//*** Show print display* @method _fnPrintStart* @param {Event} e Event object* @param {Object} oConfig Button configuration object* @returns void* @private*/"_fnPrintStart": function ( oConfig ){var that = this;var oSetDT = this.s.dt;/* Parse through the DOM hiding everything that isn't needed for the table */this._fnPrintHideNodes( oSetDT.nTable );/* Show the whole table */this.s.print.saveStart = oSetDT._iDisplayStart;this.s.print.saveLength = oSetDT._iDisplayLength;if ( oConfig.bShowAll ){oSetDT._iDisplayStart = 0;oSetDT._iDisplayLength = -1;if ( oSetDT.oApi._fnCalculateEnd ) {oSetDT.oApi._fnCalculateEnd( oSetDT );}oSetDT.oApi._fnDraw( oSetDT );}/* Adjust the display for scrolling which might be done by DataTables */if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" ){this._fnPrintScrollStart( oSetDT );// If the table redraws while in print view, the DataTables scrolling// setup would hide the header, so we need to readd it on draw$(this.s.dt.nTable).bind('draw.DTTT_Print', function () {that._fnPrintScrollStart( oSetDT );} );}/* Remove the other DataTables feature nodes - but leave the table! and info div */var anFeature = oSetDT.aanFeatures;for ( var cFeature in anFeature ){if ( cFeature != 'i' && cFeature != 't' && cFeature.length == 1 ){for ( var i=0, iLen=anFeature[cFeature].length ; i<iLen ; i++ ){this.dom.print.hidden.push( {"node": anFeature[cFeature][i],"display": "block"} );anFeature[cFeature][i].style.display = "none";}}}/* Print class can be used for styling */$(document.body).addClass( this.classes.print.body );/* Show information message to let the user know what is happening */if ( oConfig.sInfo !== "" ){this.fnInfo( oConfig.sInfo, 3000 );}/* Add a message at the top of the page */if ( oConfig.sMessage ){$('<div/>').addClass( this.classes.print.message ).html( oConfig.sMessage ).prependTo( 'body' );}/* Cache the scrolling and the jump to the top of the page */this.s.print.saveScroll = $(window).scrollTop();window.scrollTo( 0, 0 );/* Bind a key event listener to the document for the escape key -* it is removed in the callback*/$(document).bind( "keydown.DTTT", function(e) {/* Only interested in the escape key */if ( e.keyCode == 27 ){e.preventDefault();that._fnPrintEnd.call( that, e );}} );},/*** Printing is finished, resume normal display* @method _fnPrintEnd* @param {Event} e Event object* @returns void* @private*/"_fnPrintEnd": function ( e ){var that = this;var oSetDT = this.s.dt;var oSetPrint = this.s.print;var oDomPrint = this.dom.print;/* Show all hidden nodes */this._fnPrintShowNodes();/* Restore DataTables' scrolling */if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" ){$(this.s.dt.nTable).unbind('draw.DTTT_Print');this._fnPrintScrollEnd();}/* Restore the scroll */window.scrollTo( 0, oSetPrint.saveScroll );/* Drop the print message */$('div.'+this.classes.print.message).remove();/* Styling class */$(document.body).removeClass( 'DTTT_Print' );/* Restore the table length */oSetDT._iDisplayStart = oSetPrint.saveStart;oSetDT._iDisplayLength = oSetPrint.saveLength;if ( oSetDT.oApi._fnCalculateEnd ) {oSetDT.oApi._fnCalculateEnd( oSetDT );}oSetDT.oApi._fnDraw( oSetDT );$(document).unbind( "keydown.DTTT" );},/*** Take account of scrolling in DataTables by showing the full table* @returns void* @private*/"_fnPrintScrollStart": function (){varoSetDT = this.s.dt,nScrollHeadInner = oSetDT.nScrollHead.getElementsByTagName('div')[0],nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],nScrollBody = oSetDT.nTable.parentNode,nTheadSize, nTfootSize;/* Copy the header in the thead in the body table, this way we show one single table when* in print view. Note that this section of code is more or less verbatim from DT 1.7.0*/nTheadSize = oSetDT.nTable.getElementsByTagName('thead');if ( nTheadSize.length > 0 ){oSetDT.nTable.removeChild( nTheadSize[0] );}if ( oSetDT.nTFoot !== null ){nTfootSize = oSetDT.nTable.getElementsByTagName('tfoot');if ( nTfootSize.length > 0 ){oSetDT.nTable.removeChild( nTfootSize[0] );}}nTheadSize = oSetDT.nTHead.cloneNode(true);oSetDT.nTable.insertBefore( nTheadSize, oSetDT.nTable.childNodes[0] );if ( oSetDT.nTFoot !== null ){nTfootSize = oSetDT.nTFoot.cloneNode(true);oSetDT.nTable.insertBefore( nTfootSize, oSetDT.nTable.childNodes[1] );}/* Now adjust the table's viewport so we can actually see it */if ( oSetDT.oScroll.sX !== "" ){oSetDT.nTable.style.width = $(oSetDT.nTable).outerWidth()+"px";nScrollBody.style.width = $(oSetDT.nTable).outerWidth()+"px";nScrollBody.style.overflow = "visible";}if ( oSetDT.oScroll.sY !== "" ){nScrollBody.style.height = $(oSetDT.nTable).outerHeight()+"px";nScrollBody.style.overflow = "visible";}},/*** Take account of scrolling in DataTables by showing the full table. Note that the redraw of* the DataTable that we do will actually deal with the majority of the hard work here* @returns void* @private*/"_fnPrintScrollEnd": function (){varoSetDT = this.s.dt,nScrollBody = oSetDT.nTable.parentNode;if ( oSetDT.oScroll.sX !== "" ){nScrollBody.style.width = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sX );nScrollBody.style.overflow = "auto";}if ( oSetDT.oScroll.sY !== "" ){nScrollBody.style.height = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sY );nScrollBody.style.overflow = "auto";}},/*** Resume the display of all TableTools hidden nodes* @method _fnPrintShowNodes* @returns void* @private*/"_fnPrintShowNodes": function ( ){var anHidden = this.dom.print.hidden;for ( var i=0, iLen=anHidden.length ; i<iLen ; i++ ){anHidden[i].node.style.display = anHidden[i].display;}anHidden.splice( 0, anHidden.length );},/*** Hide nodes which are not needed in order to display the table. Note that this function is* recursive* @method _fnPrintHideNodes* @param {Node} nNode Element which should be showing in a 'print' display* @returns void* @private*/"_fnPrintHideNodes": function ( nNode ){var anHidden = this.dom.print.hidden;var nParent = nNode.parentNode;var nChildren = nParent.childNodes;for ( var i=0, iLen=nChildren.length ; i<iLen ; i++ ){if ( nChildren[i] != nNode && nChildren[i].nodeType == 1 ){/* If our node is shown (don't want to show nodes which were previously hidden) */var sDisplay = $(nChildren[i]).css("display");if ( sDisplay != "none" ){/* Cache the node and it's previous state so we can restore it */anHidden.push( {"node": nChildren[i],"display": sDisplay} );nChildren[i].style.display = "none";}}}if ( nParent.nodeName.toUpperCase() != "BODY" ){this._fnPrintHideNodes( nParent );}}};/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Static variables* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//*** Store of all instances that have been created of TableTools, so one can look up other (when* there is need of a master)* @property _aInstances* @type Array* @default []* @private*/TableTools._aInstances = [];/*** Store of all listeners and their callback functions* @property _aListeners* @type Array* @default []*/TableTools._aListeners = [];/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Static methods* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//*** Get an array of all the master instances* @method fnGetMasters* @returns {Array} List of master TableTools instances* @static*/TableTools.fnGetMasters = function (){var a = [];for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ ){if ( TableTools._aInstances[i].s.master ){a.push( TableTools._aInstances[i] );}}return a;};/*** Get the master instance for a table node (or id if a string is given)* @method fnGetInstance* @returns {Object} ID of table OR table node, for which we want the TableTools instance* @static*/TableTools.fnGetInstance = function ( node ){if ( typeof node != 'object' ){node = document.getElementById(node);}for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ ){if ( TableTools._aInstances[i].s.master && TableTools._aInstances[i].dom.table == node ){return TableTools._aInstances[i];}}return null;};/*** Add a listener for a specific event* @method _fnEventListen* @param {Object} that Scope of the listening function (i.e. 'this' in the caller)* @param {String} type Event type* @param {Function} fn Function* @returns void* @private* @static*/TableTools._fnEventListen = function ( that, type, fn ){TableTools._aListeners.push( {"that": that,"type": type,"fn": fn} );};/*** An event has occurred - look up every listener and fire it off. We check that the event we are* going to fire is attached to the same table (using the table node as reference) before firing* @method _fnEventDispatch* @param {Object} that Scope of the listening function (i.e. 'this' in the caller)* @param {String} type Event type* @param {Node} node Element that the event occurred on (may be null)* @param {boolean} [selected] Indicate if the node was selected (true) or deselected (false)* @returns void* @private* @static*/TableTools._fnEventDispatch = function ( that, type, node, selected ){var listeners = TableTools._aListeners;for ( var i=0, iLen=listeners.length ; i<iLen ; i++ ){if ( that.dom.table == listeners[i].that.dom.table && listeners[i].type == type ){listeners[i].fn( node, selected );}}};/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Constants* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */TableTools.buttonBase = {// Button base"sAction": "text","sTag": "default","sLinerTag": "default","sButtonClass": "DTTT_button_text","sButtonText": "Button text","sTitle": "","sToolTip": "",// Common button specific options"sCharSet": "utf8","bBomInc": false,"sFileName": "*.csv","sFieldBoundary": "","sFieldSeperator": "\t","sNewLine": "auto","mColumns": "all", /* "all", "visible", "hidden" or array of column integers */"bHeader": true,"bFooter": true,"bOpenRows": false,"bSelectedOnly": false,"oSelectorOpts": undefined, // See http://datatables.net/docs/DataTables/1.9.4/#$ for full options// Callbacks"fnMouseover": null,"fnMouseout": null,"fnClick": null,"fnSelect": null,"fnComplete": null,"fnInit": null,"fnCellRender": null};/*** @namespace Default button configurations*/TableTools.BUTTONS = {"csv": $.extend( {}, TableTools.buttonBase, {"sAction": "flash_save","sButtonClass": "DTTT_button_csv","sButtonText": "CSV","sFieldBoundary": '"',"sFieldSeperator": ",","fnClick": function( nButton, oConfig, flash ) {this.fnSetText( flash, this.fnGetTableData(oConfig) );}} ),"xls": $.extend( {}, TableTools.buttonBase, {"sAction": "flash_save","sCharSet": "utf16le","bBomInc": true,"sButtonClass": "DTTT_button_xls","sButtonText": "Excel","fnClick": function( nButton, oConfig, flash ) {this.fnSetText( flash, this.fnGetTableData(oConfig) );}} ),"copy": $.extend( {}, TableTools.buttonBase, {"sAction": "flash_copy","sButtonClass": "DTTT_button_copy","sButtonText": "Copy","fnClick": function( nButton, oConfig, flash ) {this.fnSetText( flash, this.fnGetTableData(oConfig) );},"fnComplete": function(nButton, oConfig, flash, text) {var lines = text.split('\n').length;if (oConfig.bHeader) lines--;if (this.s.dt.nTFoot !== null && oConfig.bFooter) lines--;var plural = (lines==1) ? "" : "s";this.fnInfo( '<h6>Table copied</h6>'+'<p>Copied '+lines+' row'+plural+' to the clipboard.</p>',1500);}} ),"pdf": $.extend( {}, TableTools.buttonBase, {"sAction": "flash_pdf","sNewLine": "\n","sFileName": "*.pdf","sButtonClass": "DTTT_button_pdf","sButtonText": "PDF","sPdfOrientation": "portrait","sPdfSize": "A4","sPdfMessage": "","fnClick": function( nButton, oConfig, flash ) {this.fnSetText( flash,"title:"+ this.fnGetTitle(oConfig) +"\n"+"message:"+ oConfig.sPdfMessage +"\n"+"colWidth:"+ this.fnCalcColRatios(oConfig) +"\n"+"orientation:"+ oConfig.sPdfOrientation +"\n"+"size:"+ oConfig.sPdfSize +"\n"+"--/TableToolsOpts--\n" +this.fnGetTableData(oConfig));}} ),"print": $.extend( {}, TableTools.buttonBase, {"sInfo": "<h6>Print view</h6><p>Please use your browser's print function to "+"print this table. Press escape when finished.</p>","sMessage": null,"bShowAll": true,"sToolTip": "View print view","sButtonClass": "DTTT_button_print","sButtonText": "Print","fnClick": function ( nButton, oConfig ) {this.fnPrint( true, oConfig );}} ),"text": $.extend( {}, TableTools.buttonBase ),"select": $.extend( {}, TableTools.buttonBase, {"sButtonText": "Select button","fnSelect": function( nButton, oConfig ) {if ( this.fnGetSelected().length !== 0 ) {$(nButton).removeClass( this.classes.buttons.disabled );} else {$(nButton).addClass( this.classes.buttons.disabled );}},"fnInit": function( nButton, oConfig ) {$(nButton).addClass( this.classes.buttons.disabled );}} ),"select_single": $.extend( {}, TableTools.buttonBase, {"sButtonText": "Select button","fnSelect": function( nButton, oConfig ) {var iSelected = this.fnGetSelected().length;if ( iSelected == 1 ) {$(nButton).removeClass( this.classes.buttons.disabled );} else {$(nButton).addClass( this.classes.buttons.disabled );}},"fnInit": function( nButton, oConfig ) {$(nButton).addClass( this.classes.buttons.disabled );}} ),"select_all": $.extend( {}, TableTools.buttonBase, {"sButtonText": "Select all","fnClick": function( nButton, oConfig ) {this.fnSelectAll();},"fnSelect": function( nButton, oConfig ) {if ( this.fnGetSelected().length == this.s.dt.fnRecordsDisplay() ) {$(nButton).addClass( this.classes.buttons.disabled );} else {$(nButton).removeClass( this.classes.buttons.disabled );}}} ),"select_none": $.extend( {}, TableTools.buttonBase, {"sButtonText": "Deselect all","fnClick": function( nButton, oConfig ) {this.fnSelectNone();},"fnSelect": function( nButton, oConfig ) {if ( this.fnGetSelected().length !== 0 ) {$(nButton).removeClass( this.classes.buttons.disabled );} else {$(nButton).addClass( this.classes.buttons.disabled );}},"fnInit": function( nButton, oConfig ) {$(nButton).addClass( this.classes.buttons.disabled );}} ),"ajax": $.extend( {}, TableTools.buttonBase, {"sAjaxUrl": "/xhr.php","sButtonText": "Ajax button","fnClick": function( nButton, oConfig ) {var sData = this.fnGetTableData(oConfig);$.ajax( {"url": oConfig.sAjaxUrl,"data": [{ "name": "tableData", "value": sData }],"success": oConfig.fnAjaxComplete,"dataType": "json","type": "POST","cache": false,"error": function () {alert( "Error detected when sending table data to server" );}} );},"fnAjaxComplete": function( json ) {alert( 'Ajax complete' );}} ),"div": $.extend( {}, TableTools.buttonBase, {"sAction": "div","sTag": "div","sButtonClass": "DTTT_nonbutton","sButtonText": "Text button"} ),"collection": $.extend( {}, TableTools.buttonBase, {"sAction": "collection","sButtonClass": "DTTT_button_collection","sButtonText": "Collection","fnClick": function( nButton, oConfig ) {this._fnCollectionShow(nButton, oConfig);}} )};/** on* callback parameters:* 1. node - button element* 2. object - configuration object for this button* 3. object - ZeroClipboard reference (flash button only)* 4. string - Returned string from Flash (flash button only - and only on 'complete')*/// Alias to match the other plug-ins stylingTableTools.buttons = TableTools.BUTTONS;/*** @namespace Classes used by TableTools - allows the styles to be override easily.* Note that when TableTools initialises it will take a copy of the classes object* and will use its internal copy for the remainder of its run time.*/TableTools.classes = {"container": "DTTT_container","buttons": {"normal": "DTTT_button","disabled": "DTTT_disabled"},"collection": {"container": "DTTT_collection","background": "DTTT_collection_background","buttons": {"normal": "DTTT_button","disabled": "DTTT_disabled"}},"select": {"table": "DTTT_selectable","row": "DTTT_selected selected"},"print": {"body": "DTTT_Print","info": "DTTT_print_info","message": "DTTT_PrintMessage"}};/*** @namespace ThemeRoller classes - built in for compatibility with DataTables'* bJQueryUI option.*/TableTools.classes_themeroller = {"container": "DTTT_container ui-buttonset ui-buttonset-multi","buttons": {"normal": "DTTT_button ui-button ui-state-default"},"collection": {"container": "DTTT_collection ui-buttonset ui-buttonset-multi"}};/*** @namespace TableTools default settings for initialisation*/TableTools.DEFAULTS = {"sSwfPath": "../swf/copy_csv_xls_pdf.swf","sRowSelect": "none","sRowSelector": "tr","sSelectedClass": null,"fnPreRowSelect": null,"fnRowSelected": null,"fnRowDeselected": null,"aButtons": [ "copy", "csv", "xls", "pdf", "print" ],"oTags": {"container": "div","button": "a", // We really want to use buttons here, but Firefox and IE ignore the// click on the Flash element in the button (but not mouse[in|out])."liner": "span","collection": {"container": "div","button": "a","liner": "span"}}};// Alias to match the other plug-insTableTools.defaults = TableTools.DEFAULTS;/*** Name of this class* @constant CLASS* @type String* @default TableTools*/TableTools.prototype.CLASS = "TableTools";/*** TableTools version* @constant VERSION* @type String* @default See code*/TableTools.version = "2.2.3";// DataTables 1.10 API//// This will be extended in a big way in in TableTools 3 to provide API methods// such as rows().select() and rows.selected() etc, but for the moment the// tabletools() method simply returns the instance.if ( $.fn.dataTable.Api ) {$.fn.dataTable.Api.register( 'tabletools()', function () {var tt = null;if ( this.context.length > 0 ) {tt = TableTools.fnGetInstance( this.context[0].nTable );}return tt;} );}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Initialisation* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//** Register a new feature with DataTables*/if ( typeof $.fn.dataTable == "function" &&typeof $.fn.dataTableExt.fnVersionCheck == "function" &&$.fn.dataTableExt.fnVersionCheck('1.9.0') ){$.fn.dataTableExt.aoFeatures.push( {"fnInit": function( oDTSettings ) {var init = oDTSettings.oInit;var opts = init ?init.tableTools || init.oTableTools || {} :{};return new TableTools( oDTSettings.oInstance, opts ).dom.container;},"cFeature": "T","sFeature": "TableTools"} );}else{alert( "Warning: TableTools requires DataTables 1.9.0 or newer - www.datatables.net/download");}$.fn.DataTable.TableTools = TableTools;})(jQuery, window, document);/** Register a new feature with DataTables*/if ( typeof $.fn.dataTable == "function" &&typeof $.fn.dataTableExt.fnVersionCheck == "function" &&$.fn.dataTableExt.fnVersionCheck('1.9.0') ){$.fn.dataTableExt.aoFeatures.push( {"fnInit": function( oDTSettings ) {var oOpts = typeof oDTSettings.oInit.oTableTools != 'undefined' ?oDTSettings.oInit.oTableTools : {};var oTT = new TableTools( oDTSettings.oInstance, oOpts );TableTools._aInstances.push( oTT );return oTT.dom.container;},"cFeature": "T","sFeature": "TableTools"} );}else{alert( "Warning: TableTools 2 requires DataTables 1.9.0 or newer - www.datatables.net/download");}$.fn.dataTable.TableTools = TableTools;$.fn.DataTable.TableTools = TableTools;return TableTools;}; // /factory// Define as an AMD module if possibleif ( typeof define === 'function' && define.amd ) {define( ['jquery', 'datatables'], factory );}else if ( typeof exports === 'object' ) {// Node/CommonJSfactory( require('jquery'), require('datatables') );}else if ( jQuery && !jQuery.fn.dataTable.TableTools ) {// Otherwise simply initialise as normal, stopping multiple evaluationfactory( jQuery, jQuery.fn.dataTable );}})(window, document);