diff --git a/examples/WMSPost.html b/examples/WMSPost.html new file mode 100644 index 0000000000..f7f8f92c66 --- /dev/null +++ b/examples/WMSPost.html @@ -0,0 +1,175 @@ + + + OpenLayers Basic WMS Example via HTTP-POST protocol + + + + + + +

Basic WMS Example via HTTP-POST protocol with a large SLD + included

+ +
+ +
Creating a WMS layer with a large SLD in the sld_body
+ +
+ +
+ This example uses a large SLD created on the client side to style a WMS + layer. This example uses a WMS.Post layer which transfers data via the + HTTP-POST protocol.
+ NOTE: Opera is not able to display transparent tiles with this layer, + and in some Firefox browsers can appear ugly viewport-shaking effects + while dragging arround. Use the 'unsupportedBrowsers' property to + control which browsers should use plain image tiles (like Layer.WMS) + instead. The default setting (["mozilla", "firefox", "opera"]) + excludes problematic browsers without removing the ability to use long + request parameters, because all these browsers support long urls via + GET. +
+ + diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 9898c454f1..ea7fb2477c 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -91,6 +91,7 @@ "OpenLayers/Popup.js", "OpenLayers/Tile.js", "OpenLayers/Tile/Image.js", + "OpenLayers/Tile/Image/IFrame.js", "OpenLayers/Tile/WFS.js", "OpenLayers/Layer/Image.js", "OpenLayers/Layer/SphericalMercator.js", @@ -113,6 +114,7 @@ "OpenLayers/Layer/ArcGIS93Rest.js", "OpenLayers/Layer/WMS.js", "OpenLayers/Layer/WMS/Untiled.js", + "OpenLayers/Layer/WMS/Post.js", "OpenLayers/Layer/ArcIMS.js", "OpenLayers/Layer/GeoRSS.js", "OpenLayers/Layer/Boxes.js", diff --git a/lib/OpenLayers/Layer/WMS/Post.js b/lib/OpenLayers/Layer/WMS/Post.js new file mode 100644 index 0000000000..b6b639eb67 --- /dev/null +++ b/lib/OpenLayers/Layer/WMS/Post.js @@ -0,0 +1,98 @@ +/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD + * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the + * full text of the license. */ + + +/** + * @requires OpenLayers/Layer/WMS.js + * @requires OpenLayers/Tile/Image/IFrame.js + */ + +/** + * Class: OpenLayers.Layer.WMS.Post + * Instances of OpenLayers.Layer.WMS.Post are used to retrieve data from OGC + * Web Mapping Services via HTTP-POST (application/x-www-form-urlencoded). + * Create a new WMS layer with the constructor. + * + * Inherits from: + * - + */ +OpenLayers.Layer.WMS.Post = OpenLayers.Class(OpenLayers.Layer.WMS, { + + /** + * Property: tileClass + * {Object} Class, used to create tiles. + */ + tileClass: null, + + /** + * APIProperty: unsupportedBrowsers + * {Array} Array with browsers, which should use the HTTP-GET protocol + * instead of HTTP-POST for fetching tiles from a WMS . + * Defaults to ["mozilla", "firefox", "opera"], because Opera is not able + * to show transparent images in IFrames and Firefox/Mozilla has some ugly + * effects of viewport-shaking when panning the map. Both browsers, Opera + * and Firefox/Mozilla, have no problem with long urls, which is the reason + * for using POST instead of GET. The strings to pass to this array are + * the ones returned by . + */ + unsupportedBrowsers: ["mozilla", "firefox", "opera"], + + /** + * Property: SUPPORTED_TRANSITIONS + * {Array} + * no supported transitions for this type of layer, because it is not + * possible to modify the initialized tiles (iframes) + */ + SUPPORTED_TRANSITIONS: [], + + /** + * Constructor: OpenLayers.Layer.WMS.Post + * Creates a new WMS layer object. + * + * Example: + * (code) + * var wms = new OpenLayers.Layer.WMS.Post( + * "NASA Global Mosaic", + * "http://wms.jpl.nasa.gov/wms.cgi", + * {layers: "modis, global_mosaic"}); + * (end) + * + * Parameters: + * name - {String} A name for the layer + * url - {String} Base url for the WMS + * (e.g. http://wms.jpl.nasa.gov/wms.cgi) + * params - {Object} An object with key/value pairs representing the + * GetMap query string parameters and parameter values. + * options - {Object} Hashtable of extra options to tag onto the layer. + */ + initialize: function(name, url, params, options) { + var newArguments = []; + newArguments.push(name, url, params, options); + OpenLayers.Layer.WMS.prototype.initialize.apply(this, newArguments); + + this.tileClass = OpenLayers.Util.indexOf( + this.unsupportedBrowsers, OpenLayers.Util.getBrowserName()) != -1 + ? OpenLayers.Tile.Image + : OpenLayers.Tile.Image.IFrame; + }, + + /** + * Method: addTile + * addTile creates a tile, initializes it and adds it as iframe to the + * layer div. + * + * Parameters: + * bounds - {} + * position - {} + * + * Returns: + * {} The added OpenLayers.Tile.Image.IFrame + */ + addTile: function(bounds,position) { + return new this.tileClass( + this, position, bounds, null, this.tileSize); + }, + + CLASS_NAME: 'OpenLayers.Layer.WMS.Post' +}); diff --git a/lib/OpenLayers/Tile/Image/IFrame.js b/lib/OpenLayers/Tile/Image/IFrame.js new file mode 100644 index 0000000000..8a0c9e5b68 --- /dev/null +++ b/lib/OpenLayers/Tile/Image/IFrame.js @@ -0,0 +1,260 @@ +/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD + * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the + * full text of the license. */ + + +/** + * @requires OpenLayers/Tile/Image.js + */ + +/** + * Class: OpenLayers.Tile.Image.IFrame + * Instances of OpenLayers.Tile.Image.IFrame are used to manage the image tiles + * used by Layer.WMS.Post loaded via HTTP-POST-protocol. Create a new image + * tile with the constructor. + * + * Inherits from: + * - + */ +OpenLayers.Tile.Image.IFrame = OpenLayers.Class(OpenLayers.Tile.Image, { + + /** + * Property: layerAlphaHack + * {Boolean} Always false for an instance. + */ + + /** + * Constructor: OpenLayers.Tile.Image.IFrame + * Constructor for a new instance. + * + * Parameters: + * layer - {} layer that the tile will go in. + * position - {} + * bounds - {} + * size - {} + */ + initialize: function(layer, position, bounds, url, size) { + OpenLayers.Tile.Image.prototype.initialize.apply(this, arguments); + this.layerAlphaHack = false; + }, + + /** + * Method: destroy + * nullify references to prevent circular references and memory leaks + */ + destroy: function() { + if(this.imgDiv != null) { + // unregister the "load" handler + OpenLayers.Event.stopObservingElement(this.imgDiv.firstChild); + } + OpenLayers.Tile.Image.prototype.destroy.apply(this, arguments); + }, + + /** + * Method: clear + * Removes the iframe from DOM (avoids back-button problems). + */ + clear: function() { + if(this.imgDiv) { + var iFrame = this.imgDiv.firstChild; + OpenLayers.Event.stopObservingElement(iFrame); + this.imgDiv.removeChild(iFrame); + } + }, + + /** + * Method: clone + * + * Parameters: + * obj - {} The tile to be cloned + * + * Returns: + * {} An exact clone of this + * + */ + clone: function (obj) { + if (obj == null) { + obj = new OpenLayers.Tile.Image.IFrame( + this.layer, this.position, this.bounds, this.url, this.size); + } + + //pick up properties from superclass + obj = OpenLayers.Tile.Image.prototype.clone.apply(this, [obj]); + + return obj; + }, + + /** + * Method: renderTile + */ + renderTile: function() { + if(OpenLayers.Tile.Image.prototype.renderTile.apply(this, arguments)) { + // create a html form and add it temporary to the layer div + var form = this.createRequestForm(); + this.imgDiv.appendChild(form); + + // submit the form (means fetching the image) + form.submit(); + this.imgDiv.removeChild(form); + } + }, + + /** + * Method: initImgDiv + * Creates the imgDiv property on the tile. + */ + initImgDiv: function() { + this.imgDiv = this.createImgDiv() + + OpenLayers.Util.modifyDOMElement(this.imgDiv, this.id, null, + this.layer.getImageSize(), "relative"); + this.imgDiv.className = 'olTileImage'; + + this.frame.appendChild(this.imgDiv); + this.layer.div.appendChild(this.frame); + + if(this.layer.opacity != null) { + + OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null, null, + null, null, null, + this.layer.opacity); + } + + // we need this reference to check back the viewRequestID + this.imgDiv.map = this.layer.map; + + //bind a listener to the onload of the iframe so that we + // can register when a tile has finished loading. + var onload = function() { + this.show(); + //normally isLoading should always be true here but there are some + // right funky conditions where loading and then reloading a tile + // with the same url *really*fast*. this check prevents sending + // a 'loadend' if the msg has already been sent + // + if (this.isLoading) { + this.isLoading = false; + this.events.triggerEvent("loadend"); + } + }; + }, + + /** + * Method: createImgDiv + * Creates a div with iframe.and eventPane + * + * Returns: + * {DOMElement} + */ + createImgDiv: function() { + var eventPane = document.createElement("div"); + + if(OpenLayers.Util.getBrowserName() == "msie") { + // IE cannot handle events on elements without backgroundcolor. So we + // use this little hack to make elements transparent + eventPane.style.backgroundColor = '#FFFFFF'; + eventPane.style.filter = 'chroma(color=#FFFFFF)'; + } + + OpenLayers.Util.modifyDOMElement(eventPane, null, + new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute"); + + var imgDiv = document.createElement("div"); + imgDiv.appendChild(eventPane); + return imgDiv; + }, + + /** + * Method: createIFrame + * Create the IFrame which shows the image. + * + * Returns: + * {DOMElement} Iframe + */ + createIFrame: function() { + var id = this.id+'_iFrame'; + var iframe; + if(OpenLayers.Util.getBrowserName() == "msie") { + // InternetExplorer does not set the name attribute of an iFrame + // properly via DOM manipulation, so we need to do it on our own with + // this hack. + iframe = document.createElement('