docs: function _fnGatherData( oSettings )
  		{
  			var iLoop, i, iLen, j, jLen, jInner,
  			 	nTds, nTrs, nTd, aLocalData, iThisIndex,
  				iRow, iRows, iColumn, iColumns, sNodeName,
  				oCol, oData;
  			
  			/*
  			 * Process by row first
  			 * Add the data object for the whole table - storing the tr node. Note - no point in getting
  			 * DOM based data if we are going to go and replace it with Ajax source data.
  			 */
  			if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )
  			{
  				nTrs = oSettings.nTBody.childNodes;
  				for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  				{
  					if ( nTrs[i].nodeName.toUpperCase() == "TR" )
  					{
  						iThisIndex = oSettings.aoData.length;
  						nTrs[i]._DT_RowIndex = iThisIndex;
  						oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {
  							"nTr": nTrs[i]
  						} ) );
  						
  						oSettings.aiDisplayMaster.push( iThisIndex );
  						nTds = nTrs[i].childNodes;
  						jInner = 0;
  						
  						for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
  						{
  							sNodeName = nTds[j].nodeName.toUpperCase();
  							if ( sNodeName == "TD" || sNodeName == "TH" )
  							{
  								_fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTds[j].innerHTML) );
  								jInner++;
  							}
  						}
  					}
  				}
  			}
  			
  			/* Gather in the TD elements of the Table - note that this is basically the same as
  			 * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
  			 * setup!
  			 */
  			nTrs = _fnGetTrNodes( oSettings );
  			nTds = [];
  			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  			{
  				for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
  				{
  					nTd = nTrs[i].childNodes[j];
  					sNodeName = nTd.nodeName.toUpperCase();
  					if ( sNodeName == "TD" || sNodeName == "TH" )
  					{
  						nTds.push( nTd );
  					}
  				}
  			}
  			
  			/* Now process by column */
  			for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
  			{
  				oCol = oSettings.aoColumns[iColumn];
  		
  				/* Get the title of the column - unless there is a user set one */
  				if ( oCol.sTitle === null )
  				{
  					oCol.sTitle = oCol.nTh.innerHTML;
  				}
  				
  				var
  					bAutoType = oCol._bAutoType,
  					bRender = typeof oCol.fnRender === 'function',
  					bClass = oCol.sClass !== null,
  					bVisible = oCol.bVisible,
  					nCell, sThisType, sRendered, sValType;
  				
  				/* A single loop to rule them all (and be more efficient) */
  				if ( bAutoType || bRender || bClass || !bVisible )
  				{
  					for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )
  					{
  						oData = oSettings.aoData[iRow];
  						nCell = nTds[ (iRow*iColumns) + iColumn ];
  						
  						/* Type detection */
  						if ( bAutoType && oCol.sType != 'string' )
  						{
  							sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );
  							if ( sValType !== '' )
  							{
  								sThisType = _fnDetectType( sValType );
  								if ( oCol.sType === null )
  								{
  									oCol.sType = sThisType;
  								}
  								else if ( oCol.sType != sThisType && 
  								          oCol.sType != "html" )
  								{
  									/* String is always the 'fallback' option */
  									oCol.sType = 'string';
  								}
  							}
  						}
  		
  						if ( typeof oCol.mDataProp === 'function' )
  						{
  							nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
  						}
  						
  						/* Rendering */
  						if ( bRender )
  						{
  							sRendered = _fnRender( oSettings, iRow, iColumn );
  							nCell.innerHTML = sRendered;
  							if ( oCol.bUseRendered )
  							{
  								/* Use the rendered data for filtering/sorting */
  								_fnSetCellData( oSettings, iRow, iColumn, sRendered );
  							}
  						}
  						
  						/* Classes */
  						if ( bClass )
  						{
  							nCell.className += ' '+oCol.sClass;
  						}
  						
  						/* Column visability */
  						if ( !bVisible )
  						{
  							oData._anHidden[iColumn] = nCell;
  							nCell.parentNode.removeChild( nCell );
  						}
  						else
  						{
  							oData._anHidden[iColumn] = null;
  						}
  		
  						if ( oCol.fnCreatedCell )
  						{
  							oCol.fnCreatedCell.call( oSettings.oInstance,
  								nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn
  							);
  						}
  					}
  				}
  			}
  		
  			/* Row created callbacks */
  			if ( oSettings.aoRowCreatedCallback.length !== 0 )
  			{
  				for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  				{
  					oData = oSettings.aoData[i];
  					_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );
  				}
  			}
  		}