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('