diff options
| author | Greg Roach <fisharebest@gmail.com> | 2014-07-31 11:26:40 +0100 |
|---|---|---|
| committer | Greg Roach <fisharebest@gmail.com> | 2014-07-31 11:26:40 +0100 |
| commit | 77f6aef3be4aad11ce651126f5c0a4c89fdbc33d (patch) | |
| tree | f116d6c26c71c415354c940029b5dea735fb382a /js | |
| parent | c679086edab769382da55469e4575d4bc5964ea7 (diff) | |
| download | webtrees-77f6aef3be4aad11ce651126f5c0a4c89fdbc33d.tar.gz webtrees-77f6aef3be4aad11ce651126f5c0a4c89fdbc33d.tar.bz2 webtrees-77f6aef3be4aad11ce651126f5c0a4c89fdbc33d.zip | |
Update datatables to 1.10.1
Diffstat (limited to 'js')
| -rw-r--r-- | js/jquery.datatables-1.10.1.js (renamed from js/jquery.datatables-1.10.0.js) | 703 |
1 files changed, 467 insertions, 236 deletions
diff --git a/js/jquery.datatables-1.10.0.js b/js/jquery.datatables-1.10.1.js index fce3d1a9ac..6689db3174 100644 --- a/js/jquery.datatables-1.10.0.js +++ b/js/jquery.datatables-1.10.1.js @@ -1,11 +1,11 @@ -/*! DataTables 1.10.0 +/*! DataTables 1.10.1 * ©2008-2014 SpryMedia Ltd - datatables.net/license */ /** * @summary DataTables * @description Paginate, search and order HTML tables - * @version 1.10.0 + * @version 1.10.1 * @file jquery.dataTables.js * @author SpryMedia Ltd (www.sprymedia.co.uk) * @contact www.sprymedia.co.uk/contact @@ -105,7 +105,8 @@ var _re_dic = {}; var _re_new_lines = /[\r\n]/g; var _re_html = /<.*?>/g; - var _re_date_start = /^[\d\+\-a-zA-Z]/; + var _re_date_start = /^[\w\+\-]/; + var _re_date_end = /[\w\+\-]$/; // Escape regular expression special characters var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); @@ -116,7 +117,7 @@ var _empty = function ( d ) { - return !d || d === '-' ? true : false; + return !d || d === true || d === '-' ? true : false; }; @@ -149,13 +150,13 @@ d = d.replace( _re_formatted_numeric, '' ); } - return !d || d==='-' || (!isNaN( parseFloat(d) ) && isFinite( d )); + return _empty( d ) || (!isNaN( parseFloat(d) ) && isFinite( d )); }; // A string without HTML in it can be considered to be HTML still var _isHtml = function ( d ) { - return !d || typeof d === 'string'; + return _empty( d ) || typeof d === 'string'; }; @@ -435,6 +436,18 @@ _fnCompatMap( init, 'pagingType', 'sPaginationType' ); _fnCompatMap( init, 'pageLength', 'iDisplayLength' ); _fnCompatMap( init, 'searching', 'bFilter' ); + + // Column search objects are in an array, so it needs to be converted + // element by element + var searchCols = init.aoSearchCols; + + if ( searchCols ) { + for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) { + if ( searchCols[i] ) { + _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] ); + } + } + } } @@ -591,7 +604,7 @@ oCol.sWidthOrig = th.attr('width') || null; // Style attribute - var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%])/); + var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); if ( t ) { oCol.sWidthOrig = t[1]; } @@ -649,16 +662,16 @@ attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) ); - oCol.fnGetData = function (oData, sSpecific) { - var innerData = mData( oData, sSpecific ); + oCol.fnGetData = function (rowData, type, meta) { + var innerData = mData( rowData, type, undefined, meta ); - if ( oCol.mRender && (sSpecific && sSpecific !== '') ) - { - return mRender( innerData, sSpecific, oData ); - } - return innerData; + return mRender && type ? + mRender( innerData, type, rowData, meta ) : + innerData; + }; + oCol.fnSetData = function ( rowData, val, meta ) { + return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); }; - oCol.fnSetData = _fnSetObjectDataFn( mDataSrc ); /* Feature sorting overrides column specific when off */ if ( !oSettings.oFeatures.bSort ) @@ -969,8 +982,8 @@ /* Add to the display array */ oSettings.aiDisplayMaster.push( iRow ); - /* Create the DOM information */ - if ( !oSettings.oFeatures.bDeferRender ) + /* Create the DOM information, or register it if already present */ + if ( nTr || ! oSettings.oFeatures.bDeferRender ) { _fnCreateTr( oSettings, iRow, nTr, anTds ); } @@ -1034,64 +1047,70 @@ /** * Get the data for a given cell from the internal cache, taking into account data mapping - * @param {object} oSettings dataTables settings object - * @param {int} iRow aoData row id - * @param {int} iCol Column index - * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort') + * @param {object} settings dataTables settings object + * @param {int} rowIdx aoData row id + * @param {int} colIdx Column index + * @param {string} type data get type ('display', 'type' 'filter' 'sort') * @returns {*} Cell data * @memberof DataTable#oApi */ - function _fnGetCellData( oSettings, iRow, iCol, sSpecific ) + function _fnGetCellData( settings, rowIdx, colIdx, type ) { - var oCol = oSettings.aoColumns[iCol]; - var oData = oSettings.aoData[iRow]._aData; - var sData = oCol.fnGetData( oData, sSpecific ); + var draw = settings.iDraw; + var col = settings.aoColumns[colIdx]; + var rowData = settings.aoData[rowIdx]._aData; + var defaultContent = col.sDefaultContent; + var cellData = col.fnGetData( rowData, type, { + settings: settings, + row: rowIdx, + col: colIdx + } ); - if ( sData === undefined ) - { - if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null ) - { - _fnLog( oSettings, 0, "Requested unknown parameter "+ - (typeof oCol.mData=='function' ? '{function}' : "'"+oCol.mData+"'")+ - " for row "+iRow, 4 ); - oSettings.iDrawError = oSettings.iDraw; + if ( cellData === undefined ) { + if ( settings.iDrawError != draw && defaultContent === null ) { + _fnLog( settings, 0, "Requested unknown parameter "+ + (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+ + " for row "+rowIdx, 4 ); + settings.iDrawError = draw; } - return oCol.sDefaultContent; + return defaultContent; } /* When the data source is null, we can use default column data */ - if ( (sData === oData || sData === null) && oCol.sDefaultContent !== null ) - { - sData = oCol.sDefaultContent; + if ( (cellData === rowData || cellData === null) && defaultContent !== null ) { + cellData = defaultContent; } - else if ( typeof sData === 'function' ) - { - // If the data source is a function, then we run it and use the return - return sData(); + else if ( typeof cellData === 'function' ) { + // If the data source is a function, then we run it and use the return, + // executing in the scope of the data object (for instances) + return cellData.call( rowData ); } - if ( sData === null && sSpecific == 'display' ) - { + if ( cellData === null && type == 'display' ) { return ''; } - return sData; + return cellData; } /** * Set the value for a specific cell, into the internal data cache - * @param {object} oSettings dataTables settings object - * @param {int} iRow aoData row id - * @param {int} iCol Column index + * @param {object} settings dataTables settings object + * @param {int} rowIdx aoData row id + * @param {int} colIdx Column index * @param {*} val Value to set * @memberof DataTable#oApi */ - function _fnSetCellData( oSettings, iRow, iCol, val ) + function _fnSetCellData( settings, rowIdx, colIdx, val ) { - var oCol = oSettings.aoColumns[iCol]; - var oData = oSettings.aoData[iRow]._aData; + var col = settings.aoColumns[colIdx]; + var rowData = settings.aoData[rowIdx]._aData; - oCol.fnSetData( oData, val ); + col.fnSetData( rowData, val, { + settings: settings, + row: rowIdx, + col: colIdx + } ); } @@ -1107,7 +1126,7 @@ function _fnSplitObjNotation( str ) { return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) { - return s.replace('\\.', '.'); + return s.replace(/\\./g, '.'); } ); } @@ -1131,24 +1150,24 @@ } } ); - return function (data, type, extra) { + return function (data, type, row, meta) { var t = o[type] || o._; return t !== undefined ? - t(data, type, extra) : + t(data, type, row, meta) : data; }; } else if ( mSource === null ) { /* Give an empty string for rendering / sorting etc */ - return function (data, type) { + return function (data) { // type, row and meta also passed, but not used return data; }; } else if ( typeof mSource === 'function' ) { - return function (data, type, extra) { - return mSource( data, type, extra ); + return function (data, type, row, meta) { + return mSource( data, type, row, meta ); }; } else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || @@ -1221,14 +1240,14 @@ return data; }; - return function (data, type) { + return function (data, type) { // row and meta also passed, but not used return fetchData( data, type, mSource ); }; } else { /* Array or flat object mapping */ - return function (data, type) { + return function (data, type) { // row and meta also passed, but not used return data[mSource]; }; } @@ -1256,12 +1275,12 @@ else if ( mSource === null ) { /* Nothing to do when the data source is null */ - return function (data, val) {}; + return function () {}; } else if ( typeof mSource === 'function' ) { - return function (data, val) { - mSource( data, 'set', val ); + return function (data, val, meta) { + mSource( data, 'set', val, meta ); }; } else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || @@ -1331,14 +1350,14 @@ } }; - return function (data, val) { + return function (data, val) { // meta is also passed in, but not used return setData( data, val, mSource ); }; } else { /* Array or flat object mapping */ - return function (data, val) { + return function (data, val) { // meta is also passed in, but not used data[mSource] = val; }; } @@ -1425,9 +1444,19 @@ else { // Reading from data object, update the DOM var cells = row.anCells; + var cell; if ( cells ) { for ( i=0, ien=cells.length ; i<ien ; i++ ) { + cell = cells[i]; + + // This is very frustrating, but in IE if you just write directly + // to innerHTML, and elements that are overwritten are GC'ed, + // even if there is a reference to them elsewhere + while ( cell.childNodes.length ) { + cell.removeChild( cell.firstChild ); + } + cells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' ); } } @@ -1505,7 +1534,6 @@ d.push( contents ); } - tds.push( cell ); i++; }; @@ -1516,6 +1544,7 @@ if ( name == "TD" || name == "TH" ) { cellProcess( td ); + tds.push( td ); } td = td.nextSibling; @@ -1602,7 +1631,7 @@ if ( oCol.fnCreatedCell ) { oCol.fnCreatedCell.call( oSettings.oInstance, - nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), rowData, iRow, i + nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i ); } } @@ -2002,7 +2031,13 @@ settings._iDisplayStart = 0; } + // Let any modules know about the draw hold position state (used by + // scrolling internally) + settings._drawHold = holdPosition; + _fnDraw( settings ); + + settings._drawHold = false; } @@ -2404,22 +2439,23 @@ /** * Update the table using an Ajax call - * @param {object} oSettings dataTables settings object + * @param {object} settings dataTables settings object * @returns {boolean} Block the table drawing or not * @memberof DataTable#oApi */ - function _fnAjaxUpdate( oSettings ) + function _fnAjaxUpdate( settings ) { - if ( oSettings.bAjaxDataGet ) - { - oSettings.iDraw++; - _fnProcessingDisplay( oSettings, true ); - var iColumns = oSettings.aoColumns.length; - var aoData = _fnAjaxParameters( oSettings ); + if ( settings.bAjaxDataGet ) { + settings.iDraw++; + _fnProcessingDisplay( settings, true ); - _fnBuildAjax( oSettings, aoData, function(json) { - _fnAjaxUpdateDraw( oSettings, json ); - }, oSettings ); + _fnBuildAjax( + settings, + _fnAjaxParameters( settings ), + function(json) { + _fnAjaxUpdateDraw( settings, json ); + } + ); return false; } @@ -2624,11 +2660,12 @@ { var classes = settings.oClasses; var tableId = settings.sTableId; + var language = settings.oLanguage; var previousSearch = settings.oPreviousSearch; var features = settings.aanFeatures; var input = '<input type="search" class="'+classes.sFilterInput+'"/>'; - var str = settings.oLanguage.sSearch; + var str = language.sSearch; str = str.match(/_INPUT_/) ? str.replace('_INPUT_', input) : str+input; @@ -2659,7 +2696,8 @@ } }; var jqFilter = $('input', filter) - .val( previousSearch.sSearch.replace('"','"') ) + .val( previousSearch.sSearch ) + .attr( 'placeholder', language.sSearchPlaceholder ) .bind( 'keyup.DT search.DT input.DT paste.DT cut.DT', _fnDataSource( settings ) === 'ssp' ? @@ -2675,15 +2713,17 @@ .attr('aria-controls', tableId); // Update the input elements whenever the table is filtered - $(settings.nTable).on( 'filter.DT', function () { - // IE9 throws an 'unknown error' if document.activeElement is used - // inside an iframe or frame... - try { - if ( jqFilter[0] !== document.activeElement ) { - jqFilter.val( previousSearch.sSearch ); + $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) { + if ( settings === s ) { + // IE9 throws an 'unknown error' if document.activeElement is used + // inside an iframe or frame... + try { + if ( jqFilter[0] !== document.activeElement ) { + jqFilter.val( previousSearch.sSearch ); + } } + catch ( e ) {} } - catch ( e ) {} } ); return filter[0]; @@ -2756,15 +2796,23 @@ var displayRows = settings.aiDisplay; var row, rowIdx; - for ( var i=0, iLen=filters.length ; i<iLen ; i++ ) { - for ( var j=displayRows.length-1 ; j>=0 ; j-- ) { + for ( var i=0, ien=filters.length ; i<ien ; i++ ) { + var rows = []; + + // Loop over each row and see if it should be included + for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) { rowIdx = displayRows[ j ]; row = settings.aoData[ rowIdx ]; - if ( ! filters[i]( settings, row._aFilterData, rowIdx, row._aData ) ) { - displayRows.splice( j, 1 ); + if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) { + rows.push( rowIdx ); } } + + // So the array reference doesn't break set the results into the + // existing array + displayRows.length = 0; + displayRows.push.apply( displayRows, rows ); } } @@ -2935,22 +2983,24 @@ cellData = ''; } - // If it looks like there is an HTML entity in the string, - // attempt to decode it so sorting works as expected. Note that - // we could use a single line of jQuery to do this, but the DOM - // method used here is much faster http://jsperf.com/html-decode - if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { - __filter_div.innerHTML = cellData; - cellData = __filter_div_textContent ? - __filter_div.textContent : - __filter_div.innerText; - } + if ( cellData ) { + // If it looks like there is an HTML entity in the string, + // attempt to decode it so sorting works as expected. Note that + // we could use a single line of jQuery to do this, but the DOM + // method used here is much faster http://jsperf.com/html-decode + if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { + __filter_div.innerHTML = cellData; + cellData = __filter_div_textContent ? + __filter_div.textContent : + __filter_div.innerText; + } - if ( cellData.replace ) { - cellData = cellData.replace(/[\r\n]/g, ''); - } + if ( cellData.replace ) { + cellData = cellData.replace(/[\r\n]/g, ''); + } - filterData.push( cellData ); + filterData.push( cellData ); + } } row._aFilterData = filterData; @@ -2962,6 +3012,43 @@ return wasInvalidated; } + + /** + * Convert from the internal Hungarian notation to camelCase for external + * interaction + * @param {object} obj Object to convert + * @returns {object} Inverted object + * @memberof DataTable#oApi + */ + function _fnSearchToCamel ( obj ) + { + return { + search: obj.sSearch, + smart: obj.bSmart, + regex: obj.bRegex, + caseInsensitive: obj.bCaseInsensitive + }; + } + + + + /** + * Convert from camelCase notation to the internal Hungarian. We could use the + * Hungarian convert function here, but this is cleaner + * @param {object} obj Object to convert + * @returns {object} Inverted object + * @memberof DataTable#oApi + */ + function _fnSearchToHung ( obj ) + { + return { + sSearch: obj.search, + bSmart: obj.smart, + bRegex: obj.regex, + bCaseInsensitive: obj.caseInsensitive + }; + } + /** * Generate the node required for the info display * @param {object} oSettings dataTables settings object @@ -3205,13 +3292,12 @@ div[0].id = tableId+'_length'; } - var a = settings.oLanguage.sLengthMenu.split(/(_MENU_)/); - div.children().append( a.length > 1 ? - [ a[0], select, a[2] ] : - a[0] + div.children().append( + settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML ) ); - // Can't use `select` variable, as user might provide their own select menu + // Can't use `select` variable as user might provide their own and the + // reference is broken by the use of outerHTML $('select', div) .val( settings._iDisplayLength ) .bind( 'change.DT', function(e) { @@ -3221,7 +3307,9 @@ // Update node value whenever anything changes the table's length $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) { - $('select', div).val( len ); + if ( settings === s ) { + $('select', div).val( len ); + } } ); return div[0]; @@ -3843,8 +3931,9 @@ /* Adjust the position of the header in case we loose the y-scrollbar */ divBody.scroll(); - /* If sorting or filtering has occurred, jump the scrolling back to the top */ - if ( settings.bSorted || settings.bFiltered ) { + // If sorting or filtering has occurred, jump the scrolling back to the top + // only if we aren't holding the position + if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) { divBodyEl.scrollTop = 0; } } @@ -3944,7 +4033,8 @@ // Otherwise construct a single row 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.cloneNode( false ) ) + var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table + .empty() .css( 'visibility', 'hidden' ) .removeAttr( 'id' ) .append( $(oSettings.nTHead).clone( false ) ) @@ -4529,6 +4619,11 @@ return idx+1 >= asSorting.length ? 0 : idx+1; }; + // Convert to 2D array if needed + if ( typeof sorting[0] === 'number' ) { + sorting = settings.aaSorting = [ sorting ]; + } + // If appending the sort then we are multi-column sorting if ( append && settings.oFeatures.bSortMulti ) { // Are we already doing some kind of sort on this column? @@ -4694,28 +4789,32 @@ * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ - function _fnSaveState ( oSettings ) + function _fnSaveState ( settings ) { - if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying ) + if ( !settings.oFeatures.bStateSave || settings.bDestroying ) { return; } /* Store the interesting variables */ - var i, iLen; - var oState = { - "iCreate": +new Date(), - "iStart": oSettings._iDisplayStart, - "iLength": oSettings._iDisplayLength, - "aaSorting": $.extend( true, [], oSettings.aaSorting ), - "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ), - "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ), - "abVisCols": _pluck( oSettings.aoColumns, 'bVisible' ) + var state = { + time: +new Date(), + start: settings._iDisplayStart, + length: settings._iDisplayLength, + order: $.extend( true, [], settings.aaSorting ), + search: _fnSearchToCamel( settings.oPreviousSearch ), + columns: $.map( settings.aoColumns, function ( col, i ) { + return { + visible: col.bVisible, + search: _fnSearchToCamel( settings.aoPreSearchCols[i] ) + }; + } ) }; - _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] ); + _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] ); - oSettings.fnStateSaveCallback.call( oSettings.oInstance, oSettings, oState ); + settings.oSavedState = state; + settings.fnStateSaveCallback.call( settings.oInstance, settings, state ); } @@ -4725,63 +4824,72 @@ * @param {object} oInit DataTables init object so we can override settings * @memberof DataTable#oApi */ - function _fnLoadState ( oSettings, oInit ) + function _fnLoadState ( settings, oInit ) { var i, ien; - var columns = oSettings.aoColumns; + var columns = settings.aoColumns; - if ( ! oSettings.oFeatures.bStateSave ) { + if ( ! settings.oFeatures.bStateSave ) { return; } - var oData = oSettings.fnStateLoadCallback.call( oSettings.oInstance, oSettings ); - if ( !oData ) { + var state = settings.fnStateLoadCallback.call( settings.oInstance, settings ); + if ( ! state || ! state.time ) { return; } /* Allow custom and plug-in manipulation functions to alter the saved data set and * cancelling of loading by returning false */ - var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] ); + var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] ); if ( $.inArray( false, abStateLoad ) !== -1 ) { return; } /* Reject old data */ - var duration = oSettings.iStateDuration; - if ( duration > 0 && oData.iCreate < +new Date() - (duration*1000) ) { + var duration = settings.iStateDuration; + if ( duration > 0 && state.time < +new Date() - (duration*1000) ) { return; } // Number of columns have changed - all bets are off, no restore of settings - if ( columns.length !== oData.aoSearchCols.length ) { + if ( columns.length !== state.columns.length ) { return; } - /* Store the saved state so it might be accessed at any time */ - oSettings.oLoadedState = $.extend( true, {}, oData ); + // Store the saved state so it might be accessed at any time + settings.oLoadedState = $.extend( true, {}, state ); + + // Restore key features - todo - for 1.11 this needs to be done by + // subscribed events + settings._iDisplayStart = state.start; + settings.iInitDisplayStart = state.start; + settings._iDisplayLength = state.length; + settings.aaSorting = []; - /* Restore key features */ - oSettings._iDisplayStart = oData.iStart; - oSettings.iInitDisplayStart = oData.iStart; - oSettings._iDisplayLength = oData.iLength; - oSettings.aaSorting = $.map( oData.aaSorting, function ( col, i ) { - return col[0] >= columns.length ? + // Order + $.each( state.order, function ( i, col ) { + settings.aaSorting.push( col[0] >= columns.length ? [ 0, col[1] ] : - col; + col + ); } ); - /* Search filtering */ - $.extend( oSettings.oPreviousSearch, oData.oSearch ); - $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols ); + // Search + $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) ); + + // Columns + for ( i=0, ien=state.columns.length ; i<ien ; i++ ) { + var col = state.columns[i]; - /* Column visibility state */ - var visColumns = oData.abVisCols; - for ( i=0, ien=visColumns.length ; i<ien ; i++ ) { - columns[i].bVisible = visColumns[i]; + // Visibility + columns[i].bVisible = col.visible; + + // Search + $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) ); } - _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] ); + _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] ); } @@ -4979,7 +5087,7 @@ * trigger * @memberof DataTable#oApi */ - function _fnCallbackFire( settings, callbackArr, event, args ) + function _fnCallbackFire( settings, callbackArr, e, args ) { var ret = []; @@ -4989,8 +5097,8 @@ } ); } - if ( event !== null ) { - $(settings.nTable).trigger( event+'.dt', args ); + if ( e !== null ) { + $(settings.nTable).trigger( e+'.dt', args ); } return ret; @@ -6470,7 +6578,7 @@ * // Initialisation as a constructor * var api = new $.fn.DataTable.Api( 'table.dataTable' ); */ - DataTable.Api = _Api = function ( context, data ) + _Api = function ( context, data ) { if ( ! this instanceof _Api ) { throw 'DT API must be constructed as a new object'; @@ -6513,6 +6621,7 @@ _Api.extend( this, this, __apiStruct ); }; + DataTable.Api = _Api; _Api.prototype = /** @lends DataTables.Api */{ /** @@ -6535,16 +6644,8 @@ each: function ( fn ) { - if ( __arrayProto.forEach ) { - // Where possible, use the built-in forEach - __arrayProto.forEach.call( this, fn, this ); - } - else { - // Compatibility for browsers without EMCA-252-5 (JS 1.6) - for ( var i=0, ien=this.length ; i<ien; i++ ) { - // In strict mode the execution scope is the passed value - fn.call( this, this[i], i, this ); - } + for ( var i=0, ien=this.length ; i<ien; i++ ) { + fn.call( this, this[i], i, this ); } return this; @@ -6780,7 +6881,7 @@ i, ien, j, jen, struct, inner, - methodScoping = function ( fn, struc ) { + methodScoping = function ( scope, fn, struc ) { return function () { var ret = fn.apply( scope, arguments ); @@ -6795,7 +6896,7 @@ // Value obj[ struct.name ] = typeof struct.val === 'function' ? - methodScoping( struct.val, struct ) : + methodScoping( scope, struct.val, struct ) : $.isPlainObject( struct.val ) ? {} : struct.val; @@ -6891,11 +6992,6 @@ src.propExt; } } - - // Rebuild the API with the new construct - if ( _Api.ready ) { - DataTable.api.build(); - } }; @@ -7016,6 +7112,13 @@ } ); + _api_registerPlural( 'tables().containers()', 'table().container()' , function () { + return this.iterator( 'table', function ( ctx ) { + return ctx.nTableWrapper; + } ); + } ); + + /** * Redraw the tables in the current context. @@ -7398,7 +7501,7 @@ tmp = $.inArray( i, displayFiltered ); if ((tmp === -1 && search == 'removed') || - (tmp === 1 && search == 'applied') ) + (tmp >= 0 && search == 'applied') ) { a.push( i ); } @@ -7659,7 +7762,7 @@ } else { // Otherwise create a row with a wrapper - var created = $('<tr><td/></tr>'); + var created = $('<tr><td/></tr>').addClass( k ); $('td', created) .addClass( k ) .html( r ) @@ -7691,26 +7794,42 @@ }; - var __details_display = function ( show ) { - var ctx = this.context; + var __details_remove = function ( api ) + { + var ctx = api.context; - if ( ctx.length && this.length ) { - var row = ctx[0].aoData[ this[0] ]; + if ( ctx.length && api.length ) { + var row = ctx[0].aoData[ api[0] ]; + + if ( row._details ) { + row._details.remove(); + + row._detailsShow = undefined; + row._details = undefined; + } + } + }; + + + var __details_display = function ( api, show ) { + var ctx = api.context; + + if ( ctx.length && api.length ) { + var row = ctx[0].aoData[ api[0] ]; if ( row._details ) { row._detailsShow = show; + if ( show ) { row._details.insertAfter( row.nTr ); } else { - row._details.remove(); + row._details.detach(); } __details_events( ctx[0] ); } } - - return this; }; @@ -7720,15 +7839,21 @@ var namespace = '.dt.DT_details'; var drawEvent = 'draw'+namespace; var colvisEvent = 'column-visibility'+namespace; + var destroyEvent = 'destroy'+namespace; + var data = settings.aoData; - api.off( drawEvent +' '+ colvisEvent ); + api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent ); - if ( _pluck( settings.aoData, '_details' ).length > 0 ) { + if ( _pluck( data, '_details' ).length > 0 ) { // On each draw, insert the required elements into the document - api.on( drawEvent, function () { + api.on( drawEvent, function ( e, ctx ) { + if ( settings !== ctx ) { + return; + } + api.rows( {page:'current'} ).eq(0).each( function (idx) { // Internal data grab - var row = settings.aoData[ idx ]; + var row = data[ idx ]; if ( row._detailsShow ) { row._details.insertAfter( row.nTr ); @@ -7737,27 +7862,49 @@ } ); // Column visibility change - update the colspan - api.on( colvisEvent, function ( e, settings, idx, vis ) { + api.on( colvisEvent, function ( e, ctx, idx, vis ) { + if ( settings !== ctx ) { + return; + } + // Update the colspan for the details rows (note, only if it already has // a colspan) - var row, visible = _fnVisbleColumns( settings ); + var row, visible = _fnVisbleColumns( ctx ); - for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { - row = settings.aoData[i]; + for ( var i=0, ien=data.length ; i<ien ; i++ ) { + row = data[i]; if ( row._details ) { row._details.children('td[colspan]').attr('colspan', visible ); } } } ); + + // Table destroyed - nuke any child rows + api.on( destroyEvent, function ( e, ctx ) { + if ( settings !== ctx ) { + return; + } + + for ( var i=0, ien=data.length ; i<ien ; i++ ) { + if ( data[i]._details ) { + __details_remove( data[i] ); + } + } + } ); } }; + // Strings for the method names to help minification + var _emp = ''; + var _child_obj = _emp+'row().child'; + var _child_mth = _child_obj+'()'; + // data can be: // tr // string // jQuery or array of any of the above - _api_register( 'row().child()', function ( data, klass ) { + _api_register( _child_mth, function ( data, klass ) { var ctx = this.context; if ( data === undefined ) { @@ -7766,6 +7913,14 @@ ctx[0].aoData[ this[0] ]._details : undefined; } + else if ( data === true ) { + // show + this.child.show(); + } + else if ( data === false ) { + // remove + __details_remove( this ); + } else if ( ctx.length && this.length ) { // set __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass ); @@ -7774,23 +7929,35 @@ return this; } ); + _api_register( [ - 'row().child.show()', - 'row().child().show()' - ], function () { - __details_display.call( this, true ); + _child_obj+'.show()', + _child_mth+'.show()' // only when `child()` was called with parameters (without + ], function ( show ) { // it returns an object and this method is not executed) + __details_display( this, true ); return this; } ); + _api_register( [ - 'row().child.hide()', - 'row().child().hide()' - ], function () { - __details_display.call( this, false ); + _child_obj+'.hide()', + _child_mth+'.hide()' // only when `child()` was called with parameters (without + ], function () { // it returns an object and this method is not executed) + __details_display( this, false ); return this; } ); - _api_register( 'row().child.isShown()', function () { + + _api_register( [ + _child_obj+'.remove()', + _child_mth+'.remove()' // only when `child()` was called with parameters (without + ], function () { // it returns an object and this method is not executed) + __details_remove( this ); + return this; + } ); + + + _api_register( _child_obj+'.isShown()', function () { var ctx = this.context; if ( ctx.length && this.length ) { @@ -7920,12 +8087,6 @@ else { // Remove column $( _pluck( settings.aoData, 'anCells', column ) ).detach(); - - col.bVisible = false; - _fnDrawHead( settings, settings.aoHeader ); - _fnDrawHead( settings, settings.aoFooter ); - - _fnSaveState( settings ); } // Common actions @@ -8097,7 +8258,7 @@ var a, i, ien, j; return _selector_run( selector, function ( s ) { - if ( ! s ) { + if ( s === null || s === undefined ) { // All cells a = []; @@ -8139,8 +8300,8 @@ _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) { // Argument shifting if ( $.isPlainObject( rowSelector ) ) { - // If passing in a cell index - if ( rowSelector.row ) { + // Indexes + if ( typeof rowSelector.row !== undefined ) { opts = columnSelector; columnSelector = null; } @@ -8414,6 +8575,38 @@ } ); } ); + /* + * State API methods + */ + + _api_register( 'state()', function () { + return this.context.length ? + this.context[0].oSavedState : + null; + } ); + + + _api_register( 'state.clear()', function () { + return this.iterator( 'table', function ( settings ) { + // Save an empty object + settings.fnStateSaveCallback.call( settings.oInstance, settings, {} ); + } ); + } ); + + + _api_register( 'state.loaded()', function () { + return this.context.length ? + this.context[0].oLoadedState : + null; + } ); + + + _api_register( 'state.save()', function () { + return this.iterator( 'table', function ( settings ) { + _fnSaveState( settings ); + } ); + } ); + /** @@ -8548,7 +8741,7 @@ var args = Array.prototype.slice.call(arguments); // Add the `dt` namespace automatically if it isn't already present - if ( args[0].indexOf( '.dt' ) === -1 ) { + if ( ! args[0].match(/\.dt\b/) ) { args[0] += '.dt'; } @@ -8689,7 +8882,7 @@ * @type string * @default Version number */ - DataTable.version = "1.10.0"; + DataTable.version = "1.10.1"; /** * Private data store, containing all of the settings objects that are @@ -10953,6 +11146,17 @@ /** + * Assign a `placeholder` attribute to the search `input` element + * @type string + * @default + * + * @dtopt Language + * @name DataTable.defaults.language.searchPlaceholder + */ + "sSearchPlaceholder": "", + + + /** * All of the language information can be stored in a file on the * server-side, which DataTables will look up if this parameter is passed. * It must store the URL of the language file, which is in a JSON format, @@ -12681,6 +12885,13 @@ "aoStateLoad": [], /** + * State that was saved. Useful for back reference + * @type object + * @default null + */ + "oSavedState": null, + + /** * State that was loaded. Useful for back reference * @type object * @default null @@ -13752,17 +13963,23 @@ } }; - // Because this approach is destroying and recreating the paging - // elements, focus is lost on the select button which is bad for - // accessibility. So we want to restore focus once the draw has - // completed - var activeEl = $(document.activeElement).data('dt-idx'); + // IE9 throws an 'unknown error' if document.activeElement is used + // inside an iframe or frame. Try / catch the error. Not good for + // accessibility, but neither are frames. + try { + // Because this approach is destroying and recreating the paging + // elements, focus is lost on the select button which is bad for + // accessibility. So we want to restore focus once the draw has + // completed + var activeEl = $(document.activeElement).data('dt-idx'); - attach( $(host).empty(), buttons ); + attach( $(host).empty(), buttons ); - if ( activeEl !== null ) { - $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); + if ( activeEl !== null ) { + $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); + } } + catch (e) {} } } } ); @@ -13837,7 +14054,7 @@ // html "html-pre": function ( a ) { - return ! a ? + return _empty(a) ? '' : a.replace ? a.replace( /<.*?>/g, "" ).toLowerCase() : @@ -13846,11 +14063,15 @@ // string "string-pre": function ( a ) { - return typeof a === 'string' ? - a.toLowerCase() : - ! a || ! a.toString ? - '' : - a.toString(); + // This is a little complex, but faster than always calling toString, + // http://jsperf.com/tostring-v-check + return _empty(a) ? + '' : + typeof a === 'string' ? + a.toLowerCase() : + ! a.toString ? + '' : + a.toString(); }, // string-asc and -desc are retained only for compatibility with the old @@ -13883,10 +14104,10 @@ // Dates (only those recognised by the browser's Date.parse) function ( d, settings ) { - // V8 will remove any unknown characters at the start of the expression, - // leading to false matches such as `$245.12` being a valid date. See - // forum thread 18941 for detail. - if ( d && ! _re_date_start.test(d) ) { + // V8 will remove any unknown characters at the start and end of the + // expression, leading to false matches such as `$245.12` or `10%` being + // a valid date. See forum thread 18941 for detail. + if ( d && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) { return null; } var parsed = Date.parse(d); @@ -13931,7 +14152,7 @@ $.extend( DataTable.ext.type.search, { html: function ( data ) { return _empty(data) ? - '' : + data : typeof data === 'string' ? data .replace( _re_new_lines, " " ) @@ -13941,7 +14162,7 @@ string: function ( data ) { return _empty(data) ? - '' : + data : typeof data === 'string' ? data.replace( _re_new_lines, " " ) : data; @@ -13958,7 +14179,11 @@ // `DT` namespace will allow the event to be removed automatically // on destroy, while the `dt` namespaced event is the one we are // listening for - $(settings.nTable).on( 'order.dt.DT', function ( e, settings, sorting, columns ) { + $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { + if ( settings !== ctx ) { // need to check this this is the host + return; // table, not a nested one + } + var colIdx = column.idx; cell @@ -13987,7 +14212,11 @@ .appendTo( cell ); // Attach a sort listener to update on sort - $(settings.nTable).on( 'order.dt.DT', function ( e, settings, sorting, columns ) { + $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { + if ( settings !== ctx ) { + return; + } + cell .removeClass( classes.sSortAsc +" "+classes.sSortDesc ) .addClass( columns[ colIdx ] == 'asc' ? @@ -14049,13 +14278,15 @@ number: function ( thousands, decimal, precision, prefix ) { return { display: function ( d ) { - d = parseFloat( d ); + var negative = d < 0 ? '-' : ''; + d = Math.abs( parseFloat( d ) ); + var intPart = parseInt( d, 10 ); var floatPart = precision ? - (decimal+(d - intPart).toFixed( precision )).substring( 2 ): + decimal+(d - intPart).toFixed( precision ).substring( 2 ): ''; - return (prefix||'') + + return negative + (prefix||'') + intPart.toString().replace( /\B(?=(\d{3})+(?!\d))/g, thousands ) + |
