function _fnCalculateColumnWidths ( oSettings )
	{
		var
			table = oSettings.nTable,
			columns = oSettings.aoColumns,
			scroll = oSettings.oScroll,
			scrollY = scroll.sY,
			scrollX = scroll.sX,
			scrollXInner = scroll.sXInner,
			columnCount = columns.length,
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
			headerCells = $('th', oSettings.nTHead),
			tableWidthAttr = table.getAttribute('width'), // from DOM element
			tableContainer = table.parentNode,
			userInputs = false,
			i, column, columnIdx, width, outerWidth,
			browser = oSettings.oBrowser,
			ie67 = browser.bScrollOversize;
	
		var styleWidth = table.style.width;
		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
			tableWidthAttr = styleWidth;
		}
	
		/* Convert any user input sizes into pixel sizes */
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
			column = columns[ visibleColumns[i] ];
	
			if ( column.sWidth !== null ) {
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
	
				userInputs = true;
			}
		}
	
		/* If the number of columns in the DOM equals the number that we have to
		 * process in DataTables, then we can use the offsets that are created by
		 * the web- browser. No custom sizes can be set in order for this to happen,
		 * nor scrolling used
		 */
		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
		     columnCount == _fnVisbleColumns( oSettings ) &&
		     columnCount == headerCells.length
		) {
			for ( i=0 ; i<columnCount ; i++ ) {
				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
	
				if ( colIdx ) {
					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
				}
			}
		}
		else
		{
			// Otherwise construct a single row, worst case, table with the widest
			// node in the data, assign any user defined widths, then insert it into
			// the DOM and allow the browser to do all the hard work of calculating
			// table widths
			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
				.css( 'visibility', 'hidden' )
				.removeAttr( 'id' );
	
			// Clean up the table body
			tmpTable.find('tbody tr').remove();
			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
	
			// Clone the table header and footer - we can't use the header / footer
			// from the cloned table, since if scrolling is active, the table's
			// real header and footer are contained in different table tags
			tmpTable.find('thead, tfoot').remove();
			tmpTable
				.append( $(oSettings.nTHead).clone() )
				.append( $(oSettings.nTFoot).clone() );
	
			// Remove any assigned widths from the footer (from scrolling)
			tmpTable.find('tfoot th, tfoot td').css('width', '');
	
			// Apply custom sizing to the cloned header
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
	
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
				column = columns[ visibleColumns[i] ];
	
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
					_fnStringToCss( column.sWidthOrig ) :
					'';
			}
	
			// Find the widest cell for each column and put it into the table
			if ( oSettings.aoData.length ) {
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
					columnIdx = visibleColumns[i];
					column = columns[ columnIdx ];
	
					$( _fnGetWidestNode( oSettings, columnIdx ) )
						.clone( false )
						.append( column.sContentPadding )
						.appendTo( tr );
				}
			}
	
			// Table has been built, attach to the document so we can work with it.
			// A holding element is used, positioned at the top of the container
			// with minimal height, so it has no effect on if the container scrolls
			// or not. Otherwise it might trigger scrolling when it actually isn't
			// needed
			var holder = $('<div/>').css( scrollX || scrollY ?
					{
						position: 'absolute',
						top: 0,
						left: 0,
						height: 1,
						right: 0,
						overflow: 'hidden'
					} :
					{}
				)
				.append( tmpTable )
				.appendTo( tableContainer );
	
			// When scrolling (X or Y) we want to set the width of the table as 
			// appropriate. However, when not scrolling leave the table width as it
			// is. This results in slightly different, but I think correct behaviour
			if ( scrollX && scrollXInner ) {
				tmpTable.width( scrollXInner );
			}
			else if ( scrollX ) {
				tmpTable.css( 'width', 'auto' );
	
				if ( tmpTable.width() < tableContainer.clientWidth ) {
					tmpTable.width( tableContainer.clientWidth );
				}
			}
			else if ( scrollY ) {
				tmpTable.width( tableContainer.clientWidth );
			}
			else if ( tableWidthAttr ) {
				tmpTable.width( tableWidthAttr );
			}
	
			// Browsers need a bit of a hand when a width is assigned to any columns
			// when x-scrolling as they tend to collapse the table to the min-width,
			// even if we sent the column widths. So we need to keep track of what
			// the table width should be by summing the user given values, and the
			// automatic values
			if ( scrollX )
			{
				var total = 0;
	
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
					column = columns[ visibleColumns[i] ];
	
					// Much prefer to use getBoundingClientRect due to its sub-pixel
					// resolution, but IE8- do not support the width property.
					outerWidth = browser.bBounding ?
						headerCells[i].getBoundingClientRect().width :
						$(headerCells[i]).outerWidth();
	
					total += column.sWidthOrig === null ?
						outerWidth :
						parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
				}
	
				tmpTable.width( _fnStringToCss( total ) );
				table.style.width = _fnStringToCss( total );
			}
	
			// Get the width of each column in the constructed table
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
				column = columns[ visibleColumns[i] ];
				width = $(headerCells[i]).width();
	
				if ( width ) {
					column.sWidth = _fnStringToCss( width );
				}
			}
	
			table.style.width = _fnStringToCss( tmpTable.css('width') );
	
			// Finished with the table - ditch it
			holder.remove();
		}
	
		// If there is a width attr, we want to attach an event listener which
		// allows the table sizing to automatically adjust when the window is
		// resized. Use the width attr rather than CSS, since we can't know if the
		// CSS is a relative value or absolute - DOM read is always px.
		if ( tableWidthAttr ) {
			table.style.width = _fnStringToCss( tableWidthAttr );
		}
	
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
			var bindResize = function () {
				$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
					_fnAdjustColumnSizing( oSettings );
				} ) );
			};
	
			// IE6/7 will crash if we bind a resize event handler on page load.
			// To be removed in 1.11 which drops IE6/7 support
			if ( ie67 ) {
				setTimeout( bindResize, 1000 );
			}
			else {
				bindResize();
			}
	
			oSettings._reszEvt = true;
		}
	}
/**
	 * Calculate the width of columns for the table
	 *  @param {object} oSettings dataTables settings object
	 *  @memberof DataTable#oApi
	 */
Calculate the width of columns for the table
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
Calculate the width of columns for the table @param { object } oSettings dataTables settings object @memberof DataTable#oApi
function _fnCalculateColumnWidths ( oSettings )
	{
		var
			table = oSettings.nTable,
			columns = oSettings.aoColumns,
			scroll = oSettings.oScroll,
			scrollY = scroll.sY,
			scrollX = scroll.sX,
			scrollXInner = scroll.sXInner,
			columnCount = columns.length,
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
			headerCells = $('th', oSettings.nTHead),
			tableWidthAttr = table.getAttribute('width'), 
			tableContainer = table.parentNode,
			userInputs = false,
			i, column, columnIdx, width, outerWidth,
			browser = oSettings.oBrowser,
			ie67 = browser.bScrollOversize;
		var styleWidth = table.style.width;
		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
			tableWidthAttr = styleWidth;
		}
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
			column = columns[ visibleColumns[i] ];
			if ( column.sWidth !== null ) {
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
				userInputs = true;
			}
		}
		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
		     columnCount == _fnVisbleColumns( oSettings ) &&
		     columnCount == headerCells.length
		) {
			for ( i=0 ; i<columnCount ; i++ ) {
				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
				if ( colIdx ) {
					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
				}
			}
		}
		else
		{
			var tmpTable = $(table).clone() 
				.css( 'visibility', 'hidden' )
				.removeAttr( 'id' );
			tmpTable.find('tbody tr').remove();
			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
			tmpTable.find('thead, tfoot').remove();
			tmpTable
				.append( $(oSettings.nTHead).clone() )
				.append( $(oSettings.nTFoot).clone() );
			tmpTable.find('tfoot th, tfoot td').css('width', '');
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
				column = columns[ visibleColumns[i] ];
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
					_fnStringToCss( column.sWidthOrig ) :
					'';
			}
			if ( oSettings.aoData.length ) {
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
					columnIdx = visibleColumns[i];
					column = columns[ columnIdx ];
					$( _fnGetWidestNode( oSettings, columnIdx ) )
						.clone( false )
						.append( column.sContentPadding )
						.appendTo( tr );
				}
			}
			var holder = $('<div/>').css( scrollX || scrollY ?
					{
						position: 'absolute',
						top: 0,
						left: 0,
						height: 1,
						right: 0,
						overflow: 'hidden'
					} :
					{}
				)
				.append( tmpTable )
				.appendTo( tableContainer );
			if ( scrollX && scrollXInner ) {
				tmpTable.width( scrollXInner );
			}
			else if ( scrollX ) {
				tmpTable.css( 'width', 'auto' );
				if ( tmpTable.width() < tableContainer.clientWidth ) {
					tmpTable.width( tableContainer.clientWidth );
				}
			}
			else if ( scrollY ) {
				tmpTable.width( tableContainer.clientWidth );
			}
			else if ( tableWidthAttr ) {
				tmpTable.width( tableWidthAttr );
			}
			if ( scrollX )
			{
				var total = 0;
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
					column = columns[ visibleColumns[i] ];
					outerWidth = browser.bBounding ?
						headerCells[i].getBoundingClientRect().width :
						$(headerCells[i]).outerWidth();
					total += column.sWidthOrig === null ?
						outerWidth :
						parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
				}
				tmpTable.width( _fnStringToCss( total ) );
				table.style.width = _fnStringToCss( total );
			}
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
				column = columns[ visibleColumns[i] ];
				width = $(headerCells[i]).width();
				if ( width ) {
					column.sWidth = _fnStringToCss( width );
				}
			}
			table.style.width = _fnStringToCss( tmpTable.css('width') );
			holder.remove();
		}
		if ( tableWidthAttr ) {
			table.style.width = _fnStringToCss( tableWidthAttr );
		}
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
			var bindResize = function () {
				$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
					_fnAdjustColumnSizing( oSettings );
				} ) );
			};
			if ( ie67 ) {
				setTimeout( bindResize, 1000 );
			}
			else {
				bindResize();
			}
			oSettings._reszEvt = true;
		}
	}
function _fnCalculateColumnWidths ( oSettings ) { var table = oSettings . nTable , columns = oSettings . aoColumns , scroll = oSettings . oScroll , scrollY = scroll . sY , scrollX = scroll . sX , scrollXInner = scroll . sXInner , columnCount = columns . length , visibleColumns = _fnGetColumns ( oSettings , 'bVisible' ) , headerCells = $ ( 'th' , oSettings . nTHead ) , tableWidthAttr = table . getAttribute ( 'width' ) , tableContainer = table . parentNode , userInputs = false , i , column , columnIdx , width , outerWidth , browser = oSettings . oBrowser , ie67 = browser . bScrollOversize ; var styleWidth = table . style . width ; if ( styleWidth && styleWidth . indexOf ( '%' ) !== - 1 ) { tableWidthAttr = styleWidth ; } for ( i = 0 ; i < visibleColumns . length ; i ++ ) { column = columns [ visibleColumns [ i ] ] ; if ( column . sWidth !== null ) { column . sWidth = _fnConvertToWidth ( column . sWidthOrig , tableContainer ) ; userInputs = true ; } } if ( ie67 || ! userInputs && ! scrollX && ! scrollY && columnCount == _fnVisbleColumns ( oSettings ) && columnCount == headerCells . length ) { for ( i = 0 ; i < columnCount ; i ++ ) { var colIdx = _fnVisibleToColumnIndex ( oSettings , i ) ; if ( colIdx ) { columns [ colIdx ] . sWidth = _fnStringToCss ( headerCells . eq ( i ) . width ( ) ) ; } } } else { var tmpTable = $ ( table ) . clone ( ) . css ( 'visibility' , 'hidden' ) . removeAttr ( 'id' ) ; tmpTable . find ( 'tbody tr' ) . remove ( ) ; var tr = $ ( '<tr/>' ) . appendTo ( tmpTable . find ( 'tbody' ) ) ; tmpTable . find ( 'thead, tfoot' ) . remove ( ) ; tmpTable . append ( $ ( oSettings . nTHead ) . clone ( ) ) . append ( $ ( oSettings . nTFoot ) . clone ( ) ) ; tmpTable . find ( 'tfoot th, tfoot td' ) . css ( 'width' , '' ) ; headerCells = _fnGetUniqueThs ( oSettings , tmpTable . find ( 'thead' ) [ 0 ] ) ; for ( i = 0 ; i < visibleColumns . length ; i ++ ) { column = columns [ visibleColumns [ i ] ] ; headerCells [ i ] . style . width = column . sWidthOrig !== null && column . sWidthOrig !== '' ? _fnStringToCss ( column . sWidthOrig ) : '' ; } if ( oSettings . aoData . length ) { for ( i = 0 ; i < visibleColumns . length ; i ++ ) { columnIdx = visibleColumns [ i ] ; column = columns [ columnIdx ] ; $ ( _fnGetWidestNode ( oSettings , columnIdx ) ) . clone ( false ) . append ( column . sContentPadding ) . appendTo ( tr ) ; } } var holder = $ ( '<div/>' ) . css ( scrollX || scrollY ? { position : 'absolute' , top : 0 , left : 0 , height : 1 , right : 0 , overflow : 'hidden' } : { } ) . append ( tmpTable ) . appendTo ( tableContainer ) ; if ( scrollX && scrollXInner ) { tmpTable . width ( scrollXInner ) ; } else if ( scrollX ) { tmpTable . css ( 'width' , 'auto' ) ; if ( tmpTable . width ( ) < tableContainer . clientWidth ) { tmpTable . width ( tableContainer . clientWidth ) ; } } else if ( scrollY ) { tmpTable . width ( tableContainer . clientWidth ) ; } else if ( tableWidthAttr ) { tmpTable . width ( tableWidthAttr ) ; } if ( scrollX ) { var total = 0 ; for ( i = 0 ; i < visibleColumns . length ; i ++ ) { column = columns [ visibleColumns [ i ] ] ; outerWidth = browser . bBounding ? headerCells [ i ] . getBoundingClientRect ( ) . width : $ ( headerCells [ i ] ) . outerWidth ( ) ; total += column . sWidthOrig === null ? outerWidth : parseInt ( column . sWidth , 10 ) + outerWidth - $ ( headerCells [ i ] ) . width ( ) ; } tmpTable . width ( _fnStringToCss ( total ) ) ; table . style . width = _fnStringToCss ( total ) ; } for ( i = 0 ; i < visibleColumns . length ; i ++ ) { column = columns [ visibleColumns [ i ] ] ; width = $ ( headerCells [ i ] ) . width ( ) ; if ( width ) { column . sWidth = _fnStringToCss ( width ) ; } } table . style . width = _fnStringToCss ( tmpTable . css ( 'width' ) ) ; holder . remove ( ) ; } if ( tableWidthAttr ) { table . style . width = _fnStringToCss ( tableWidthAttr ) ; } if ( ( tableWidthAttr || scrollX ) && ! oSettings . _reszEvt ) { var bindResize = function ( ) { $ ( window ) . bind ( 'resize.DT-' + oSettings . sInstance , _fnThrottle ( function ( ) { _fnAdjustColumnSizing ( oSettings ) ; } ) ) ; } ; if ( ie67 ) { setTimeout ( bindResize , 1000 ) ; } else { bindResize ( ) ; } oSettings . _reszEvt = true ; } }
Calculate the width of columns for the table
  @param {object} oSettings dataTables settings object
  @memberof DataTable#oApi
Calculate the width of columns for the table @param { object } oSettings dataTables settings object @memberof DataTable#oApi
// from DOM element /* Convert any user input sizes into pixel sizes */ /* If the number of columns in the DOM equals the number that we have to
		 * process in DataTables, then we can use the offsets that are created by
		 * the web- browser. No custom sizes can be set in order for this to happen,
		 * nor scrolling used
		 */ // Otherwise construct a single row, worst case, table with the widest // node in the data, assign any user defined widths, then insert it into // the DOM and allow the browser to do all the hard work of calculating // table widths // don't use cloneNode - IE8 will remove events on the main table // Clean up the table body // Clone the table header and footer - we can't use the header / footer // from the cloned table, since if scrolling is active, the table's // real header and footer are contained in different table tags // Remove any assigned widths from the footer (from scrolling) // Apply custom sizing to the cloned header // Find the widest cell for each column and put it into the table // Table has been built, attach to the document so we can work with it. // A holding element is used, positioned at the top of the container // with minimal height, so it has no effect on if the container scrolls // or not. Otherwise it might trigger scrolling when it actually isn't // needed // When scrolling (X or Y) we want to set the width of the table as  // appropriate. However, when not scrolling leave the table width as it // is. This results in slightly different, but I think correct behaviour // Browsers need a bit of a hand when a width is assigned to any columns // when x-scrolling as they tend to collapse the table to the min-width, // even if we sent the column widths. So we need to keep track of what // the table width should be by summing the user given values, and the // automatic values // Much prefer to use getBoundingClientRect due to its sub-pixel // resolution, but IE8- do not support the width property. // Get the width of each column in the constructed table // Finished with the table - ditch it // If there is a width attr, we want to attach an event listener which // allows the table sizing to automatically adjust when the window is // resized. Use the width attr rather than CSS, since we can't know if the // CSS is a relative value or absolute - DOM read is always px. // IE6/7 will crash if we bind a resize event handler on page load. // To be removed in 1.11 which drops IE6/7 support