2014-05-05 06:11:50 +04:00
|
|
|
/*
|
|
|
|
* OpenSeadragon - ImageLoader
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 CodePlex Foundation
|
2022-06-28 15:11:02 +03:00
|
|
|
* Copyright (C) 2010-2022 OpenSeadragon contributors
|
2014-11-06 01:48:37 +03:00
|
|
|
|
2014-05-05 06:11:50 +04:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* - Neither the name of CodePlex Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
(function($){
|
2014-05-05 06:11:50 +04:00
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
/**
|
|
|
|
* @class ImageJob
|
|
|
|
* @classdesc Handles downloading of a single image.
|
|
|
|
* @param {Object} options - Options for this ImageJob.
|
|
|
|
* @param {String} [options.src] - URL of image to download.
|
2022-06-07 15:53:18 +03:00
|
|
|
* @param {Tile} [options.tile] - Tile that belongs the data to.
|
2022-04-16 22:19:54 +03:00
|
|
|
* @param {TileSource} [options.source] - Image loading strategy
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {String} [options.loadWithAjax] - Whether to load this image with AJAX.
|
2016-11-08 20:27:30 +03:00
|
|
|
* @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX.
|
2022-06-07 15:53:18 +03:00
|
|
|
* @param {Boolean} [options.ajaxWithCredentials] - Whether to set withCredentials on AJAX requests.
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {String} [options.crossOriginPolicy] - CORS policy to use for downloads
|
2022-03-23 12:22:13 +03:00
|
|
|
* @param {String} [options.postData] - HTTP POST data (usually but not necessarily in k=v&k2=v2... form,
|
2022-05-04 16:16:13 +03:00
|
|
|
* see TileSource::getPostData) or null
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {Function} [options.callback] - Called once image has been downloaded.
|
|
|
|
* @param {Function} [options.abort] - Called when this image job is aborted.
|
2017-05-12 07:36:27 +03:00
|
|
|
* @param {Number} [options.timeout] - The max number of milliseconds that this image job may take to complete.
|
2016-10-22 00:28:12 +03:00
|
|
|
*/
|
2022-04-30 00:45:01 +03:00
|
|
|
$.ImageJob = function(options) {
|
2014-11-06 01:48:37 +03:00
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
$.extend(true, this, {
|
|
|
|
timeout: $.DEFAULT_SETTINGS.timeout,
|
|
|
|
jobId: null
|
|
|
|
}, options);
|
2014-11-06 01:48:37 +03:00
|
|
|
|
2014-05-05 06:11:50 +04:00
|
|
|
/**
|
2022-04-29 19:41:43 +03:00
|
|
|
* Data object which will contain downloaded image data.
|
|
|
|
* @member {Image|*} image data object, by default an Image object (depends on TileSource)
|
2014-05-05 06:11:50 +04:00
|
|
|
* @memberof OpenSeadragon.ImageJob#
|
|
|
|
*/
|
2022-04-29 19:41:43 +03:00
|
|
|
this.data = null;
|
2014-05-05 06:11:50 +04:00
|
|
|
|
2022-04-30 00:45:01 +03:00
|
|
|
/**
|
|
|
|
* User workspace to populate with helper variables
|
2022-05-04 16:16:13 +03:00
|
|
|
* @member {*} userData to append custom data and avoid namespace collision
|
2022-04-30 00:45:01 +03:00
|
|
|
* @memberof OpenSeadragon.ImageJob#
|
|
|
|
*/
|
|
|
|
this.userData = {};
|
2022-05-04 16:16:13 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Error message holder
|
|
|
|
* @member {string} error message
|
|
|
|
* @memberof OpenSeadragon.ImageJob#
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this.errorMsg = null;
|
2022-04-30 00:45:01 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
$.ImageJob.prototype = {
|
2016-10-22 00:28:12 +03:00
|
|
|
/**
|
|
|
|
* Starts the image job.
|
|
|
|
* @method
|
|
|
|
*/
|
2022-04-16 22:19:54 +03:00
|
|
|
start: function() {
|
2016-10-22 00:28:12 +03:00
|
|
|
var self = this;
|
|
|
|
var selfAbort = this.abort;
|
2014-05-05 06:11:50 +04:00
|
|
|
|
2022-04-16 22:19:54 +03:00
|
|
|
this.jobId = window.setTimeout(function () {
|
2022-06-07 15:53:18 +03:00
|
|
|
self.finish(null, null, "Image load exceeded timeout (" + self.timeout + " ms)");
|
2014-05-05 06:11:50 +04:00
|
|
|
}, this.timeout);
|
|
|
|
|
2022-04-16 22:19:54 +03:00
|
|
|
this.abort = function() {
|
2022-04-29 19:41:43 +03:00
|
|
|
self.source.downloadTileAbort(self);
|
2022-04-16 22:19:54 +03:00
|
|
|
if (typeof selfAbort === "function") {
|
|
|
|
selfAbort();
|
2016-10-22 00:28:12 +03:00
|
|
|
}
|
2022-04-16 22:19:54 +03:00
|
|
|
};
|
2016-10-22 00:28:12 +03:00
|
|
|
|
2022-04-16 22:19:54 +03:00
|
|
|
this.source.downloadTileStart(this);
|
2014-05-05 06:11:50 +04:00
|
|
|
},
|
|
|
|
|
2022-05-04 16:16:13 +03:00
|
|
|
/**
|
|
|
|
* Finish this job.
|
|
|
|
* @param {*} data data that has been downloaded
|
|
|
|
* @param {XMLHttpRequest} request reference to the request if used
|
|
|
|
* @param {string} errorMessage description upon failure
|
|
|
|
*/
|
|
|
|
finish: function(data, request, errorMessage ) {
|
|
|
|
this.data = data;
|
|
|
|
this.request = request;
|
2022-04-16 22:19:54 +03:00
|
|
|
this.errorMsg = errorMessage;
|
2014-05-05 06:11:50 +04:00
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
if (this.jobId) {
|
|
|
|
window.clearTimeout(this.jobId);
|
2014-05-05 06:11:50 +04:00
|
|
|
}
|
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
this.callback(this);
|
2014-05-05 06:11:50 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2014-11-06 01:48:37 +03:00
|
|
|
* @class ImageLoader
|
|
|
|
* @memberof OpenSeadragon
|
2014-05-05 06:11:50 +04:00
|
|
|
* @classdesc Handles downloading of a set of images using asynchronous queue pattern.
|
2014-11-06 01:48:37 +03:00
|
|
|
* You generally won't have to interact with the ImageLoader directly.
|
2014-12-19 17:17:15 +03:00
|
|
|
* @param {Object} options - Options for this ImageLoader.
|
2014-12-22 10:51:57 +03:00
|
|
|
* @param {Number} [options.jobLimit] - The number of concurrent image requests. See imageLoaderLimit in {@link OpenSeadragon.Options} for details.
|
2017-05-12 07:36:27 +03:00
|
|
|
* @param {Number} [options.timeout] - The max number of milliseconds that an image job may take to complete.
|
2014-05-05 06:11:50 +04:00
|
|
|
*/
|
2016-10-22 00:28:12 +03:00
|
|
|
$.ImageLoader = function(options) {
|
2014-11-06 01:48:37 +03:00
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
$.extend(true, this, {
|
2014-05-05 06:11:50 +04:00
|
|
|
jobLimit: $.DEFAULT_SETTINGS.imageLoaderLimit,
|
2017-05-12 07:36:27 +03:00
|
|
|
timeout: $.DEFAULT_SETTINGS.timeout,
|
2014-05-05 06:11:50 +04:00
|
|
|
jobQueue: [],
|
|
|
|
jobsInProgress: 0
|
2016-10-22 00:28:12 +03:00
|
|
|
}, options);
|
2014-05-05 06:11:50 +04:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2016-01-25 00:09:18 +03:00
|
|
|
/** @lends OpenSeadragon.ImageLoader.prototype */
|
|
|
|
$.ImageLoader.prototype = {
|
2014-11-06 01:48:37 +03:00
|
|
|
|
2014-05-05 06:11:50 +04:00
|
|
|
/**
|
|
|
|
* Add an unloaded image to the loader queue.
|
|
|
|
* @method
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {Object} options - Options for this job.
|
|
|
|
* @param {String} [options.src] - URL of image to download.
|
2022-06-07 15:53:18 +03:00
|
|
|
* @param {Tile} [options.tile] - Tile that belongs the data to. The tile instance
|
|
|
|
* is not internally used and serves for custom TileSources implementations.
|
2022-04-16 22:19:54 +03:00
|
|
|
* @param {TileSource} [options.source] - Image loading strategy
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {String} [options.loadWithAjax] - Whether to load this image with AJAX.
|
2016-11-08 20:27:30 +03:00
|
|
|
* @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX.
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {String|Boolean} [options.crossOriginPolicy] - CORS policy to use for downloads
|
2022-03-23 12:22:13 +03:00
|
|
|
* @param {String} [options.postData] - POST parameters (usually but not necessarily in k=v&k2=v2... form,
|
2022-05-04 16:16:13 +03:00
|
|
|
* see TileSource::getPostData) or null
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {Boolean} [options.ajaxWithCredentials] - Whether to set withCredentials on AJAX
|
2022-03-23 12:22:13 +03:00
|
|
|
* requests.
|
2016-10-22 00:28:12 +03:00
|
|
|
* @param {Function} [options.callback] - Called once image has been downloaded.
|
|
|
|
* @param {Function} [options.abort] - Called when this image job is aborted.
|
2014-05-05 06:11:50 +04:00
|
|
|
*/
|
2016-10-22 00:28:12 +03:00
|
|
|
addJob: function(options) {
|
2022-04-29 19:41:43 +03:00
|
|
|
if (!options.source) {
|
|
|
|
$.console.error('ImageLoader.prototype.addJob() requires [options.source]. ' +
|
|
|
|
'TileSource since new API defines how images are fetched. Creating a dummy TileSource.');
|
2022-04-30 00:45:01 +03:00
|
|
|
var implementation = $.TileSource.prototype;
|
2022-04-29 19:41:43 +03:00
|
|
|
options.source = {
|
|
|
|
downloadTileStart: implementation.downloadTileStart,
|
2022-05-04 16:16:13 +03:00
|
|
|
downloadTileAbort: implementation.downloadTileAbort
|
2022-04-29 19:41:43 +03:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-05-05 06:11:50 +04:00
|
|
|
var _this = this,
|
2016-10-22 00:28:12 +03:00
|
|
|
complete = function(job) {
|
|
|
|
completeJob(_this, job, options.callback);
|
2014-05-05 06:11:50 +04:00
|
|
|
},
|
|
|
|
jobOptions = {
|
|
|
|
src: options.src,
|
2022-06-07 15:53:18 +03:00
|
|
|
tile: options.tile || {},
|
2022-04-16 22:19:54 +03:00
|
|
|
source: options.source,
|
2016-10-22 00:28:12 +03:00
|
|
|
loadWithAjax: options.loadWithAjax,
|
2016-11-08 20:27:30 +03:00
|
|
|
ajaxHeaders: options.loadWithAjax ? options.ajaxHeaders : null,
|
2014-06-26 22:33:43 +04:00
|
|
|
crossOriginPolicy: options.crossOriginPolicy,
|
2016-10-22 00:28:12 +03:00
|
|
|
ajaxWithCredentials: options.ajaxWithCredentials,
|
2021-12-08 11:54:14 +03:00
|
|
|
postData: options.postData,
|
2015-03-03 11:29:23 +03:00
|
|
|
callback: complete,
|
2017-05-12 07:36:27 +03:00
|
|
|
abort: options.abort,
|
|
|
|
timeout: this.timeout
|
2014-05-05 06:11:50 +04:00
|
|
|
},
|
2022-04-30 00:45:01 +03:00
|
|
|
newJob = new $.ImageJob(jobOptions);
|
2014-05-05 06:11:50 +04:00
|
|
|
|
|
|
|
if ( !this.jobLimit || this.jobsInProgress < this.jobLimit ) {
|
|
|
|
newJob.start();
|
|
|
|
this.jobsInProgress++;
|
|
|
|
}
|
|
|
|
else {
|
2014-12-19 17:50:19 +03:00
|
|
|
this.jobQueue.push( newJob );
|
2014-05-05 06:11:50 +04:00
|
|
|
}
|
2014-05-22 05:29:40 +04:00
|
|
|
},
|
2014-05-05 06:11:50 +04:00
|
|
|
|
2014-05-22 05:29:40 +04:00
|
|
|
/**
|
|
|
|
* Clear any unstarted image loading jobs from the queue.
|
|
|
|
* @method
|
|
|
|
*/
|
|
|
|
clear: function() {
|
2015-03-03 11:29:23 +03:00
|
|
|
for( var i = 0; i < this.jobQueue.length; i++ ) {
|
2015-03-03 11:36:04 +03:00
|
|
|
var job = this.jobQueue[i];
|
2015-03-03 11:29:23 +03:00
|
|
|
if ( typeof job.abort === "function" ) {
|
|
|
|
job.abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 05:29:40 +04:00
|
|
|
this.jobQueue = [];
|
2014-05-05 06:11:50 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cleans up ImageJob once completed.
|
|
|
|
* @method
|
|
|
|
* @private
|
|
|
|
* @param loader - ImageLoader used to start job.
|
|
|
|
* @param job - The ImageJob that has completed.
|
|
|
|
* @param callback - Called once cleanup is finished.
|
|
|
|
*/
|
2016-10-22 00:28:12 +03:00
|
|
|
function completeJob(loader, job, callback) {
|
2014-05-05 06:11:50 +04:00
|
|
|
var nextJob;
|
|
|
|
|
|
|
|
loader.jobsInProgress--;
|
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
if ((!loader.jobLimit || loader.jobsInProgress < loader.jobLimit) && loader.jobQueue.length > 0) {
|
2014-05-05 06:11:50 +04:00
|
|
|
nextJob = loader.jobQueue.shift();
|
|
|
|
nextJob.start();
|
2014-12-19 17:50:19 +03:00
|
|
|
loader.jobsInProgress++;
|
2014-05-05 06:11:50 +04:00
|
|
|
}
|
|
|
|
|
2022-06-07 15:53:18 +03:00
|
|
|
callback(job.data, job.errorMsg, job.request);
|
2014-05-05 06:11:50 +04:00
|
|
|
}
|
|
|
|
|
2016-10-22 00:28:12 +03:00
|
|
|
}(OpenSeadragon));
|