CC-3735 : Now Playing: Browser(Firefox) Mem usage goes high when play a show with hundreds of songs more than 3 hours

updating datatables to stable 1.9.1 release.

optimizing javascript, using jquery to add/remove nodes to avoid JQuery.cache issues.
This commit is contained in:
Naomi Aro 2012-05-03 15:04:23 +02:00
parent 08d939d736
commit c2c6e1b114
2 changed files with 399 additions and 184 deletions

View File

@ -143,35 +143,34 @@ var AIRTIME = (function(AIRTIME){
mod.checkToolBarIcons();
};
mod.fnItemCallback = function(json) {
checkError(json);
oSchedTable.fnDraw();
};
mod.fnAdd = function(aMediaIds, aSchedIds) {
$.post("/showbuilder/schedule-add",
{"format": "json", "mediaIds": aMediaIds, "schedIds": aSchedIds},
function(json){
checkError(json);
oSchedTable.fnDraw();
});
mod.fnItemCallback
);
};
mod.fnMove = function(aSelect, aAfter) {
$.post("/showbuilder/schedule-move",
{"format": "json", "selectedItem": aSelect, "afterItem": aAfter},
function(json){
checkError(json);
oSchedTable.fnDraw();
});
mod.fnItemCallback
);
};
mod.fnRemove = function(aItems) {
$.post( "/showbuilder/schedule-remove",
{"items": aItems, "format": "json"},
function(json) {
checkError(json);
oSchedTable.fnDraw();
});
mod.fnItemCallback
);
};
mod.fnRemoveSelectedItems = function() {
@ -189,10 +188,10 @@ var AIRTIME = (function(AIRTIME){
mod.fnRemove(aItems);
};
mod.fnServerData = function ( sSource, aoData, fnCallback ) {
mod.fnServerData = function fnBuilderServerData( sSource, aoData, fnCallback ) {
aoData.push( { name: "timestamp", value: AIRTIME.showbuilder.getTimestamp()} );
aoData.push( { name: "instances", value: AIRTIME.showbuilder.getShowInstances()} );
aoData.push( { name: "timestamp", value: mod.getTimestamp()} );
aoData.push( { name: "instances", value: mod.getShowInstances()} );
aoData.push( { name: "format", value: "json"} );
if (mod.fnServerData.hasOwnProperty("start")) {
@ -212,8 +211,8 @@ var AIRTIME = (function(AIRTIME){
"url": sSource,
"data": aoData,
"success": function(json) {
AIRTIME.showbuilder.setTimestamp(json.timestamp);
AIRTIME.showbuilder.setShowInstances(json.instances);
mod.setTimestamp(json.timestamp);
mod.setShowInstances(json.instances);
fnCallback(json);
}
});
@ -295,12 +294,12 @@ var AIRTIME = (function(AIRTIME){
oData.iCreate = parseInt(oData.iCreate, 10);
},
"fnServerData": AIRTIME.showbuilder.fnServerData,
"fnServerData": mod.fnServerData,
"fnRowCallback": function fnRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var i,
var i, length,
sSeparatorHTML,
fnPrepareSeparatorRow,
node,
$node,
cl="",
//background-color to imitate calendar color.
r,g,b,a,
@ -310,37 +309,37 @@ var AIRTIME = (function(AIRTIME){
fnPrepareSeparatorRow = function fnPrepareSeparatorRow(sRowContent, sClass, iNodeIndex) {
node = nRow.children[iNodeIndex];
node.innerHTML = sRowContent;
node.setAttribute('colspan',100);
for (i = iNodeIndex + 1; i < nRow.children.length; i = i+1) {
node = nRow.children[i];
node.innerHTML = "";
node.setAttribute("style", "display : none");
$node = $(nRow.children[iNodeIndex]);
$node.html(sRowContent);
$node.attr('colspan',100);
for (i = iNodeIndex + 1, length = nRow.children.length; i < length; i = i+1) {
$node = $(nRow.children[i]);
$node.html("");
$node.attr("style", "display : none");
}
$(nRow).addClass(sClass);
$nRow.addClass(sClass);
};
if (aData.header === true) {
//remove the column classes from all tds.
$(nRow).find('td').removeClass();
$nRow.find('td').removeClass();
node = nRow.children[0];
node.innerHTML = '';
$node = $(nRow.children[0]);
$node.html("");
cl = 'sb-header';
if (aData.record === true) {
$div = $("<div/>", {
"class": "small-icon recording"
});
$(node).append($div);
$node.append($div);
}
else if(aData.rebroadcast === true) {
else if (aData.rebroadcast === true) {
$div = $("<div/>", {
"class": "small-icon rebroadcast"
});
$(node).append($div);
$node.append($div);
}
sSeparatorHTML = '<span class="show-title">'+aData.title+'</span>';
@ -366,18 +365,18 @@ var AIRTIME = (function(AIRTIME){
}
else if (aData.footer === true) {
//remove the column classes from all tds.
$(nRow).find('td').removeClass();
$nRow.find('td').removeClass();
node = nRow.children[0];
$node = $(nRow.children[0]);
cl = 'sb-footer';
//check the show's content status.
if (aData.runtime > 0) {
node.innerHTML = '<span class="ui-icon ui-icon-check"></span>';
$node.html('<span class="ui-icon ui-icon-check"></span>');
cl = cl + ' ui-state-highlight';
}
else {
node.innerHTML = '<span class="ui-icon ui-icon-notice"></span>';
$node.html('<span class="ui-icon ui-icon-notice"></span>');
cl = cl + ' ui-state-error';
}
@ -386,10 +385,10 @@ var AIRTIME = (function(AIRTIME){
}
else if (aData.empty === true) {
//remove the column classes from all tds.
$(nRow).find('td').removeClass();
$nRow.find('td').removeClass();
node = nRow.children[0];
node.innerHTML = '';
$node = $(nRow.children[0]);
$node.html('');
sSeparatorHTML = '<span>Show Empty</span>';
cl = cl + " sb-empty odd";
@ -398,10 +397,10 @@ var AIRTIME = (function(AIRTIME){
}
else if (aData.record === true) {
//remove the column classes from all tds.
$(nRow).find('td').removeClass();
$nRow.find('td').removeClass();
node = nRow.children[0];
node.innerHTML = '';
$node = $(nRow.children[0]);
$node.html('');
sSeparatorHTML = '<span>Recording From Line In</span>';
cl = cl + " sb-record odd";
@ -411,7 +410,7 @@ var AIRTIME = (function(AIRTIME){
else {
//add the play function if the file exists on disk.
$image = $(nRow).find('td.sb-image');
$image = $nRow.find('td.sb-image');
//check if the file exists.
if (aData.image === true) {
$image.html('<img title="Track preview" src="/css/images/icon_audioclip.png"></img>')
@ -424,12 +423,12 @@ var AIRTIME = (function(AIRTIME){
$image.html('<span class="ui-icon ui-icon-alert"></span>');
}
node = nRow.children[0];
$node = $(nRow.children[0]);
if (aData.allowed === true && aData.scheduled >= 1) {
node.innerHTML = '<input type="checkbox" name="'+aData.id+'"></input>';
$node.html('<input type="checkbox" name="'+aData.id+'"></input>');
}
else {
node.innerHTML = '';
$node.html('');
}
}
@ -455,39 +454,39 @@ var AIRTIME = (function(AIRTIME){
}
//save some info for reordering purposes.
$(nRow).data({"aData": aData});
$nRow.data({"aData": aData});
if (aData.scheduled === 1) {
$(nRow).addClass("sb-now-playing");
$nRow.addClass("sb-now-playing");
}
else if (aData.scheduled === 0) {
$(nRow).addClass("sb-past");
$nRow.addClass("sb-past");
}
else {
$(nRow).addClass("sb-future");
$nRow.addClass("sb-future");
}
if (aData.allowed !== true) {
$(nRow).addClass("sb-not-allowed");
$nRow.addClass("sb-not-allowed");
}
else {
$(nRow).addClass("sb-allowed");
$nRow.addClass("sb-allowed");
}
//status used to colour tracks.
if (aData.status === 2) {
$(nRow).addClass("sb-boundry");
$nRow.addClass("sb-boundry");
}
else if (aData.status === 0) {
$(nRow).addClass("sb-over");
$nRow.addClass("sb-over");
}
if (aData.currentShow === true) {
$(nRow).addClass("sb-current-show");
$nRow.addClass("sb-current-show");
}
//call the context menu so we can prevent the event from propagating.
$(nRow).find('td:gt(1)').click(function(e){
$nRow.find('td:gt(1)').click(function(e){
$(this).contextMenu({x: e.pageX, y: e.pageY});
@ -513,7 +512,7 @@ var AIRTIME = (function(AIRTIME){
//use this array to cache DOM heights then we can detach the table to manipulate it to increase speed.
heights = [];
clearTimeout(AIRTIME.showbuilder.timeout);
clearTimeout(mod.timeout);
//only create the cursor arrows if the library is on the page.
if ($lib.length > 0 && $lib.filter(":visible").length > 0) {
@ -574,7 +573,7 @@ var AIRTIME = (function(AIRTIME){
if (temp.length > 0) {
aData = temp.data("aData");
setTimeout(mod.refresh, aData.refresh * 1000); //need refresh in milliseconds
mod.timeout = setTimeout(mod.refresh, aData.refresh * 1000); //need refresh in milliseconds
break;
}
}
@ -646,7 +645,7 @@ var AIRTIME = (function(AIRTIME){
}
aSchedIds.push({"id": oPrevData.id, "instance": oPrevData.instance, "timestamp": oPrevData.timestamp});
AIRTIME.showbuilder.fnAdd(aMediaIds, aSchedIds);
mod.fnAdd(aMediaIds, aSchedIds);
};
fnMove = function() {
@ -659,7 +658,7 @@ var AIRTIME = (function(AIRTIME){
aAfter.push({"id": oPrevData.id, "instance": oPrevData.instance, "timestamp": oPrevData.timestamp});
AIRTIME.showbuilder.fnMove(aSelect, aAfter);
mod.fnMove(aSelect, aAfter);
};
fnReceive = function(event, ui) {

View File

@ -1,7 +1,7 @@
/**
* @summary DataTables
* @description Paginate, search and sort HTML tables
* @version 1.9.1.dev
* @version 1.9.1
* @file jquery.dataTables.js
* @author Allan Jardine (www.sprymedia.co.uk)
* @contact www.sprymedia.co.uk/contact
@ -21,7 +21,7 @@
*/
/*jslint evil: true, undef: true, browser: true */
/*globals $, jQuery,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex*/
/*globals $, jQuery,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros*/
(/** @lends <global> */function($, window, document, undefined) {
/**
@ -445,9 +445,8 @@
/* Create the object for storing information about this new row */
var iRow = oSettings.aoData.length;
var oData = $.extend( true, {}, DataTable.models.oRow, {
"_aData": aDataIn
} );
var oData = $.extend( true, {}, DataTable.models.oRow );
oData._aData = aDataIn;
oSettings.aoData.push( oData );
/* Create the cells */
@ -461,6 +460,10 @@
{
_fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );
}
else
{
_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
}
/* See if we should auto-detect the column type */
if ( oCol._bAutoType && oCol.sType != 'string' )
@ -738,8 +741,9 @@
{
if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
{
_fnLog( oSettings, 0, "Requested unknown parameter '"+oCol.mDataProp+
"' from the data source for row "+iRow );
_fnLog( oSettings, 0, "Requested unknown parameter "+
(typeof oCol.mDataProp=='function' ? '{mDataprop function}' : "'"+oCol.mDataProp+"'")+
" from the data source for row "+iRow );
oSettings.iDrawError = oSettings.iDraw;
}
return oCol.sDefaultContent;
@ -862,6 +866,10 @@
for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
{
data = data[ a[i] ];
if ( data === undefined )
{
return;
}
}
data[ a[a.length-1] ] = val;
};
@ -996,7 +1004,7 @@
for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
{
var oCol = oSettings.aoColumns[i];
nTd = document.createElement('td');
nTd = document.createElement( oCol.sCellType );
/* Render if needed - if bUseRendered is true then we already have the rendered
* value in the data source - so can just use that
@ -1372,22 +1380,22 @@
anRows[ 0 ].className = oSettings.asStripeClasses[0];
}
var sZero = oSettings.oLanguage.sZeroRecords.replace(
'_MAX_', oSettings.fnFormatNumber(oSettings.fnRecordsTotal()) );
var oLang = oSettings.oLanguage;
var sZero = oLang.sZeroRecords;
if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
{
sZero = oSettings.oLanguage.sLoadingRecords;
sZero = oLang.sLoadingRecords;
}
else if ( oSettings.oLanguage.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
{
sZero = oSettings.oLanguage.sEmptyTable;
sZero = oLang.sEmptyTable;
}
var nTd = document.createElement( 'td' );
nTd.setAttribute( 'valign', "top" );
nTd.colSpan = _fnVisbleColumns( oSettings );
nTd.className = oSettings.oClasses.sRowEmpty;
nTd.innerHTML = sZero;
nTd.innerHTML = _fnInfoMacros( oSettings, sZero );
anRows[ iRowCount ].appendChild( nTd );
}
@ -1968,19 +1976,21 @@
jqFilter.bind( 'keyup.DT', function(e) {
/* Update all other filter input elements for the new display */
var n = oSettings.aanFeatures.f;
var val = this.value==="" ? "" : this.value; // mental IE8 fix :-(
for ( var i=0, iLen=n.length ; i<iLen ; i++ )
{
if ( n[i] != $(this).parents('div.dataTables_filter')[0] )
{
$(n[i]._DT_Input).val( this.value );
$(n[i]._DT_Input).val( val );
}
}
/* Now do the filter */
if ( this.value != oPreviousSearch.sSearch )
if ( val != oPreviousSearch.sSearch )
{
_fnFilterComplete( oSettings, {
"sSearch": this.value,
"sSearch": val,
"bRegex": oPreviousSearch.bRegex,
"bSmart": oPreviousSearch.bSmart ,
"bCaseInsensitive": oPreviousSearch.bCaseInsensitive
@ -2307,6 +2317,10 @@
{
return DataTable.ext.ofnSearch[sType]( sData );
}
else if ( sData === null )
{
return '';
}
else if ( sType == "html" )
{
return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" );
@ -2315,10 +2329,6 @@
{
return sData.replace(/[\r\n]/g," ");
}
else if ( sData === null )
{
return '';
}
return sData;
}
@ -2381,57 +2391,41 @@
}
var
iStart = oSettings._iDisplayStart+1, iEnd = oSettings.fnDisplayEnd(),
iMax = oSettings.fnRecordsTotal(), iTotal = oSettings.fnRecordsDisplay(),
sStart = oSettings.fnFormatNumber( iStart ), sEnd = oSettings.fnFormatNumber( iEnd ),
sMax = oSettings.fnFormatNumber( iMax ), sTotal = oSettings.fnFormatNumber( iTotal ),
oLang = oSettings.oLanguage,
iStart = oSettings._iDisplayStart+1,
iEnd = oSettings.fnDisplayEnd(),
iMax = oSettings.fnRecordsTotal(),
iTotal = oSettings.fnRecordsDisplay(),
sOut;
/* When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
* internally
*/
if ( oSettings.oScroll.bInfinite )
{
sStart = oSettings.fnFormatNumber( 1 );
}
if ( oSettings.fnRecordsDisplay() === 0 &&
oSettings.fnRecordsDisplay() == oSettings.fnRecordsTotal() )
if ( iTotal === 0 && iTotal == iMax )
{
/* Empty record set */
sOut = oSettings.oLanguage.sInfoEmpty+ oSettings.oLanguage.sInfoPostFix;
sOut = oLang.sInfoEmpty;
}
else if ( oSettings.fnRecordsDisplay() === 0 )
else if ( iTotal === 0 )
{
/* Rmpty record set after filtering */
sOut = oSettings.oLanguage.sInfoEmpty +' '+
oSettings.oLanguage.sInfoFiltered.replace('_MAX_', sMax)+
oSettings.oLanguage.sInfoPostFix;
/* Empty record set after filtering */
sOut = oLang.sInfoEmpty +' '+ oLang.sInfoFiltered;
}
else if ( oSettings.fnRecordsDisplay() == oSettings.fnRecordsTotal() )
else if ( iTotal == iMax )
{
/* Normal record set */
sOut = oSettings.oLanguage.sInfo.
replace('_START_', sStart).
replace('_END_', sEnd).
replace('_TOTAL_', sTotal)+
oSettings.oLanguage.sInfoPostFix;
sOut = oLang.sInfo;
}
else
{
/* Record set after filtering */
sOut = oSettings.oLanguage.sInfo.
replace('_START_', sStart).
replace('_END_', sEnd).
replace('_TOTAL_', sTotal) +' '+
oSettings.oLanguage.sInfoFiltered.replace('_MAX_',
oSettings.fnFormatNumber(oSettings.fnRecordsTotal()))+
oSettings.oLanguage.sInfoPostFix;
sOut = oLang.sInfo +' '+ oLang.sInfoFiltered;
}
// Convert the macros
sOut += oLang.sInfoPostFix;
sOut = _fnInfoMacros( oSettings, sOut );
if ( oSettings.oLanguage.fnInfoCallback !== null )
if ( oLang.fnInfoCallback !== null )
{
sOut = oSettings.oLanguage.fnInfoCallback.call( oSettings.oInstance,
sOut = oLang.fnInfoCallback.call( oSettings.oInstance,
oSettings, iStart, iEnd, iMax, iTotal, sOut );
}
@ -2443,6 +2437,33 @@
}
function _fnInfoMacros ( oSettings, str )
{
var
iStart = oSettings._iDisplayStart+1,
sStart = oSettings.fnFormatNumber( iStart ),
iEnd = oSettings.fnDisplayEnd(),
sEnd = oSettings.fnFormatNumber( iEnd ),
iTotal = oSettings.fnRecordsDisplay(),
sTotal = oSettings.fnFormatNumber( iTotal ),
iMax = oSettings.fnRecordsTotal(),
sMax = oSettings.fnFormatNumber( iMax );
// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
// internally
if ( oSettings.oScroll.bInfinite )
{
sStart = oSettings.fnFormatNumber( 1 );
}
return str.
replace('_START_', sStart).
replace('_END_', sEnd).
replace('_TOTAL_', sTotal).
replace('_MAX_', sMax);
}
/**
* Draw the table for the first time, adding all required features
@ -2576,16 +2597,20 @@
*/
function _fnLanguageCompat( oLanguage )
{
var oDefaults = DataTable.defaults.oLanguage;
/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
* sZeroRecords - assuming that is given.
*/
if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords )
if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords &&
oDefaults.sEmptyTable === "No data available in table" )
{
_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );
}
/* Likewise with loading records */
if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords )
if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&
oDefaults.sLoadingRecords === "Loading..." )
{
_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' );
}
@ -2954,7 +2979,8 @@
nScrollHead.style.border = "0";
nScrollHead.style.width = "100%";
nScrollFoot.style.border = "0";
nScrollHeadInner.style.width = "150%"; /* will be overwritten */
nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ?
oSettings.oScroll.sXInner : "100%"; /* will be overwritten */
/* Modify attributes to respect the clones */
nScrollHeadTable.removeAttribute('id');
@ -2966,11 +2992,20 @@
nScrollFootTable.style.marginLeft = "0";
}
/* Move any caption elements from the body to the header */
var nCaptions = $(oSettings.nTable).children('caption');
for ( var i=0, iLen=nCaptions.length ; i<iLen ; i++ )
/* Move caption elements from the body to the header, footer or leave where it is
* depending on the configuration. Note that the DTD says there can be only one caption */
var nCaption = $(oSettings.nTable).children('caption');
if ( nCaption.length > 0 )
{
nScrollHeadTable.appendChild( nCaptions[i] );
nCaption = nCaption[0];
if ( nCaption._captionSide === "top" )
{
nScrollHeadTable.appendChild( nCaption );
}
else if ( nCaption._captionSide === "bottom" && nTfoot )
{
nScrollFootTable.appendChild( nCaption );
}
}
/*
@ -3070,14 +3105,14 @@
/* Remove the old minimised thead and tfoot elements in the inner table */
$(o.nTable).children('thead, tfoot').remove();
/* Clone the current header and footer elements and then place it into the inner table */
nTheadSize = o.nTHead.cloneNode(true);
nTheadSize = $(o.nTHead).clone()[0];
o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
if ( o.nTFoot !== null )
{
nTfootSize = o.nTFoot.cloneNode(true);
nTfootSize = $(o.nTFoot).clone()[0];
o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
}
@ -3108,6 +3143,14 @@
n.style.width = "";
}, nTfootSize.getElementsByTagName('tr') );
}
// If scroll collapse is enabled, when we put the headers back into the body for sizing, we
// will end up forcing the scrollbar to appear, making our measurements wrong for when we
// then hide it (end of this function), so add the header height to the body scroller.
if ( o.oScroll.bCollapse && o.oScroll.sY !== "" )
{
nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px";
}
/* Size the table as a whole */
iSanityWidth = $(o.nTable).outerWidth();
@ -3292,7 +3335,7 @@
o.oScroll.iBarWidth : 0;
if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
{
nScrollBody.style.height = _fnStringToCss( $(o.nTable).height()+iExtra );
nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
}
}
@ -3796,7 +3839,9 @@
sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
if ( DataTable.ext.afnSortData[sDataType] )
{
var aData = DataTable.ext.afnSortData[sDataType]( oSettings, iColumn, iVisColumn );
var aData = DataTable.ext.afnSortData[sDataType].call(
oSettings.oInstance, oSettings, iColumn, iVisColumn
);
if ( aData.length === aoData.length )
{
for ( j=0, jLen=aoData.length ; j<jLen ; j++ )
@ -3894,6 +3939,7 @@
for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
{
var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" );
nTh = aoColumns[i].nTh;
nTh.removeAttribute('aria-sort');
nTh.removeAttribute('aria-label');
@ -3907,18 +3953,18 @@
var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ?
aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
nTh.setAttribute('aria-label', aoColumns[i].sTitle+
nTh.setAttribute('aria-label', sTitle+
(nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
}
else
{
nTh.setAttribute('aria-label', aoColumns[i].sTitle+
nTh.setAttribute('aria-label', sTitle+
(aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
}
}
else
{
nTh.setAttribute('aria-label', aoColumns[i].sTitle);
nTh.setAttribute('aria-label', sTitle);
}
}
@ -5194,10 +5240,8 @@
/* Flag to note that the table is currently being destroyed - no action should be taken */
oSettings.bDestroying = true;
/* Restore hidden columns */
for ( i=0, iLen=oSettings.aoDestroyCallback.length ; i<iLen ; i++ ) {
oSettings.aoDestroyCallback[i].fn();
}
/* Fire off the destroy callbacks for plug-ins etc */
_fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
/* Restore hidden columns */
for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
@ -5317,7 +5361,7 @@
this.fnDraw = function( bComplete )
{
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
if ( bComplete )
if ( bComplete === false )
{
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
@ -5713,7 +5757,7 @@
var i, iLen;
var aoColumns = oSettings.aoColumns;
var aoData = oSettings.aoData;
var nTd, nCell, anTrs, jqChildren, bAppend, iBefore;
var nTd, bAppend, iBefore;
/* No point in doing anything if we are requesting what is already true */
if ( aoColumns[iCol].bVisible == bShow )
@ -5833,7 +5877,7 @@
/**
* Sort the table by a particular row
* Sort the table by a particular column
* @param {int} iCol the data index to sort on. Note that this will not match the
* 'display index' if you have hidden data entries
* @dtopt API
@ -5899,7 +5943,7 @@
this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
{
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
var iVisibleColumn, i, iLen, sDisplay;
var i, iLen, sDisplay;
var iRow = (typeof mRow === 'object') ?
_fnNodeToDataIndex(oSettings, mRow) : mRow;
@ -6105,7 +6149,8 @@
"_fnCallbackFire": _fnCallbackFire,
"_fnJsonString": _fnJsonString,
"_fnRender": _fnRender,
"_fnNodeToColumnIndex": _fnNodeToColumnIndex
"_fnNodeToColumnIndex": _fnNodeToColumnIndex,
"_fnInfoMacros": _fnInfoMacros
};
$.extend( DataTable.ext.oApi, this.oApi );
@ -6173,7 +6218,7 @@
}
/* Ensure the table has an ID - required for accessibility */
if ( sId === null )
if ( sId === null || sId === "" )
{
sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++);
this.id = sId;
@ -6320,8 +6365,9 @@
if ( oInit.iDeferLoading !== null )
{
oSettings.bDeferLoading = true;
oSettings._iRecordsTotal = oInit.iDeferLoading;
oSettings._iRecordsDisplay = oInit.iDeferLoading;
var tmp = $.isArray( oInit.iDeferLoading );
oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
}
if ( oInit.aaData !== null )
@ -6353,6 +6399,13 @@
/*
* Stripes
*/
if ( oInit.asStripeClasses === null )
{
oSettings.asStripeClasses =[
oSettings.oClasses.sStripeOdd,
oSettings.oClasses.sStripeEven
];
}
/* Remove row stripe classes if they are already on the table row */
var bStripeRemove = false;
@ -6485,6 +6538,12 @@
* Final init
* Cache the header, body and footer as required, creating them if needed
*/
// Work around for Webkit bug 83867 - store the caption-side before removing from doc
var captions = $(this).children('caption').each( function () {
this._captionSide = $(this).css('caption-side');
} );
var thead = $(this).children('thead');
if ( thead.length === 0 )
{
@ -6505,6 +6564,14 @@
oSettings.nTBody.setAttribute( "aria-relevant", "all" );
var tfoot = $(this).children('tfoot');
if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
{
// If we are a scrolling table, and no footer has been given, then we need to create
// a tfoot element for the caption element to be appended to
tfoot = [ document.createElement( 'tfoot' ) ];
this.appendChild( tfoot[0] );
}
if ( tfoot.length > 0 )
{
oSettings.nTFoot = tfoot[0];
@ -6541,6 +6608,105 @@
} );
};
/**
* Provide a common method for plug-ins to check the version of DataTables being used, in order
* to ensure compatibility.
* @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
* formats "X" and "X.Y" are also acceptable.
* @returns {boolean} true if this version of DataTables is greater or equal to the required
* version, or false if this version of DataTales is not suitable
* @static
* @dtopt API-Static
*
* @example
* alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );
*/
DataTable.fnVersionCheck = function( sVersion )
{
/* This is cheap, but effective */
var fnZPad = function (Zpad, count)
{
while(Zpad.length < count) {
Zpad += '0';
}
return Zpad;
};
var aThis = DataTable.ext.sVersion.split('.');
var aThat = sVersion.split('.');
var sThis = '', sThat = '';
for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
{
sThis += fnZPad( aThis[i], 3 );
sThat += fnZPad( aThat[i], 3 );
}
return parseInt(sThis, 10) >= parseInt(sThat, 10);
};
/**
* Check if a TABLE node is a DataTable table already or not.
* @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
* node types can be passed in, but will always return false).
* @returns {boolean} true the table given is a DataTable, or false otherwise
* @static
* @dtopt API-Static
*
* @example
* var ex = document.getElementById('example');
* if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
* $(ex).dataTable();
* }
*/
DataTable.fnIsDataTable = function ( nTable )
{
var o = DataTable.settings;
for ( var i=0 ; i<o.length ; i++ )
{
if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable )
{
return true;
}
}
return false;
};
/**
* Get all DataTable tables that have been initialised - optionally you can select to
* get only currently visible tables.
* @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or
* visible tables only.
* @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables
* @static
* @dtopt API-Static
*
* @example
* var table = $.fn.dataTable.fnTables(true);
* if ( table.length > 0 ) {
* $(table).dataTable().fnAdjustColumnSizing();
* }
*/
DataTable.fnTables = function ( bVisible )
{
var out = [];
jQuery.each( DataTable.settings, function (i, o) {
if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
{
out.push( o.nTable );
}
} );
return out;
};
/**
* Version string for plug-ins to check compatibility. Allowed format is
* a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
@ -6549,7 +6715,7 @@
* @type string
* @default Version number
*/
DataTable.version = "1.9.1.dev";
DataTable.version = "1.9.1";
/**
* Private data store, containing all of the settings objects that are created for the
@ -6797,28 +6963,7 @@
* alert( oTable.fnVersionCheck( '1.9.0' ) );
* } );
*/
"fnVersionCheck": function( sVersion )
{
/* This is cheap, but very effective */
var fnZPad = function (Zpad, count)
{
while(Zpad.length < count) {
Zpad += '0';
}
return Zpad;
};
var aThis = DataTable.ext.sVersion.split('.');
var aThat = sVersion.split('.');
var sThis = '', sThat = '';
for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
{
sThis += fnZPad( aThis[i], 3 );
sThat += fnZPad( aThat[i], 3 );
}
return parseInt(sThis, 10) >= parseInt(sThat, 10);
},
"fnVersionCheck": DataTable.fnVersionCheck,
/**
@ -7683,7 +7828,8 @@
* array may be of any length, and DataTables will apply each class
* sequentially, looping when required.
* @type array
* @default [ 'odd', 'even' ]
* @default null <i>Will take the values determinted by the oClasses.sStripe*
* options</i>
* @dtopt Option
*
* @example
@ -7693,7 +7839,7 @@
* } );
* } )
*/
"asStripeClasses": [ 'odd', 'even' ],
"asStripeClasses": null,
/**
@ -7768,7 +7914,7 @@
* specified (this allow matching across multiple columns). Note that if you
* wish to use filtering in DataTables this must remain 'true' - to remove the
* default filtering input box and retain filtering abilities, please use
* @ref{sDom}.
* {@link DataTable.defaults.sDom}.
* @type boolean
* @default true
* @dtopt Features
@ -8129,7 +8275,7 @@
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "fnDrawCallback": function() {
* "fnDrawCallback": function( oSettings ) {
* alert( 'DataTables has redrawn the table' );
* }
* } );
@ -8399,8 +8545,8 @@
"type": oSettings.sServerMethod,
"error": function (xhr, error, thrown) {
if ( error == "parsererror" ) {
alert( "DataTables warning: JSON data from server could not be parsed. "+
"This is caused by a JSON formatting error." );
oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
"server could not be parsed. This is caused by a JSON formatting error." );
}
}
} );
@ -8627,12 +8773,18 @@
* will be applied to it), thus saving on an XHR at load time. iDeferLoading
* is used to indicate that deferred loading is required, but it is also used
* to tell DataTables how many records there are in the full table (allowing
* the information element and pagination to be displayed correctly).
* @type int
* the information element and pagination to be displayed correctly). In the case
* where a filtering is applied to the table on initial load, this can be
* indicated by giving the parameter as an array, where the first element is
* the number of records available after filtering and the second element is the
* number of records without filtering (allowing the table information element
* to be shown correctly).
* @type int | array
* @default null
* @dtopt Options
*
* @example
* // 57 records available in the table, no filtering applied
* $(document).ready(function() {
* $('#example').dataTable( {
* "bServerSide": true,
@ -8640,6 +8792,19 @@
* "iDeferLoading": 57
* } );
* } );
*
* @example
* // 57 records after filtering, 100 without filtering (an initial filter applied)
* $(document).ready(function() {
* $('#example').dataTable( {
* "bServerSide": true,
* "sAjaxSource": "scripts/server_processing.php",
* "iDeferLoading": [ 57, 100 ],
* "oSearch": {
* "sSearch": "my_filter"
* }
* } );
* } );
*/
"iDeferLoading": null,
@ -9315,7 +9480,7 @@
* Enable horizontal scrolling. When a table is too wide to fit into a certain
* layout, or you have a large number of columns in the table, you can enable
* x-scrolling to show the table in a viewport, which can be scrolled. This
* property can by any CSS unit, or a number (in which case it will be treated
* property can be any CSS unit, or a number (in which case it will be treated
* as a pixel measurement).
* @type string
* @default <i>blank string - i.e. disabled</i>
@ -9356,10 +9521,10 @@
/**
* Enable vertical scrolling. Vertical scrolling will constrain the DataTable
* to the given height, an enable scrolling for any data which overflows the
* to the given height, and enable scrolling for any data which overflows the
* current viewport. This can be used as an alternative to paging to display
* a lot of data in a small area (although paging and scrolling can both be
* enabled at the same time). This property can by any CSS unit, or a number
* enabled at the same time). This property can be any CSS unit, or a number
* (in which case it will be treated as a pixel measurement).
* @type string
* @default <i>blank string - i.e. disabled</i>
@ -9753,8 +9918,9 @@
* <ul>
* <li>{array|object} The data source for the row</li>
* <li>{string} The type call data requested - this will be 'set' when
* setting data or 'filter', 'display', 'type' or 'sort' when gathering
* data.</li>
* setting data or 'filter', 'display', 'type', 'sort' or undefined when
* gathering data. Note that when <i>undefined</i> is given for the type
* DataTables expects to get the raw data for the object back</li>
* <li>{*} Data to set when the second parameter is 'set'.</li>
* </ul>
* The return value from the function is not required when 'set' is the type
@ -9802,7 +9968,7 @@
* else if (type === 'filter') {
* return source.price_filter;
* }
* // 'sort' and 'type' both just use the integer
* // 'sort', 'type' and undefined all just use the integer
* return source.price;
* }
* ]
@ -9812,6 +9978,29 @@
"mDataProp": null,
/**
* Change the cell type created for the column - either TD cells or TH cells. This
* can be useful as TH cells have semantic meaning in the table body, allowing them
* to act as a header for a row (you may wish to add scope='row' to the TH elements).
* @type string
* @default td
* @dtopt Columns
*
* @example
* // Make the first column use TH cells
* $(document).ready(function() {
* var oTable = $('#example').dataTable( {
* "aoColumnDefs": [
* {
* "aTargets": [ 0 ],
* "sCellType": "th"
* ]
* } );
* } );
*/
"sCellType": "td",
/**
* Class to give to each cell in this column.
* @type string
@ -10965,7 +11154,17 @@
* tabindex attribute value that is added to DataTables control elements, allowing
* keyboard navigation of the table and its controls.
*/
"iTabIndex": 0
"iTabIndex": 0,
/**
* DIV container for the footer scrolling table if scrolling
*/
"nScrollHead": null,
/**
* DIV container for the footer scrolling table if scrolling
*/
"nScrollFoot": null
};
/**
@ -11272,7 +11471,13 @@
};
/* Pages calculation */
if (iPages < iPageCount)
if ( oSettings._iDisplayLength === -1 )
{
iStartButton = 1;
iEndButton = 1;
iCurrentPage = 1;
}
else if (iPages < iPageCount)
{
iStartButton = 1;
iEndButton = iPages;
@ -11292,6 +11497,7 @@
iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
iEndButton = iStartButton + iPageCount - 1;
}
/* Build the dynamic list */
for ( i=iStartButton ; i<=iEndButton ; i++ )
@ -11619,4 +11825,14 @@
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
/**
* Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
* the bDestroy:true parameter in the initialisation object. This can be used to remove
* bound events, added DOM nodes, etc.
* @name DataTable#destroy
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
}(jQuery, window, document, undefined));