diff --git a/src/ol/net.js b/src/ol/net.js index ae890a991d..d426c7c539 100644 --- a/src/ol/net.js +++ b/src/ol/net.js @@ -1,17 +1,21 @@ -goog.provide('ol.net.Jsonp'); +goog.provide('ol.net'); /** + * Simple JSONP helper. Supports error callbacks and a custom callback param. + * The error callback will be called when no JSONP is executed after 10 seconds. + * * @param {string} url Request url. A 'callback' query parameter will be * appended. * @param {Function} callback Callback on success. * @param {function()=} opt_errback Callback on error. - * @param {string=} opt_callbackParam Callback parameter. Default is 'callback'. + * @param {string=} opt_callbackParam Custom qurey parameter for the JSONP + * callback. Default is 'callback'. */ -ol.net.Jsonp = function(url, callback, opt_errback, opt_callbackParam) { +ol.net.jsonp = function(url, callback, opt_errback, opt_callbackParam) { var script = goog.global.document.createElement('script'); script.async = true; - var key = 'ol_callback_' + goog.getUid(callback); + var key = 'olc_' + goog.getUid(callback); script.src = url + (url.indexOf('?') == -1 ? '?' : '&') + (opt_callbackParam || 'callback') + '=' + key; var timer = goog.global.setTimeout(function() { diff --git a/src/ol/source/bingmapssource.js b/src/ol/source/bingmapssource.js index ba92981f67..a2adf057f4 100644 --- a/src/ol/source/bingmapssource.js +++ b/src/ol/source/bingmapssource.js @@ -5,7 +5,7 @@ goog.require('ol.Attribution'); goog.require('ol.TileRange'); goog.require('ol.TileUrlFunction'); goog.require('ol.extent'); -goog.require('ol.net.Jsonp'); +goog.require('ol.net'); goog.require('ol.proj'); goog.require('ol.source.State'); goog.require('ol.source.TileImage'); @@ -49,7 +49,7 @@ ol.source.BingMaps = function(options) { options.imagerySet + '?uriScheme=https&include=ImageryProviders&key=' + options.key; - ol.net.Jsonp(url, this.handleImageryMetadataResponse.bind(this), undefined, + ol.net.jsonp(url, this.handleImageryMetadataResponse.bind(this), undefined, 'jsonp'); }; diff --git a/src/ol/source/tilejsonsource.js b/src/ol/source/tilejsonsource.js index 7c8e52c355..1abf80ec55 100644 --- a/src/ol/source/tilejsonsource.js +++ b/src/ol/source/tilejsonsource.js @@ -12,7 +12,7 @@ goog.require('ol.Attribution'); goog.require('ol.TileRange'); goog.require('ol.TileUrlFunction'); goog.require('ol.extent'); -goog.require('ol.net.Jsonp'); +goog.require('ol.net'); goog.require('ol.proj'); goog.require('ol.source.State'); goog.require('ol.source.TileImage'); @@ -40,7 +40,7 @@ ol.source.TileJSON = function(options) { }); if (options.jsonp) { - ol.net.Jsonp(options.url, this.handleTileJSONResponse.bind(this), + ol.net.jsonp(options.url, this.handleTileJSONResponse.bind(this), this.handleTileJSONError.bind(this)); } else { var xhr = new XMLHttpRequest(); diff --git a/src/ol/source/tileutfgridsource.js b/src/ol/source/tileutfgridsource.js index 7a089b4298..e23e11a179 100644 --- a/src/ol/source/tileutfgridsource.js +++ b/src/ol/source/tileutfgridsource.js @@ -9,7 +9,7 @@ goog.require('ol.TileUrlFunction'); goog.require('ol.events'); goog.require('ol.events.EventType'); goog.require('ol.extent'); -goog.require('ol.net.Jsonp'); +goog.require('ol.net'); goog.require('ol.proj'); goog.require('ol.source.State'); goog.require('ol.source.Tile'); @@ -49,7 +49,7 @@ ol.source.TileUTFGrid = function(options) { */ this.template_ = undefined; - ol.net.Jsonp(options.url, this.handleTileJSONResponse.bind(this)); + ol.net.jsonp(options.url, this.handleTileJSONResponse.bind(this)); }; goog.inherits(ol.source.TileUTFGrid, ol.source.Tile); @@ -359,7 +359,7 @@ ol.source.TileUTFGridTile_.prototype.handleLoad_ = function(json) { ol.source.TileUTFGridTile_.prototype.loadInternal_ = function() { if (this.state == ol.TileState.IDLE) { this.state = ol.TileState.LOADING; - ol.net.Jsonp(this.src_, this.handleLoad_.bind(this), + ol.net.jsonp(this.src_, this.handleLoad_.bind(this), this.handleError_.bind(this)); } }; diff --git a/test/spec/ol/net.test.js b/test/spec/ol/net.test.js new file mode 100644 index 0000000000..27cc1daef8 --- /dev/null +++ b/test/spec/ol/net.test.js @@ -0,0 +1,65 @@ +goog.provide('ol.test.net'); + + +describe('ol.net', function() { + + describe('jsonp()', function() { + var head = goog.global.document.getElementsByTagName('head')[0]; + var origAppendChild = head.appendChild; + var origSetTimeout = goog.global.setTimeout; + var key; + + function createCallback(url, done) { + var callback = function(data) { + expect(data).to.be(url + key); + done(); + }; + key = 'olc_' + goog.getUid(callback); + return callback; + } + + beforeEach(function() { + head.appendChild = function(element) { + origSetTimeout(function() { + goog.global[key](element.getAttribute('src')); + }, 0); + }; + goog.global.setTimeout = function(fn, time) { + origSetTimeout(fn, 100); + }; + }); + + afterEach(function() { + head.appendChild = origAppendChild; + goog.global.setTimeout = origSetTimeout; + }); + + it('appends callback param to url, cleans up after call', function(done) { + ol.net.jsonp('foo', createCallback('foo?callback=', done)); + }); + it('appends correct callback param to a url with query', function(done) { + var callback = createCallback('http://foo/bar?baz&callback=', done); + ol.net.jsonp('http://foo/bar?baz', callback); + }); + it('calls errback when jsonp is not executed, cleans up', function(done) { + head.appendChild = function() {}; + function callback() { + expect.fail(); + } + function errback() { + expect(goog.global[key]).to.be(undefined); + done(); + } + ol.net.jsonp('foo', callback, errback); + }); + it('accepts a custom callback param', function(done) { + var callback = createCallback('foo?mycallback=', done); + ol.net.jsonp('foo', callback, undefined, 'mycallback'); + }); + + }); + +}); + + +goog.require('ol.net'); diff --git a/test/spec/ol/source/bingmapssource.test.js b/test/spec/ol/source/bingmapssource.test.js index bec185aa4f..326a814cbf 100644 --- a/test/spec/ol/source/bingmapssource.test.js +++ b/test/spec/ol/source/bingmapssource.test.js @@ -7,9 +7,9 @@ describe('ol.source.BingMaps', function() { var source, tileGrid; beforeEach(function(done) { - var olNetJsonp = ol.net.Jsonp; + var olNetJsonp = ol.net.jsonp; // mock ol.net.Jsonp (used in the ol.source.TileJSON constructor) - ol.net.Jsonp = function(url, callback) { + ol.net.jsonp = function(url, callback) { var client = new XMLHttpRequest(); client.open('GET', 'spec/ol/data/bing_aerialwithlabels.json', true); client.onload = function() { @@ -21,7 +21,7 @@ describe('ol.source.BingMaps', function() { imagerySet: 'AerialWithLabels', key: '' }); - ol.net.Jsonp = olNetJsonp; + ol.net.jsonp = olNetJsonp; var key = source.on('change', function() { if (source.getState() === 'ready') { ol.Observable.unByKey(key); @@ -72,7 +72,7 @@ describe('ol.source.BingMaps', function() { }); -goog.require('ol.net.Jsonp'); +goog.require('ol.net'); goog.require('ol.source.BingMaps'); goog.require('ol.tilecoord'); goog.require('ol.Observable');