/* * File: ColReorderWithResize.js * Version: 1.0.7 * CVS: $Id$ * Description: Allow columns to be reordered in a DataTable * Author: Allan Jardine (www.sprymedia.co.uk) * Author: Christophe Battarel (www.altairis.fr) * Created: Wed Sep 15 18:23:29 BST 2010 * Modified: July 2011 by Christophe Battarel - christophe.battarel@altairis.fr (columns resizable) * Modified: February 2012 by Martin Marchetta - martin.marchetta@gmail.com * 1. Made the "hot area" for resizing a little wider (it was a little difficult to hit the exact border of a column for resizing) * 2. Resizing didn't work at all when using scroller (that plugin splits the table into 2 different tables: one for the header and another one for the body, so when you resized the header, the data columns didn't follow) * 3. Fixed collateral effects of sorting feature * 4. If sScrollX is enabled (i.e. horizontal scrolling), when resizing a column the width of the other columns is not changed, but the whole * table is resized to give an Excel-like behavior (good suggestion by Allan) * Modified: February 2012 by Christophe Battarel - christophe.battarel@altairis.fr (ColReorder v1.0.5 adaptation) * Modified: September 16th 2012 by Hassan Kamara - h@phrmc.com * Language: Javascript * License: GPL v2 or BSD 3 point style * Project: DataTables * Contact: www.sprymedia.co.uk/contact * * Copyright 2010-2011 Allan Jardine, all rights reserved. * * This source file is free software, under either the GPL v2 license or a * BSD style license, available at: * http://datatables.net/license_gpl2 * http://datatables.net/license_bsd * */ (function($, window, document) { /** * Switch the key value pairing of an index array to be value key (i.e. the old value is now the * key). For example consider [ 2, 0, 1 ] this would be returned as [ 1, 2, 0 ]. * @method fnInvertKeyValues * @param array aIn Array to switch around * @returns array */ function fnInvertKeyValues( aIn ) { var aRet=[]; for ( var i=0, iLen=aIn.length ; i= iCols ) { this.oApi._fnLog( oSettings, 1, "ColReorder 'from' index is out of bounds: "+iFrom ); return; } if ( iTo < 0 || iTo >= iCols ) { this.oApi._fnLog( oSettings, 1, "ColReorder 'to' index is out of bounds: "+iTo ); return; } /* * Calculate the new column array index, so we have a mapping between the old and new */ var aiMapping = []; for ( i=0, iLen=iCols ; i this.s.fixed-1 ) { this._fnMouseListener( i, this.s.dt.aoColumns[i].nTh ); } /* Mark the original column order for later reference */ this.s.dt.aoColumns[i]._ColReorder_iOrigCol = i; } /* State saving */ this.s.dt.oApi._fnCallbackReg( this.s.dt, 'aoStateSaveParams', function (oS, oData) { that._fnStateSave.call( that, oData ); }, "ColReorder_State" ); /* An initial column order has been specified */ var aiOrder = null; if ( typeof this.s.init.aiOrder != 'undefined' ) { aiOrder = this.s.init.aiOrder.slice(); } /* State loading, overrides the column order given */ if ( this.s.dt.oLoadedState && typeof this.s.dt.oLoadedState.ColReorder != 'undefined' && this.s.dt.oLoadedState.ColReorder.length == this.s.dt.aoColumns.length ) { aiOrder = this.s.dt.oLoadedState.ColReorder; } /* If we have an order to apply - do so */ if ( aiOrder ) { /* We might be called during or after the DataTables initialisation. If before, then we need * to wait until the draw is done, if after, then do what we need to do right away */ if ( !that.s.dt._bInitComplete ) { var bDone = false; this.s.dt.aoDrawCallback.push( { "fn": function () { if ( !that.s.dt._bInitComplete && !bDone ) { bDone = true; var resort = fnInvertKeyValues( aiOrder ); that._fnOrderColumns.call( that, resort ); } }, "sName": "ColReorder_Pre" } ); } else { var resort = fnInvertKeyValues( aiOrder ); that._fnOrderColumns.call( that, resort ); } } }, /** * Set the column order from an array * @method _fnOrderColumns * @param array a An array of integers which dictate the column order that should be applied * @returns void * @private */ "_fnOrderColumns": function ( a ) { if ( a.length != this.s.dt.aoColumns.length ) { this.s.dt.oInstance.oApi._fnLog( oDTSettings, 1, "ColReorder - array reorder does not "+ "match known number of columns. Skipping." ); return; } for ( var i=0, iLen=a.length ; i 0) this.table_size = $($('div.dataTables_scrollHead', this.s.dt.nTableWrapper)[0].childNodes[0].childNodes[0]).width(); } //////////////////// /* are we resizing a column ? */ if (this.dom.resize) { var nTh = this.s.mouse.resizeElem; var nThNext = $(nTh).next(); var moveLength = e.pageX-this.s.mouse.startX; if (moveLength != 0 && !scrollXEnabled) $(nThNext).width(this.s.mouse.nextStartWidth - moveLength); $(nTh).width(this.s.mouse.startWidth + moveLength); //Martin Marchetta: Resize the header too (if sScrollX is enabled) if(scrollXEnabled && $('div.dataTables_scrollHead', this.s.dt.nTableWrapper) != undefined){ if($('div.dataTables_scrollHead', this.s.dt.nTableWrapper).length > 0) $($('div.dataTables_scrollHead', this.s.dt.nTableWrapper)[0].childNodes[0].childNodes[0]).width(this.table_size + moveLength); } //////////////////////// //Martin Marchetta: Fixed col resizing when the scroller is enabled. var visibleColumnIndex; //First determine if this plugin is being used along with the smart scroller... if($('div.dataTables_scrollBody') != null){ //...if so, when resizing the header, also resize the table's body (when enabling the Scroller, the table's header and //body are split into different tables, so the column resizing doesn't work anymore) if($('div.dataTables_scrollBody').length > 0){ //Since some columns might have been hidden, find the correct one to resize in the table's body var currentColumnIndex; visibleColumnIndex = -1; for(currentColumnIndex=-1; currentColumnIndex < this.s.dt.aoColumns.length-1 && currentColumnIndex != colResized; currentColumnIndex++){ if(this.s.dt.aoColumns[currentColumnIndex+1].bVisible) visibleColumnIndex++; } //Get the scroller's div tableScroller = $('div.dataTables_scrollBody', this.s.dt.nTableWrapper)[0]; //Get the table scrollingTableHead = $(tableScroller)[0].childNodes[0].childNodes[0].childNodes[0]; //Resize the columns if (moveLength != 0 && !scrollXEnabled){ $($(scrollingTableHead)[0].childNodes[visibleColumnIndex+1]).width(this.s.mouse.nextStartWidth - moveLength); } $($(scrollingTableHead)[0].childNodes[visibleColumnIndex]).width(this.s.mouse.startWidth + moveLength); //Resize the table too if(scrollXEnabled) $($(tableScroller)[0].childNodes[0]).width(this.table_size + moveLength); } } //////////////////////// return; } else if (this.s.allowReorder) { if ( this.dom.drag === null ) { /* Only create the drag element if the mouse has moved a specific distance from the start * point - this allows the user to make small mouse movements when sorting and not have a * possibly confusing drag element showing up */ if ( Math.pow( Math.pow(e.pageX - this.s.mouse.startX, 2) + Math.pow(e.pageY - this.s.mouse.startY, 2), 0.5 ) < 5 ) { return; } this._fnCreateDragNode(); } /* Position the element - we respect where in the element the click occured */ this.dom.drag.style.left = (e.pageX - this.s.mouse.offsetX) + "px"; this.dom.drag.style.top = (e.pageY - this.s.mouse.offsetY) + "px"; /* Based on the current mouse position, calculate where the insert should go */ var bSet = false; for ( var i=1, iLen=this.s.aoTargets.length ; i