Adding a protocol for reading features cross-origin from services that support JSON with a callback. r=erilem (closes #2956)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@11691 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
35
examples/cross-origin.html
Normal file
35
examples/cross-origin.html
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenLayers Script Protocol Example</title>
|
||||||
|
<link rel="stylesheet" href="../theme/default/style.css" type="text/css">
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<script src="../lib/OpenLayers.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 id="title">Script Protocol</h1>
|
||||||
|
<div id="tags">
|
||||||
|
protocol, script, cross origin, advanced
|
||||||
|
</div>
|
||||||
|
<p id="shortdesc">
|
||||||
|
Demonstrates the use of a script protocol for making feature requests
|
||||||
|
cross origin.
|
||||||
|
</p>
|
||||||
|
<div id="map" class="smallmap"></div>
|
||||||
|
<div id="docs">
|
||||||
|
<p>
|
||||||
|
In cases where a service returns serialized features and accepts
|
||||||
|
a named callback (e.g. http://example.com/features.json?callback=foo),
|
||||||
|
the script protocol can be used to read features without being
|
||||||
|
restricted by the same origin policy.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
View the <a href="cross-origin.js" target="_blank">cross-origin.js</a>
|
||||||
|
source to see how this is done
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<script src="cross-origin.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
39
examples/cross-origin.js
Normal file
39
examples/cross-origin.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
var map = new OpenLayers.Map({
|
||||||
|
div: "map",
|
||||||
|
layers: [
|
||||||
|
new OpenLayers.Layer.WMS(
|
||||||
|
"World Map",
|
||||||
|
"http://maps.opengeo.org/geowebcache/service/wms",
|
||||||
|
{layers: "bluemarble"}
|
||||||
|
),
|
||||||
|
new OpenLayers.Layer.Vector("States", {
|
||||||
|
strategies: [new OpenLayers.Strategy.BBOX()],
|
||||||
|
protocol: new OpenLayers.Protocol.Script({
|
||||||
|
url: "http://suite.opengeo.org/geoserver/wfs",
|
||||||
|
callbackKey: "format_options",
|
||||||
|
callbackPrefix: "callback:",
|
||||||
|
params: {
|
||||||
|
service: "WFS",
|
||||||
|
version: "1.1.0",
|
||||||
|
srsName: "EPSG:4326",
|
||||||
|
request: "GetFeature",
|
||||||
|
typeName: "world:cities",
|
||||||
|
outputFormat: "json"
|
||||||
|
},
|
||||||
|
filterToParams: function(filter, params) {
|
||||||
|
// example to demonstrate BBOX serialization
|
||||||
|
if (filter.type === OpenLayers.Filter.Spatial.BBOX) {
|
||||||
|
params.bbox = filter.value.toArray();
|
||||||
|
if (filter.projection) {
|
||||||
|
params.bbox.push(filter.projection.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
],
|
||||||
|
center: new OpenLayers.LonLat(0, 0),
|
||||||
|
zoom: 1
|
||||||
|
});
|
||||||
|
|
||||||
@@ -252,6 +252,7 @@
|
|||||||
"OpenLayers/Protocol/WFS/v1.js",
|
"OpenLayers/Protocol/WFS/v1.js",
|
||||||
"OpenLayers/Protocol/WFS/v1_0_0.js",
|
"OpenLayers/Protocol/WFS/v1_0_0.js",
|
||||||
"OpenLayers/Protocol/WFS/v1_1_0.js",
|
"OpenLayers/Protocol/WFS/v1_1_0.js",
|
||||||
|
"OpenLayers/Protocol/Script.js",
|
||||||
"OpenLayers/Protocol/SOS.js",
|
"OpenLayers/Protocol/SOS.js",
|
||||||
"OpenLayers/Protocol/SOS/v1_0_0.js",
|
"OpenLayers/Protocol/SOS/v1_0_0.js",
|
||||||
"OpenLayers/Layer/PointTrack.js",
|
"OpenLayers/Layer/PointTrack.js",
|
||||||
|
|||||||
363
lib/OpenLayers/Protocol/Script.js
Normal file
363
lib/OpenLayers/Protocol/Script.js
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
|
||||||
|
* full list of contributors). Published under the Clear BSD license.
|
||||||
|
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the
|
||||||
|
* full text of the license. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires OpenLayers/Protocol.js
|
||||||
|
* @requires OpenLayers/Feature/Vector.js
|
||||||
|
* @requires OpenLayers/Format/GeoJSON.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: OpenLayers.Protocol.Script
|
||||||
|
* A basic Script protocol for vector layers. Create a new instance with the
|
||||||
|
* <OpenLayers.Protocol.Script> constructor. A script protocol is used to
|
||||||
|
* get around the same origin policy. It works with services that return
|
||||||
|
* JSONP - that is, JSON wrapped in a client-specified callback. The
|
||||||
|
* protocol handles fetching and parsing of feature data and sends parsed
|
||||||
|
* features to the <callback> configured with the protocol. The protocol
|
||||||
|
* expects features serialized as GeoJSON by default, but can be configured
|
||||||
|
* to work with other formats by setting the <format> property.
|
||||||
|
*
|
||||||
|
* Inherits from:
|
||||||
|
* - <OpenLayers.Protocol>
|
||||||
|
*/
|
||||||
|
OpenLayers.Protocol.Script = OpenLayers.Class(OpenLayers.Protocol, {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: url
|
||||||
|
* {String} Service URL. The service is expected to return serialized
|
||||||
|
* features wrapped in a named callback (where the callback name is
|
||||||
|
* generated by this protocol).
|
||||||
|
* Read-only, set through the options passed to the constructor.
|
||||||
|
*/
|
||||||
|
url: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: params
|
||||||
|
* {Object} Query string parameters to be appended to the URL.
|
||||||
|
* Read-only, set through the options passed to the constructor.
|
||||||
|
* Example: {maxFeatures: 50}
|
||||||
|
*/
|
||||||
|
params: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: callback
|
||||||
|
* {Object} Function to be called when the <read> operation completes.
|
||||||
|
*/
|
||||||
|
callback: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: scope
|
||||||
|
* {Object} Optional ``this`` object for the callback. Read-only, set
|
||||||
|
* through the options passed to the constructor.
|
||||||
|
*/
|
||||||
|
scope: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: format
|
||||||
|
* {<OpenLayers.Format>} Format for parsing features. Default is an
|
||||||
|
* <OpenLayers.Format.GeoJSON> format. If an alternative is provided,
|
||||||
|
* the format's read method must take an object and return an array
|
||||||
|
* of features.
|
||||||
|
*/
|
||||||
|
format: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: callbackKey
|
||||||
|
* {String} The name of the query string parameter that the service
|
||||||
|
* recognizes as the callback identifier. Default is "callback".
|
||||||
|
* This key is used to generate the URL for the script. For example
|
||||||
|
* setting <callbackKey> to "myCallback" would result in a URL like
|
||||||
|
* http://example.com/?myCallback=...
|
||||||
|
*/
|
||||||
|
callbackKey: "callback",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: callbackPrefix
|
||||||
|
* {String} Where a service requires that the callback query string
|
||||||
|
* parameter value is prefixed by some string, this value may be set.
|
||||||
|
* For example, setting <callbackPrefix> to "foo:" would result in a
|
||||||
|
* URL like http://example.com/?callback=foo:... Default is "".
|
||||||
|
*/
|
||||||
|
callbackPrefix: "",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: pendingRequests
|
||||||
|
* {Object} References all pending requests. Property names are script
|
||||||
|
* identifiers and property values are script elements.
|
||||||
|
*/
|
||||||
|
pendingRequests: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor: OpenLayers.Protocol.Script
|
||||||
|
* A class for giving layers generic Script protocol.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Optional object whose properties will be set on the
|
||||||
|
* instance.
|
||||||
|
*
|
||||||
|
* Valid options include:
|
||||||
|
* url - {String}
|
||||||
|
* params - {Object}
|
||||||
|
* callback - {Function}
|
||||||
|
* scope - {Object}
|
||||||
|
*/
|
||||||
|
initialize: function(options) {
|
||||||
|
options = options || {};
|
||||||
|
this.params = {};
|
||||||
|
this.pendingRequests = {};
|
||||||
|
OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
|
||||||
|
if (!this.format) {
|
||||||
|
this.format = new OpenLayers.Format.GeoJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.filterToParams && OpenLayers.Protocol.simpleFilterSerializer) {
|
||||||
|
this.filterToParams = OpenLayers.Function.bind(
|
||||||
|
OpenLayers.Protocol.simpleFilterSerializer, this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: read
|
||||||
|
* Construct a request for reading new features.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Optional object for configuring the request.
|
||||||
|
* This object is modified and should not be reused.
|
||||||
|
*
|
||||||
|
* Valid options:
|
||||||
|
* url - {String} Url for the request.
|
||||||
|
* params - {Object} Parameters to get serialized as a query string.
|
||||||
|
* filter - {<OpenLayers.Filter>} Filter to get serialized as a
|
||||||
|
* query string.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {<OpenLayers.Protocol.Response>} A response object, whose "priv" property
|
||||||
|
* references the injected script. This object is also passed to the
|
||||||
|
* callback function when the request completes, its "features" property
|
||||||
|
* is then populated with the features received from the server.
|
||||||
|
*/
|
||||||
|
read: function(options) {
|
||||||
|
OpenLayers.Protocol.prototype.read.apply(this, arguments);
|
||||||
|
options = OpenLayers.Util.applyDefaults(options, this.options);
|
||||||
|
options.params = OpenLayers.Util.applyDefaults(
|
||||||
|
options.params, this.options.params
|
||||||
|
);
|
||||||
|
if (options.filter && this.filterToParams) {
|
||||||
|
options.params = this.filterToParams(
|
||||||
|
options.filter, options.params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var response = new OpenLayers.Protocol.Response({requestType: "read"});
|
||||||
|
var request = this.createRequest(
|
||||||
|
options.url,
|
||||||
|
options.params,
|
||||||
|
OpenLayers.Function.bind(function(data) {
|
||||||
|
response.data = data;
|
||||||
|
this.handleRead(response, options);
|
||||||
|
}, this)
|
||||||
|
);
|
||||||
|
response.priv = request;
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: filterToParams
|
||||||
|
* Optional method to translate an <OpenLayers.Filter> object into an object
|
||||||
|
* that can be serialized as request query string provided. If a custom
|
||||||
|
* method is not provided, any filter will not be serialized.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* filter - {<OpenLayers.Filter>} filter to convert.
|
||||||
|
* params - {Object} The parameters object.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Object} The resulting parameters object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: createRequest
|
||||||
|
* Issues a request for features by creating injecting a script in the
|
||||||
|
* document head.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* url - {String} Service URL.
|
||||||
|
* params - {Object} Query string parameters.
|
||||||
|
* callback - {Function} Callback to be called with resulting data.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {HTMLScriptElement} The script pending execution.
|
||||||
|
*/
|
||||||
|
createRequest: function(url, params, callback) {
|
||||||
|
var id = OpenLayers.Protocol.Script.register(callback);
|
||||||
|
var name = "OpenLayers.Protocol.Script.getCallback(" + id + ")";
|
||||||
|
params = OpenLayers.Util.extend({}, params);
|
||||||
|
params[this.callbackKey] = this.callbackPrefix + name;
|
||||||
|
url = OpenLayers.Util.urlAppend(
|
||||||
|
url, OpenLayers.Util.getParameterString(params)
|
||||||
|
);
|
||||||
|
var script = document.createElement("script");
|
||||||
|
script.type = "text/javascript";
|
||||||
|
script.src = url;
|
||||||
|
script.id = "OpenLayers_Protocol_Script_" + id;
|
||||||
|
this.pendingRequests[script.id] = script;
|
||||||
|
var head = document.getElementsByTagName("head")[0];
|
||||||
|
head.appendChild(script);
|
||||||
|
return script;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: destroyRequest
|
||||||
|
* Remove a script node associated with a response from the document. Also
|
||||||
|
* unregisters the callback and removes the script from the
|
||||||
|
* <pendingRequests> object.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* script - {HTMLScriptElement}
|
||||||
|
*/
|
||||||
|
destroyRequest: function(script) {
|
||||||
|
OpenLayers.Protocol.Script.unregister(script.id.split("_").pop());
|
||||||
|
delete this.pendingRequests[script.id];
|
||||||
|
if (script.parentNode) {
|
||||||
|
script.parentNode.removeChild(script);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: handleRead
|
||||||
|
* Individual callbacks are created for read, create and update, should
|
||||||
|
* a subclass need to override each one separately.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* response - {<OpenLayers.Protocol.Response>} The response object to pass to
|
||||||
|
* the user callback.
|
||||||
|
* options - {Object} The user options passed to the read call.
|
||||||
|
*/
|
||||||
|
handleRead: function(response, options) {
|
||||||
|
this.handleResponse(response, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: handleResponse
|
||||||
|
* Called by CRUD specific handlers.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* response - {<OpenLayers.Protocol.Response>} The response object to pass to
|
||||||
|
* any user callback.
|
||||||
|
* options - {Object} The user options passed to the create, read, update,
|
||||||
|
* or delete call.
|
||||||
|
*/
|
||||||
|
handleResponse: function(response, options) {
|
||||||
|
if (options.callback) {
|
||||||
|
if (response.data) {
|
||||||
|
response.features = this.parseFeatures(response.data);
|
||||||
|
response.code = OpenLayers.Protocol.Response.SUCCESS;
|
||||||
|
} else {
|
||||||
|
response.code = OpenLayers.Protocol.Response.FAILURE;
|
||||||
|
}
|
||||||
|
this.destroyRequest(response.priv);
|
||||||
|
options.callback.call(options.scope, response);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: parseFeatures
|
||||||
|
* Read Script response body and return features.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* data - {Object} The data sent to the callback function by the server.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Array({<OpenLayers.Feature.Vector>})} or
|
||||||
|
* {<OpenLayers.Feature.Vector>} Array of features or a single feature.
|
||||||
|
*/
|
||||||
|
parseFeatures: function(data) {
|
||||||
|
return this.format.read(data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: abort
|
||||||
|
* Abort an ongoing request. If no response is provided, all pending
|
||||||
|
* requests will be aborted.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* response - {<OpenLayers.Protocol.Response>} The response object returned
|
||||||
|
* from a <read> request.
|
||||||
|
*/
|
||||||
|
abort: function(response) {
|
||||||
|
if (response) {
|
||||||
|
this.destroyRequest(response.priv);
|
||||||
|
} else {
|
||||||
|
for (var key in this.pendingRequests) {
|
||||||
|
this.destroyRequest(this.pendingRequests[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: destroy
|
||||||
|
* Clean up the protocol.
|
||||||
|
*/
|
||||||
|
destroy: function() {
|
||||||
|
this.abort();
|
||||||
|
delete this.params;
|
||||||
|
delete this.format;
|
||||||
|
OpenLayers.Protocol.prototype.destroy.apply(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
CLASS_NAME: "OpenLayers.Protocol.Script"
|
||||||
|
});
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var o = OpenLayers.Protocol.Script;
|
||||||
|
var counter = 0;
|
||||||
|
var registry = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function: OpenLayers.Protocol.Script.register
|
||||||
|
* Register a callback for a newly created script.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* callback: {Function} The callback to be executed when the newly added
|
||||||
|
* script loads. This callback will be called with a single argument
|
||||||
|
* that is the JSON returned by the service.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Number} An identifier for retreiving the registered callback.
|
||||||
|
*/
|
||||||
|
o.register = function(callback) {
|
||||||
|
var id = ++counter;
|
||||||
|
registry[id] = callback;
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function: OpenLayers.Protocol.Script.unregister
|
||||||
|
* Unregister a callback previously registered with the register function.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* id: {Number} The identifer returned by the register function.
|
||||||
|
*/
|
||||||
|
o.unregister = function(id) {
|
||||||
|
delete registry[id];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function: OpenLayers.Protocol.Script.getCallback
|
||||||
|
* Retreive and unregister a callback. A call to this function is the "P"
|
||||||
|
* in JSONP. For example, a script may be added with a src attribute
|
||||||
|
* http://example.com/features.json?callback=OpenLayers.Protocol.Script.getCallback(1)
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* id: {Number} The identifer returned by the register function.
|
||||||
|
*/
|
||||||
|
o.getCallback = function(id) {
|
||||||
|
var callback = registry[id];
|
||||||
|
o.unregister(id);
|
||||||
|
return callback;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
271
tests/Protocol/Script.html
Normal file
271
tests/Protocol/Script.html
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="../../lib/OpenLayers.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
function test_constructor(t) {
|
||||||
|
t.plan(11);
|
||||||
|
var a = new OpenLayers.Protocol.Script({
|
||||||
|
url: "foo"
|
||||||
|
});
|
||||||
|
|
||||||
|
// 7 tests
|
||||||
|
t.eq(a.url, "foo", "constructor sets url");
|
||||||
|
t.eq(a.options.url, a.url, "constructor copies url to options.url");
|
||||||
|
t.eq(a.params, {}, "constructor sets params");
|
||||||
|
t.eq(a.options.params, undefined, "constructor does not copy params to options.params");
|
||||||
|
t.ok(a.format instanceof OpenLayers.Format.GeoJSON,
|
||||||
|
"constructor sets a GeoJSON format by default");
|
||||||
|
t.eq(a.callbackKey, 'callback',
|
||||||
|
"callbackKey is set to 'callback' by default");
|
||||||
|
t.eq(a.callbackPrefix, '',
|
||||||
|
"callbackPrefix is set to '' by default");
|
||||||
|
|
||||||
|
var params = {hello: "world"};
|
||||||
|
var b = new OpenLayers.Protocol.Script({
|
||||||
|
url: "bar",
|
||||||
|
params: params,
|
||||||
|
callbackKey: 'cb_key',
|
||||||
|
callbackPrefix: 'cb_prefix'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 6 tests
|
||||||
|
t.eq(b.params, params, "constructor sets params");
|
||||||
|
t.eq(b.options.params, b.params, "constructor copies params to options.params");
|
||||||
|
t.eq(b.callbackKey, 'cb_key',
|
||||||
|
"callbackKey is set to 'cb_key'");
|
||||||
|
t.eq(b.callbackPrefix, 'cb_prefix',
|
||||||
|
"callbackPrefix is set to 'cb_prefix'");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_destroy(t) {
|
||||||
|
t.plan(3);
|
||||||
|
var aborted = false;
|
||||||
|
var protocol = new OpenLayers.Protocol.Script({
|
||||||
|
url: "bar",
|
||||||
|
params: {hello: "world"},
|
||||||
|
abort: function() {
|
||||||
|
aborted = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
protocol.destroy();
|
||||||
|
t.ok(aborted, "destroy aborts request");
|
||||||
|
t.eq(protocol.params, null, "destroy nullifies params");
|
||||||
|
t.eq(protocol.format, null, "destroy nullifies format");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_read(t) {
|
||||||
|
t.plan(5);
|
||||||
|
var protocol = new OpenLayers.Protocol.Script({
|
||||||
|
'url': 'foo_url',
|
||||||
|
'params': {'k': 'foo_param'}
|
||||||
|
});
|
||||||
|
|
||||||
|
// fake XHR request object
|
||||||
|
var request = {'status': 200};
|
||||||
|
|
||||||
|
// options to pass to read
|
||||||
|
var readOptions = {
|
||||||
|
'url': 'bar_url',
|
||||||
|
'params': {'k': 'bar_param'}
|
||||||
|
};
|
||||||
|
|
||||||
|
var response;
|
||||||
|
|
||||||
|
protocol.createRequest = function(url, params, callback) {
|
||||||
|
// 4 tests
|
||||||
|
t.ok(this == protocol,
|
||||||
|
'createRequest called with correct scope');
|
||||||
|
t.ok(url == readOptions.url,
|
||||||
|
'createRequest called with correct url');
|
||||||
|
t.ok(params == readOptions.params,
|
||||||
|
'createRequest called with correct params');
|
||||||
|
t.ok(callback instanceof Function,
|
||||||
|
'createRequest called with a function as callback');
|
||||||
|
|
||||||
|
return 'foo_request';
|
||||||
|
};
|
||||||
|
|
||||||
|
var resp = protocol.read(readOptions);
|
||||||
|
|
||||||
|
t.eq(resp.priv, 'foo_request',
|
||||||
|
'response priv property set to what the createRequest method returns');
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_read_bbox(t) {
|
||||||
|
t.plan(6);
|
||||||
|
|
||||||
|
var _createRequest = OpenLayers.Protocol.Script.prototype.createRequest;
|
||||||
|
|
||||||
|
var bounds = new OpenLayers.Bounds(1, 2, 3, 4);
|
||||||
|
var filter = new OpenLayers.Filter.Spatial({
|
||||||
|
type: OpenLayers.Filter.Spatial.BBOX,
|
||||||
|
value: bounds,
|
||||||
|
projection: new OpenLayers.Projection("foo")
|
||||||
|
});
|
||||||
|
|
||||||
|
// log requests
|
||||||
|
var log, exp;
|
||||||
|
OpenLayers.Protocol.Script.prototype.createRequest = function(url, params,
|
||||||
|
callback) {
|
||||||
|
log.push(params.bbox);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 1) issue request with default protocol
|
||||||
|
log = [];
|
||||||
|
new OpenLayers.Protocol.Script().read({filter: filter});
|
||||||
|
|
||||||
|
t.eq(log.length, 1, "1) createRequest called once");
|
||||||
|
t.ok(log[0] instanceof Array, "1) bbox param is array");
|
||||||
|
exp = bounds.toArray();
|
||||||
|
t.eq(log[0], exp, "1) bbox param doesn't include SRS id by default");
|
||||||
|
|
||||||
|
// 2) issue request with default protocol
|
||||||
|
log = [];
|
||||||
|
new OpenLayers.Protocol.Script({srsInBBOX: true}).read({filter: filter});
|
||||||
|
|
||||||
|
t.eq(log.length, 1, "2) createRequest called once");
|
||||||
|
t.ok(log[0] instanceof Array, "2) bbox param is array");
|
||||||
|
exp = bounds.toArray();
|
||||||
|
exp.push("foo");
|
||||||
|
t.eq(log[0], exp, "2) bbox param includes SRS id if srsInBBOX is true");
|
||||||
|
|
||||||
|
OpenLayers.Protocol.Script.prototype.createRequest = _createRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_createRequest(t) {
|
||||||
|
t.plan(3);
|
||||||
|
var protocol = new OpenLayers.Protocol.Script({
|
||||||
|
callbackKey: 'cb_key',
|
||||||
|
callbackPrefix: 'cb_prefix:'
|
||||||
|
});
|
||||||
|
|
||||||
|
var _register = OpenLayers.Protocol.Script.register;
|
||||||
|
OpenLayers.Protocol.Script.register = function() {
|
||||||
|
return 'bar';
|
||||||
|
};
|
||||||
|
|
||||||
|
var script = protocol.createRequest('http://bar_url/', {'k': 'bar_param'}, 'bar_callback');
|
||||||
|
|
||||||
|
t.eq(script.type, 'text/javascript',
|
||||||
|
'created script has a correct type');
|
||||||
|
t.eq(script.src, 'http://bar_url/?k=bar_param&cb_key=cb_prefix%3AOpenLayers.Protocol.Script.getCallback(bar)',
|
||||||
|
'created script has a correct url');
|
||||||
|
t.eq(script.id, 'OpenLayers_Protocol_Script_bar',
|
||||||
|
'created script has a correct id');
|
||||||
|
|
||||||
|
OpenLayers.Protocol.Script.register = _register;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_destroyRequest(t) {
|
||||||
|
t.plan(2);
|
||||||
|
|
||||||
|
var protocol = new OpenLayers.Protocol.Script({});
|
||||||
|
|
||||||
|
var _unregister = OpenLayers.Protocol.Script.unregister;
|
||||||
|
OpenLayers.Protocol.Script.unregister = function(id) {
|
||||||
|
t.eq(id, 'foo', "destroyRequest calls unregister with correct id");
|
||||||
|
};
|
||||||
|
var script = {
|
||||||
|
id: 'script_foo'
|
||||||
|
};
|
||||||
|
protocol.destroyRequest(script);
|
||||||
|
t.eq(protocol.pendingRequests[script.id], null,
|
||||||
|
"destroyRequest nullifies the pending request");
|
||||||
|
|
||||||
|
OpenLayers.Protocol.Script.unregister = _unregister;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_handleResponse(t) {
|
||||||
|
t.plan(8);
|
||||||
|
|
||||||
|
var protocol = new OpenLayers.Protocol.Script();
|
||||||
|
|
||||||
|
// 2 tests (should be called only twive)
|
||||||
|
protocol.destroyRequest = function(priv) {
|
||||||
|
t.eq(priv, 'foo_priv', 'destroyRequest called with correct argument');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 test (should be called only once)
|
||||||
|
protocol.parseFeatures = function(data) {
|
||||||
|
t.eq(data, 'foo_data', 'parseFeatures called with correct argument');
|
||||||
|
return 'foo_features';
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
priv: 'foo_priv',
|
||||||
|
data: 'foo_data'
|
||||||
|
}
|
||||||
|
var options = {
|
||||||
|
// 2 tests (should be called twice)
|
||||||
|
scope: 'foo_scope',
|
||||||
|
callback: function(resp) {
|
||||||
|
t.eq(this, 'foo_scope', 'callback called with correct scope');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protocol.handleResponse(response, options);
|
||||||
|
// 2 tests
|
||||||
|
t.eq(response.code, OpenLayers.Protocol.Response.SUCCESS,
|
||||||
|
'response code correctly set');
|
||||||
|
t.eq(response.features, 'foo_features',
|
||||||
|
'response features takes a correct value');
|
||||||
|
|
||||||
|
response = {
|
||||||
|
priv: 'foo_priv'
|
||||||
|
}
|
||||||
|
protocol.handleResponse(response, options);
|
||||||
|
// 1 test
|
||||||
|
t.eq(response.code, OpenLayers.Protocol.Response.FAILURE,
|
||||||
|
'response code correctly set');
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_parseFeatures(t) {
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
var protocol = new OpenLayers.Protocol.Script();
|
||||||
|
|
||||||
|
protocol.format = {
|
||||||
|
'read': function(data) {
|
||||||
|
t.ok(true, 'format.read called');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ret = protocol.parseFeatures({foo: 'bar'});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_abort(t) {
|
||||||
|
t.plan(2);
|
||||||
|
|
||||||
|
var protocol = new OpenLayers.Protocol.Script();
|
||||||
|
|
||||||
|
// 1 test
|
||||||
|
protocol.destroyRequest = function(priv) {
|
||||||
|
t.eq(priv, 'foo_priv', 'destroyRequest called with correct argument');
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
priv: 'foo_priv'
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol.abort(response);
|
||||||
|
|
||||||
|
var calls = [];
|
||||||
|
protocol.pendingRequests = {
|
||||||
|
'foo': 'foo_request',
|
||||||
|
'bar': 'bar_request'
|
||||||
|
}
|
||||||
|
protocol.destroyRequest = function(priv) {
|
||||||
|
calls.push(priv);
|
||||||
|
}
|
||||||
|
protocol.abort();
|
||||||
|
// 1 test
|
||||||
|
t.eq(calls, ['foo_request', 'bar_request'],
|
||||||
|
'destroyRequest called for each pending requests');
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -177,6 +177,7 @@
|
|||||||
<li>Projection.html</li>
|
<li>Projection.html</li>
|
||||||
<li>Protocol.html</li>
|
<li>Protocol.html</li>
|
||||||
<li>Protocol/HTTP.html</li>
|
<li>Protocol/HTTP.html</li>
|
||||||
|
<li>Protocol/Script.html</li>
|
||||||
<li>Protocol/SimpleFilterSerializer.html</li>
|
<li>Protocol/SimpleFilterSerializer.html</li>
|
||||||
<li>Protocol/SQL.html</li>
|
<li>Protocol/SQL.html</li>
|
||||||
<li>Protocol/SQL/Gears.html</li>
|
<li>Protocol/SQL/Gears.html</li>
|
||||||
|
|||||||
Reference in New Issue
Block a user