// namespaces
var dwv = dwv || {};
dwv.ctrl = dwv.ctrl || {};
/**
* Load controller.
*
* @param {string} defaultCharacterSet The default character set.
* @class
*/
dwv.ctrl.LoadController = function (defaultCharacterSet) {
// closure to self
var self = this;
// current loaders
var currentLoaders = {};
// load counter
var counter = -1;
/**
* Get the next load id.
*
* @returns {number} The next id.
*/
function getNextLoadId() {
++counter;
return counter;
}
/**
* Load a list of files. Can be image files or a state file.
*
* @param {Array} files The list of files to load.
* @param {object} options The options object, can contain:
* - timepoint: an object with time information
*/
this.loadFiles = function (files, options) {
// has been checked for emptiness.
var ext = files[0].name.split('.').pop().toLowerCase();
if (ext === 'json') {
loadStateFile(files[0], options);
} else {
loadImageFiles(files, options);
}
};
/**
* Load a list of URLs. Can be image files or a state file.
*
* @param {Array} urls The list of urls to load.
* @param {object} options The load options:
* - requestHeaders: an array of {name, value} to use as request headers.
* - withCredentials: credentials flag to pass to the request.
*/
this.loadURLs = function (urls, options) {
// has been checked for emptiness.
var ext = urls[0].split('.').pop().toLowerCase();
if (ext === 'json') {
loadStateUrl(urls[0], options);
} else {
loadImageUrls(urls, options);
}
};
/**
* Load a list of ArrayBuffers.
*
* @param {Array} data The list of ArrayBuffers to load
* in the form of [{name: "", filename: "", data: data}].
*/
this.loadImageObject = function (data) {
// create IO
var memoryIO = new dwv.io.MemoryLoader();
// load data
loadData(data, memoryIO, 'image');
};
/**
* Abort the current loaders.
*/
this.abort = function () {
var keys = Object.keys(currentLoaders);
for (var i = 0; i < keys.length; ++i) {
currentLoaders[i].loader.abort();
delete currentLoaders[i];
}
};
// private ----------------------------------------------------------------
/**
* Load a list of image files.
*
* @param {Array} files The list of image files to load.
* @param {object} options The options object, can contain:
* - timepoint: an object with time information
* @private
*/
function loadImageFiles(files, options) {
// create IO
var fileIO = new dwv.io.FilesLoader();
fileIO.setDefaultCharacterSet(defaultCharacterSet);
// load data
loadData(files, fileIO, 'image', options);
}
/**
* Load a list of image URLs.
*
* @param {Array} urls The list of urls to load.
* @param {object} options The load options:
* - requestHeaders: an array of {name, value} to use as request headers.
* - withCredentials: credentials flag to pass to the request.
* @private
*/
function loadImageUrls(urls, options) {
// create IO
var urlIO = new dwv.io.UrlsLoader();
urlIO.setDefaultCharacterSet(defaultCharacterSet);
// load data
loadData(urls, urlIO, 'image', options);
}
/**
* Load a State file.
*
* @param {string} file The state file to load.
* @param {object} options The options object.
* @private
*/
function loadStateFile(file, options) {
// create IO
var fileIO = new dwv.io.FilesLoader();
// load data
loadData([file], fileIO, 'state', options);
}
/**
* Load a State url.
*
* @param {string} url The state url to load.
* @param {object} options The load options:
* - requestHeaders: an array of {name, value} to use as request headers.
* - withCredentials: credentials flag to pass to the request.
* @private
*/
function loadStateUrl(url, options) {
// create IO
var urlIO = new dwv.io.UrlsLoader();
// load data
loadData([url], urlIO, 'state', options);
}
/**
* Load a list of data.
*
* @param {Array} data Array of data to load.
* @param {object} loader The data loader.
* @param {string} loadType The data load type: 'image' or 'state'.
* @param {object} options Options passed to the final loader.
* @private
*/
function loadData(data, loader, loadType, options) {
var eventInfo = {
loadtype: loadType,
};
// check if timepoint
var hasTimepoint = false;
if (typeof options !== 'undefined' &&
typeof options.timepoint !== 'undefined') {
hasTimepoint = true;
}
var loadId = null;
if (hasTimepoint) {
loadId = options.timepoint.dataId;
eventInfo.timepoint = options.timepoint;
} else {
loadId = getNextLoadId();
}
eventInfo.loadid = loadId;
// set callbacks
loader.onloadstart = function (event) {
// store loader to allow abort
currentLoaders[loadId] = {
loader: loader,
isFirstItem: true
};
// callback
augmentCallbackEvent(self.onloadstart, eventInfo)(event);
};
loader.onprogress = augmentCallbackEvent(self.onprogress, eventInfo);
loader.onloaditem = function (event) {
var isFirstItem = currentLoaders[loadId].isFirstItem;
var eventInfoItem = {
loadtype: loadType,
loadid: loadId,
isfirstitem: isFirstItem
};
if (hasTimepoint) {
eventInfoItem.timepoint = options.timepoint;
}
augmentCallbackEvent(self.onloaditem, eventInfoItem)(event);
if (isFirstItem) {
currentLoaders[loadId].isFirstItem = false;
}
};
loader.onload = augmentCallbackEvent(self.onload, eventInfo);
loader.onloadend = function (event) {
// reset current loader
delete currentLoaders[loadId];
// callback
augmentCallbackEvent(self.onloadend, eventInfo)(event);
};
loader.onerror = augmentCallbackEvent(self.onerror, eventInfo);
loader.onabort = augmentCallbackEvent(self.onabort, eventInfo);
// launch load
try {
loader.load(data, options);
} catch (error) {
self.onerror({
error: error,
loadId: loadId
});
self.onloadend({
loadId: loadId
});
return;
}
}
/**
* Augment a callback event: adds loadtype to the event
* passed to a callback.
*
* @param {object} callback The callback to update.
* @param {object} info Info object to append to the event.
* @returns {object} A function representing the modified callback.
*/
function augmentCallbackEvent(callback, info) {
return function (event) {
var keys = Object.keys(info);
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
event[key] = info[key];
}
callback(event);
};
}
}; // class LoadController
/**
* Handle a load start event.
* Default does nothing.
*
* @param {object} _event The load start event.
*/
dwv.ctrl.LoadController.prototype.onloadstart = function (_event) {};
/**
* Handle a load progress event.
* Default does nothing.
*
* @param {object} _event The progress event.
*/
dwv.ctrl.LoadController.prototype.onprogress = function (_event) {};
/**
* Handle a load event.
* Default does nothing.
*
* @param {object} _event The load event fired
* when a file has been loaded successfully.
*/
dwv.ctrl.LoadController.prototype.onload = function (_event) {};
/**
* Handle a load end event.
* Default does nothing.
*
* @param {object} _event The load end event fired
* when a file load has completed, successfully or not.
*/
dwv.ctrl.LoadController.prototype.onloadend = function (_event) {};
/**
* Handle an error event.
* Default does nothing.
*
* @param {object} _event The error event.
*/
dwv.ctrl.LoadController.prototype.onerror = function (_event) {};
/**
* Handle an abort event.
* Default does nothing.
*
* @param {object} _event The abort event.
*/
dwv.ctrl.LoadController.prototype.onabort = function (_event) {};