Here's the entire script for anyone interested - obviously it's called by another script so a bunch of the specifics are refactored out. Hope it's useful.
/*Paginated table builder via datatables.net
HAS: configured URL against the overlay layer, 1=1 where clause, specific out fields
initial loading gif to accompany "Processing...", which doesn't really cover the initial load
*/
function loadtable(overlayLayerUrl,lyrOutFields,sortableFields,sortColumn,displayStart,pageLength,totalOverlayFeatureCount){
var colArr = lyrOutFields.split(','); //pull the individual columns out of the lyrOutFields to build a custom column object
var columnsObj = [];
$(colArr).each(function(i){
if ($.inArray(colArr[i],sortableFields) !== -1) {
columnsObj.push({ 'data': 'attributes.'+colArr[i],'orderable':true }); //set the column to sortable
} else {
columnsObj.push({ 'data': 'attributes.'+colArr[i],'orderable':false }); //set the column to unsortable
}
});
//build the AJAX URL - could probably get by with less params
var tableURL = overlayLayerUrl+"/query?where=1%3D1&text=&objectIds=&time=&geometry=";
tableURL += "&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=";
tableURL += "&returnGeometry=false&returnTrueCurves=false&maxAllowableOffset=&outFields="+lyrOutFields;
tableURL += "&geometryPrecision=&outSR=&having=&returnIdsOnly=false"
tableURL += "&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&historicMoment=";
tableURL += "&returnDistinctValues=false&queryByDistance=&returnExtentOnly=false";
tableURL += "&datumTransformation=¶meterValues=&rangeValues=&quantizationParameters=&featureEncoding=";
tableURL += "esriDefault&f=json";
$('#tableSpace').DataTable({
destroy: true, // delete and recreate table for sorting purposes
order: sortColumn, //initial sort column
searching: false,
serverSide: true, //false would allow for nice native sorting but limited to the REST endpoint's default record count
processing: true,
displayStart: displayStart, // set the page the user is on
pageLength: pageLength, // set how many records to show
ajax: {
url: tableURL,
type: 'get',
format: 'json',
dataSrc: function(json) { // grabbing the data we want to display, also setting some params datatables uses for pagination
json.recordsTotal = totalOverlayFeatureCount; //set from the initial AJAX request for queryFeatureCount
json.recordsFiltered = totalOverlayFeatureCount;
return json.features;
},
data: function(d) { // this is where datatables add url params for server-side processing
d.resultOffset = d.start;
d.resultRecordCount = d.length;
//reference the request against the column array to customize the sort
d.orderByFields = colArr[d.order[0].column] +" "+ d.order[0].dir;
return d;
}
},
columns: columnsObj,
initComplete: function(settings, json) {
//show HTML content after load
$("#tableSpace").css("display","block");
$('#tableThrobber').hide();
//make the page length drop down more compliant with WCAG for select
//take the select element and place it after the label element
$('#tableSpace_length').find('select').each(function () {
$(this).parent().after(this);
$(this).attr('id', 'datatable_lengthSelect');
});
//change the HTML of the label to be more compliant
$('#tableSpace_length').children('label').html("Select number of records per page: ")
$('#tableSpace_length').children('label').attr('for','datatable_lengthSelect')
}
});//end datatables function
}