diff --git a/src/dzitilesource.js b/src/dzitilesource.js index f600a4d1..daed1f80 100644 --- a/src/dzitilesource.js +++ b/src/dzitilesource.js @@ -124,10 +124,11 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead * @function * @param {Object|XMLDocument} data - the raw configuration * @param {String} url - the url the data was retrieved from if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null; * @return {Object} options - A dictionary of keyword arguments sufficient * to configure this tile sources constructor. */ - configure: function( data, url ){ + configure: function( data, url, postData ){ var options; diff --git a/src/iiiftilesource.js b/src/iiiftilesource.js index dd6eeff1..dfa10c8e 100644 --- a/src/iiiftilesource.js +++ b/src/iiiftilesource.js @@ -183,6 +183,8 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea * * @function * @param {Object} data - the raw configuration + * @param {String} url - the url configuration was retrieved from + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null; * @example IIIF 1.1 Info Looks like this * { * "@context" : "http://library.stanford.edu/iiif/image-api/1.1/context.json", @@ -197,7 +199,7 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea * "profile" : "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0" * } */ - configure: function( data, url ){ + configure: function( data, url, postData ){ // Try to deduce our version and fake it upwards if needed if ( !$.isPlainObject(data) ) { var options = configureFromXml10( data ); diff --git a/src/imageloader.js b/src/imageloader.js index faa1fac8..dc92e4ea 100644 --- a/src/imageloader.js +++ b/src/imageloader.js @@ -43,6 +43,7 @@ * @param {String} [options.loadWithAjax] - Whether to load this image with AJAX. * @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX. * @param {String} [options.crossOriginPolicy] - CORS policy to use for downloads + * @param {String} [options.postData] - HTTP POST data in k=v&k2=v2... form; or null * @param {Function} [options.callback] - Called once image has been downloaded. * @param {Function} [options.abort] - Called when this image job is aborted. * @param {Number} [options.timeout] - The max number of milliseconds that this image job may take to complete. @@ -96,6 +97,7 @@ ImageJob.prototype = { withCredentials: this.ajaxWithCredentials, headers: this.ajaxHeaders, responseType: "arraybuffer", + postData: this.postData, success: function(request) { var blb; // Make the raw data into a blob. @@ -196,6 +198,7 @@ $.ImageLoader.prototype = { * @param {String} [options.loadWithAjax] - Whether to load this image with AJAX. * @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX. * @param {String|Boolean} [options.crossOriginPolicy] - CORS policy to use for downloads + * @param {String} [options.postData] - POST parameters in k=v&k2=v2... form or null * @param {Boolean} [options.ajaxWithCredentials] - Whether to set withCredentials on AJAX * requests. * @param {Function} [options.callback] - Called once image has been downloaded. @@ -212,6 +215,7 @@ $.ImageLoader.prototype = { ajaxHeaders: options.loadWithAjax ? options.ajaxHeaders : null, crossOriginPolicy: options.crossOriginPolicy, ajaxWithCredentials: options.ajaxWithCredentials, + postData: options.postData, callback: complete, abort: options.abort, timeout: this.timeout diff --git a/src/imagetilesource.js b/src/imagetilesource.js index 25f67988..462c33a4 100644 --- a/src/imagetilesource.js +++ b/src/imagetilesource.js @@ -89,10 +89,11 @@ * @function * @param {Object} options - the options * @param {String} dataUrl - the url the image was retrieved from, if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null * @return {Object} options - A dictionary of keyword arguments sufficient * to configure this tile sources constructor. */ - configure: function (options, dataUrl) { + configure: function (options, dataUrl, postData) { return options; }, /** diff --git a/src/legacytilesource.js b/src/legacytilesource.js index c1c5e253..ab544eb1 100644 --- a/src/legacytilesource.js +++ b/src/legacytilesource.js @@ -122,10 +122,11 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, /** @lends OpenS * @function * @param {Object|XMLDocument} configuration - the raw configuration * @param {String} dataUrl - the url the data was retrieved from if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null * @return {Object} options - A dictionary of keyword arguments sufficient * to configure this tile sources constructor. */ - configure: function( configuration, dataUrl ){ + configure: function( configuration, dataUrl, postData ){ var options; diff --git a/src/openseadragon.js b/src/openseadragon.js index 4f982eba..73fb912b 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -659,6 +659,15 @@ * @property {Object} [ajaxHeaders={}] * A set of headers to include when making AJAX requests for tile sources or tiles. * + * @property {Boolean} [splitHashDataForPost=false] + * Allows to treat _first_ hash ('#') symbol as a separator for POST data: + * URL to be opened by a {@link OpenSeadragon.TileSource} can thus look like: http://some.url#postdata=here . + * The URL is split to 'http://some.url' and 'postdata=here'; post data is given to the + * {@link OpenSeadragon.TileSource} of the choice and can be further used within tile requests + * (see TileSource methods). {@link OpenSeadragon.TileSource.prototype.configure} return value + * should contain the post data so that it is given to its subclass in the constructor. + * NOTE: post data is expected to be ampersand-separated (just like GET parameters), and is not used + * to fetch tile image data if loadTilesWithAjax=false (but it is still used for the initial request). */ /** @@ -1140,6 +1149,7 @@ function OpenSeadragon( options ){ ajaxWithCredentials: false, loadTilesWithAjax: false, ajaxHeaders: {}, + splitHashDataForPost: false, //PAN AND ZOOM SETTINGS AND CONSTRAINTS panHorizontal: true, @@ -2299,6 +2309,7 @@ function OpenSeadragon( options ){ * @param {Function} options.error - a function to call on when an error occurs * @param {Object} options.headers - headers to add to the AJAX request * @param {String} options.responseType - the response type of the the AJAX request + * @param {String} options.postData - HTTP POST data in k=v&k2=v2... form, GET method used if null * @param {Boolean} [options.withCredentials=false] - whether to set the XHR's withCredentials * @throws {Error} * @returns {XMLHttpRequest} @@ -2307,6 +2318,7 @@ function OpenSeadragon( options ){ var withCredentials; var headers; var responseType; + var postData; // Note that our preferred API is that you pass in a single object; the named // arguments are for legacy support. @@ -2316,6 +2328,7 @@ function OpenSeadragon( options ){ withCredentials = url.withCredentials; headers = url.headers; responseType = url.responseType || null; + postData = url.postData || null; url = url.url; } @@ -2348,8 +2361,9 @@ function OpenSeadragon( options ){ } }; + var method = postData ? "POST" : "GET"; try { - request.open( "GET", url, true ); + request.open( method, url, true ); if (responseType) { request.responseType = responseType; @@ -2367,7 +2381,7 @@ function OpenSeadragon( options ){ request.withCredentials = true; } - request.send(null); + request.send(postData); } catch (e) { $.console.error( "%s while making AJAX request: %s", e.name, e.message ); diff --git a/src/osmtilesource.js b/src/osmtilesource.js index c28945bb..fcfe5c30 100644 --- a/src/osmtilesource.js +++ b/src/osmtilesource.js @@ -122,10 +122,11 @@ $.extend( $.OsmTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead * @function * @param {Object} data - the raw configuration * @param {String} url - the url the data was retrieved from if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null * @return {Object} options - A dictionary of keyword arguments sufficient * to configure this tile sources constructor. */ - configure: function( data, url ){ + configure: function( data, url, postData ){ return data; }, diff --git a/src/tile.js b/src/tile.js index f003c157..a427e137 100644 --- a/src/tile.js +++ b/src/tile.js @@ -50,10 +50,11 @@ * @param {Boolean} loadWithAjax Whether this tile image should be loaded with an AJAX request . * @param {Object} ajaxHeaders The headers to send with this tile's AJAX request (if applicable). * @param {OpenSeadragon.Rect} sourceBounds The portion of the tile to use as the source of the + * @param {String} postData HTTP POST data in k=v&k2=v2... form; or null * drawing operation, in pixels. Note that this only works when drawing with canvas; when drawing * with HTML the entire tile is always used. */ -$.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, ajaxHeaders, sourceBounds) { +$.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, ajaxHeaders, sourceBounds, postData) { /** * The zoom level this tile belongs to. * @member {Number} level @@ -97,6 +98,13 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, aja * @memberof OpenSeadragon.Tile# */ this.url = url; + /** + * Post parameters for this tile. Either it is an URL-encoded string + * in k1=v1&k2=v2... format or null + * @member {String} postData HTTP POST data in k=v&k2=v2... form; or null + * @memberof OpenSeadragon.Tile# + */ + this.postData = postData; /** * The context2D of this tile if it is provided directly by the tile source. * @member {CanvasRenderingContext2D} context2D diff --git a/src/tiledimage.js b/src/tiledimage.js index 2817710f..76f3eead 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -1500,6 +1500,7 @@ function getTile( sourceBounds, exists, url, + post, ajaxHeaders, context2D, tile; @@ -1518,6 +1519,7 @@ function getTile( sourceBounds = tileSource.getTileBounds( level, xMod, yMod, true ); exists = tileSource.tileExists( level, xMod, yMod ); url = tileSource.getTileUrl( level, xMod, yMod ); + post = tileSource.getTilePostData( level, xMod, yMod ); // Headers are only applicable if loadTilesWithAjax is set if (tiledImage.loadTilesWithAjax) { @@ -1543,7 +1545,8 @@ function getTile( context2D, tiledImage.loadTilesWithAjax, ajaxHeaders, - sourceBounds + sourceBounds, + post ); if (tiledImage.getFlip()) { @@ -1583,6 +1586,7 @@ function loadTile( tiledImage, tile, time ) { tile.loading = true; tiledImage._imageLoader.addJob({ src: tile.url, + postData: tile.postData, loadWithAjax: tile.loadWithAjax, ajaxHeaders: tile.ajaxHeaders, crossOriginPolicy: tiledImage.crossOriginPolicy, diff --git a/src/tilesource.js b/src/tilesource.js index 32df56cf..60535eea 100644 --- a/src/tilesource.js +++ b/src/tilesource.js @@ -69,6 +69,9 @@ * the XHR's withCredentials (for accessing secure data). * @param {Object} [options.ajaxHeaders] * A set of headers to include in AJAX requests. + * @param {Boolean} [options.splitHashDataForPost] + * First occurrence of '#' in the options.url is used to split URL + * and the latter part is treated as POST data (applies to getImageInfo(...)) * @param {Number} [options.width] * Width of the source image at max resolution in pixels. * @param {Number} [options.height] @@ -445,6 +448,15 @@ $.TileSource.prototype = { } } + var postData = null; + if (this.splitHashDataForPost) { + var hashIdx = url.indexOf("#"); + if (hashIdx !== -1) { + postData = url.substring(hashIdx + 1); + url = url.substr(0, hashIdx); + } + } + callback = function( data ){ if( typeof (data) === "string" ) { data = $.parseXml( data ); @@ -466,7 +478,7 @@ $.TileSource.prototype = { return; } - options = $TileSource.prototype.configure.apply( _this, [ data, url ]); + options = $TileSource.prototype.configure.apply( _this, [ data, url, postData ]); if (options.ajaxWithCredentials === undefined) { options.ajaxWithCredentials = _this.ajaxWithCredentials; } @@ -501,6 +513,7 @@ $.TileSource.prototype = { // request info via xhr asynchronously. $.makeAjaxRequest( { url: url, + postData: postData, withCredentials: this.ajaxWithCredentials, headers: this.ajaxHeaders, success: function( xhr ) { @@ -537,11 +550,13 @@ $.TileSource.prototype = { * @property {OpenSeadragon.TileSource} eventSource - A reference to the TileSource which raised the event. * @property {String} message * @property {String} source + * @property {String} postData - HTTP POST data in k=v&k2=v2... form; or null * @property {?Object} userData - Arbitrary subscriber-defined object. */ _this.raiseEvent( 'open-failed', { message: msg, - source: url + source: url, + postData: postData }); } }); @@ -578,11 +593,14 @@ $.TileSource.prototype = { * @param {String|Object|Array|Document} data * @param {String} url - the url the data was loaded * from if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null; value obtained from + * the protocol URL after '#' sign if flag splitHashDataForPost set to 'true' * @return {Object} options - A dictionary of keyword arguments sufficient - * to configure this tile sources constructor. + * to configure the tile source constructor (include all values you want to + * instantiate the TileSource subclass with - what _options_ object should contain). * @throws {Error} */ - configure: function( data, url ) { + configure: function( data, url, postData ) { throw new Error( "Method not implemented." ); }, @@ -603,6 +621,20 @@ $.TileSource.prototype = { throw new Error( "Method not implemented." ); }, + /** + * Must use AJAX in order to work, i.e. loadTilesWithAjax = true is set. + * It should return url-encoded string with the following structure: + * key=value&key2=value2... + * or null in case GET is used instead. + * @param level + * @param x + * @param y + * @return {string || null} post data to send with tile configuration request + */ + getTilePostData: function( level, x, y ) { + return null; + }, + /** * Responsible for retrieving the headers which will be attached to the image request for the * region specified by the given x, y, and level components. diff --git a/src/tmstilesource.js b/src/tmstilesource.js index abb8f2db..e9eef83b 100644 --- a/src/tmstilesource.js +++ b/src/tmstilesource.js @@ -111,10 +111,11 @@ $.extend( $.TmsTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead * @function * @param {Object} data - the raw configuration * @param {String} url - the url the data was retrieved from if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null * @return {Object} options - A dictionary of keyword arguments sufficient * to configure this tile sources constructor. */ - configure: function( data, url ){ + configure: function( data, url, postData ){ return data; }, diff --git a/src/viewer.js b/src/viewer.js index b1a60446..b4199a42 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -2432,6 +2432,7 @@ function getTileSourceImplementation( viewer, tileSource, imgOptions, successCal ajaxWithCredentials: viewer.ajaxWithCredentials, ajaxHeaders: imgOptions.ajaxHeaders ? imgOptions.ajaxHeaders : viewer.ajaxHeaders, + splitHashDataForPost: viewer.splitHashDataForPost, useCanvas: viewer.useCanvas, success: function( event ) { successCallback( event.tileSource ); diff --git a/src/zoomifytilesource.js b/src/zoomifytilesource.js index 9ffa4988..ce90aba8 100644 --- a/src/zoomifytilesource.js +++ b/src/zoomifytilesource.js @@ -122,10 +122,11 @@ * @function * @param {Object} data - the raw configuration * @param {String} url - the url the data was retrieved from if any. + * @param {String} postData - HTTP POST data in k=v&k2=v2... form; or null * @return {Object} options - A dictionary of keyword arguments sufficient * to configure this tile sources constructor. */ - configure: function(data, url) { + configure: function(data, url, postData) { return data; }, diff --git a/test/coverage.html b/test/coverage.html index df0e9781..6d392209 100644 --- a/test/coverage.html +++ b/test/coverage.html @@ -86,6 +86,7 @@ +