mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
184 lines
7.8 KiB
JavaScript
184 lines
7.8 KiB
JavaScript
/*
|
|
TODO:
|
|
?? superclass dataloader, subclass lazydataloader??
|
|
|
|
*/
|
|
//==============================================================================
|
|
/**
|
|
* Object to progressively load JSON data from a REST url, delaying some time between loading chunks
|
|
*
|
|
* Data from ajax loading is aggregated in a list, with one element for each ajax response.
|
|
* It's up to the calling code to combine the results in a meaningful, correct way
|
|
*
|
|
* example:
|
|
* var loader = new scatterplot.LazyDataLoader({
|
|
* //logger : console,
|
|
* url : ( apiDatasetsURL + '/' + hda.id + '?data_type=raw_data'
|
|
* + '&columns=[10,14]' ),
|
|
* total : hda.metadata_data_lines,
|
|
* size : 500,
|
|
*
|
|
* initialize : function( config ){
|
|
* // ... do some stuff
|
|
* },
|
|
*
|
|
* buildUrl : function( start, size ){
|
|
* // change the formation of start, size in query string
|
|
* return loader.url + '&' + jQuery.param({
|
|
* start_val: start,
|
|
* max_vals: size
|
|
* });
|
|
* },
|
|
*
|
|
* loadedPartialEvent : 'loader.partial',
|
|
* loadedAllEvent : 'loader.all',
|
|
* });
|
|
* $( loader ).bind( 'loader.partial', function( event, data ){
|
|
* console.info( 'partial load complete:', event, data );
|
|
* // ... do stuff with new data
|
|
* });
|
|
* $( loader ).bind( 'loader.all', function( event, data ){
|
|
* console.info( 'final load complete:', event, data );
|
|
* // ... do stuff with all data
|
|
* });
|
|
*
|
|
* loader.load( function( dataArray ){ console.debug( 'FINISHED!', x, y, z ); } );
|
|
*/
|
|
function LazyDataLoader( config ){
|
|
// for now assume:
|
|
// get, async, and params sent via url query string
|
|
// we want json
|
|
// we know the size of the data on the server beforehand
|
|
var loader = this;
|
|
|
|
jQuery.extend( loader, LoggableMixin );
|
|
jQuery.extend( loader, {
|
|
|
|
//NOTE: the next two need to be sent in config (required)
|
|
// total size of data on server
|
|
total : undefined,
|
|
// url of service to get the data
|
|
url : undefined,
|
|
|
|
// holds the interval id for the current load delay
|
|
currentIntervalId : undefined,
|
|
|
|
// optional events to trigger when partial, last data are loaded
|
|
// loadedPartialEvent will be sent: the ajax response data, start value, and size
|
|
loadedPartialEvent : undefined,
|
|
// loadedAllEvent will be sent: the final loader's data array and the total
|
|
loadedAllEvent : undefined,
|
|
|
|
// each load call will add an element to this array
|
|
// it's the responsibility of the code using this to combine them properly
|
|
data : [],
|
|
// ms btwn recursive loads
|
|
delay : 500,
|
|
// starting line, element, whatever
|
|
start : 0,
|
|
// size to fetch per load
|
|
size : 1000,
|
|
|
|
// loader init func: extends loader with config and calls config.init if there
|
|
//@param {object} config : object containing variables to override (or additional)
|
|
initialize : function( config ){
|
|
jQuery.extend( loader, config );
|
|
|
|
// call the custom initialize function if any
|
|
// only dangerous if the user tries LazyDataLoader.prototype.init
|
|
if( config.hasOwnProperty( 'initialize' ) ){
|
|
config.initialize.call( loader, config );
|
|
}
|
|
|
|
// ensure necessary stuff
|
|
if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); }
|
|
if( !loader.url ){ throw( loader + ' requires a url' ); }
|
|
|
|
this.log( this + ' initialized:', loader );
|
|
},
|
|
|
|
// returns query string formatted start and size (for the next fetch) appended to the loader.url
|
|
//OVERRIDE: to change how params are passed, param names, etc.
|
|
//@param {int} start : the line/row/datum indicating where in the dataset the next load begins
|
|
//@param {int} size : the number of lines/rows/data to get on the next load
|
|
buildUrl : function( start, size ){
|
|
// currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
|
|
return loader.url + '&' + jQuery.param({
|
|
start_val: start,
|
|
max_vals: size
|
|
});
|
|
},
|
|
|
|
//OVERRIDE: to handle ajax errors differently
|
|
ajaxErrorFn : function( xhr, status, error ){
|
|
alert( loader + ' ERROR:' + status + '\n' + error );
|
|
},
|
|
|
|
// interface to begin load (and first recursive call)
|
|
//@param {Function} callback : function to execute when all data is loaded. callback is passed loader.data
|
|
load : function( callback ){
|
|
|
|
// subsequent recursive calls
|
|
function loadHelper( start, size ){
|
|
loader.log( loader + '.loadHelper, start:', start, 'size:', size );
|
|
var url = loader.buildUrl( start, size );
|
|
loader.log( '\t url:', url );
|
|
|
|
jQuery.ajax({
|
|
url : loader.buildUrl( start, size ),
|
|
dataType : 'json',
|
|
error : function( xhr, status, error ){
|
|
loader.log( '\t ajax error, status:', status, 'error:', error );
|
|
if( loader.currentIntervalId ){
|
|
clearInterval( loader.currentIntervalId );
|
|
}
|
|
loader.ajaxErrorFn( xhr, status, error );
|
|
},
|
|
|
|
success : function( response ){
|
|
var next = start + size,
|
|
remainder = Math.min( loader.total - next, loader.size );
|
|
loader.log( '\t ajax success, next:', next, 'remainder:', remainder );
|
|
|
|
// store the response as is in a new element
|
|
//TODO:?? store start, size as well?
|
|
loader.data.push( response );
|
|
|
|
// fire the partial load event
|
|
if( loader.loadedPartialEvent ){
|
|
loader.log( '\t firing:', loader.loadedPartialEvent );
|
|
$( loader ).trigger( loader.loadedPartialEvent, response, start, size );
|
|
}
|
|
|
|
// if we haven't gotten everything yet,
|
|
// set up for next recursive call and set the timer
|
|
if( remainder > 0 ){
|
|
loader.currentIntervalId = setTimeout(
|
|
function(){ loadHelper( next, remainder ); },
|
|
loader.delay
|
|
);
|
|
loader.log( '\t currentIntervalId:', loader.currentIntervalId );
|
|
|
|
// otherwise (base-case), don't do anything
|
|
} else {
|
|
loader.log( loader + '.loadHelper, has finished:', loader.data );
|
|
if( loader.loadedAllEvent ){
|
|
loader.log( '\t firing:', loader.loadedAllEvent );
|
|
$( loader ).trigger( loader.loadedAllEvent, loader.data, loader.total );
|
|
}
|
|
if( callback ){ callback( loader.data ); }
|
|
}
|
|
}
|
|
});
|
|
}
|
|
loadHelper( loader.start, Math.min( loader.total, loader.size ) );
|
|
},
|
|
|
|
toString : function(){ return 'LazyDataLoader'; }
|
|
});
|
|
|
|
loader.initialize( config );
|
|
return loader;
|
|
}
|
|
|