[OpenLayers-Commits] r10940 - in sandbox/tschaub/xdomain: examples lib lib/OpenLayers/Protocol

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Wed Dec 1 17:47:34 EST 2010


Author: tschaub
Date: 2010-12-01 14:47:34 -0800 (Wed, 01 Dec 2010)
New Revision: 10940

Added:
   sandbox/tschaub/xdomain/examples/cross-origin.html
   sandbox/tschaub/xdomain/examples/cross-origin.js
   sandbox/tschaub/xdomain/lib/OpenLayers/Protocol/Script.js
Modified:
   sandbox/tschaub/xdomain/lib/OpenLayers.js
Log:
Look ma, no proxy!

Added: sandbox/tschaub/xdomain/examples/cross-origin.html
===================================================================
--- sandbox/tschaub/xdomain/examples/cross-origin.html	                        (rev 0)
+++ sandbox/tschaub/xdomain/examples/cross-origin.html	2010-12-01 22:47:34 UTC (rev 10940)
@@ -0,0 +1,33 @@
+<!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">
+        <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>

Added: sandbox/tschaub/xdomain/examples/cross-origin.js
===================================================================
--- sandbox/tschaub/xdomain/examples/cross-origin.js	                        (rev 0)
+++ sandbox/tschaub/xdomain/examples/cross-origin.js	2010-12-01 22:47:34 UTC (rev 10940)
@@ -0,0 +1,29 @@
+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"
+                }
+            })
+        })
+    ],
+    center: new OpenLayers.LonLat(0, 0),
+    zoom: 1
+});
+

Added: sandbox/tschaub/xdomain/lib/OpenLayers/Protocol/Script.js
===================================================================
--- sandbox/tschaub/xdomain/lib/OpenLayers/Protocol/Script.js	                        (rev 0)
+++ sandbox/tschaub/xdomain/lib/OpenLayers/Protocol/Script.js	2010-12-01 22:47:34 UTC (rev 10940)
@@ -0,0 +1,361 @@
+/* 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/Protocol/Script.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();
+        }
+    },
+    
+    /**
+     * 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 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) {
+            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;
+    },
+    
+    /**
+     * Method: filterToParams
+     * Convert an <OpenLayers.Filter> object to parameters.
+     *
+     * Parameters:
+     * filter - {OpenLayers.Filter} filter to convert.
+     * params - {Object} The parameters object.
+     *
+     * Returns:
+     * {Object} The resulting parameters object.
+     */
+    filterToParams: function(filter, params) {
+        return OpenLayers.Protocol.HTTP.prototype.filterToParams.apply(
+            OpenLayers.Protocol.HTTP.prototype, arguments
+        );
+    },
+    
+    /** 
+     * 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;
+    };    
+})();
+

Modified: sandbox/tschaub/xdomain/lib/OpenLayers.js
===================================================================
--- sandbox/tschaub/xdomain/lib/OpenLayers.js	2010-12-01 22:45:21 UTC (rev 10939)
+++ sandbox/tschaub/xdomain/lib/OpenLayers.js	2010-12-01 22:47:34 UTC (rev 10940)
@@ -215,6 +215,7 @@
             "OpenLayers/Filter/Spatial.js",
             "OpenLayers/Protocol.js",
             "OpenLayers/Protocol/HTTP.js",
+            "OpenLayers/Protocol/Script.js",
             "OpenLayers/Protocol/SQL.js",
             "OpenLayers/Protocol/SQL/Gears.js",
             "OpenLayers/Protocol/WFS.js",



More information about the Commits mailing list