Tile.Image improvements and partial rewrite. Thanks erilem for the excellent collaboration during the review phase. p=me,erilem r=erilem (closes #3419)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@12241 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
+127
-155
@@ -14,14 +14,13 @@
|
||||
* remote services. Images will be loaded using HTTP-POST into an IFrame.
|
||||
*
|
||||
* This mixin will be applied to <OpenLayers.Tile.Image> instances
|
||||
* configured with <OpenLayers.Tile.Image.allowPost> or
|
||||
* <OpenLayers.Tile.Image.enforcePost> set to true.
|
||||
* configured with <OpenLayers.Tile.Image.maxGetUrlLength> set.
|
||||
*
|
||||
* Inherits from:
|
||||
* - <OpenLayers.Tile.Image>
|
||||
*/
|
||||
OpenLayers.Tile.Image.IFrame = {
|
||||
|
||||
|
||||
/**
|
||||
* Property: useIFrame
|
||||
* {Boolean} true if we are currently using an IFrame to render POST
|
||||
@@ -30,158 +29,110 @@ OpenLayers.Tile.Image.IFrame = {
|
||||
useIFrame: null,
|
||||
|
||||
/**
|
||||
* Method: clear
|
||||
* Removes the iframe from DOM (avoids back-button problems).
|
||||
* Property: blankImageUrl
|
||||
* {String} This is only used as background image for the eventPane, so we
|
||||
* don't care that this doesn't actually result in a blank image on all
|
||||
* browsers
|
||||
*/
|
||||
clear: function() {
|
||||
if (this.useIFrame) {
|
||||
if (this.imgDiv) {
|
||||
var iFrame = this.imgDiv.firstChild;
|
||||
OpenLayers.Event.stopObservingElement(iFrame);
|
||||
this.imgDiv.removeChild(iFrame);
|
||||
delete iFrame;
|
||||
}
|
||||
} else {
|
||||
OpenLayers.Tile.Image.prototype.clear.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
blankImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",
|
||||
|
||||
/**
|
||||
* Method: renderTile
|
||||
* Method: updateBackBuffer
|
||||
* Update the <backBufferData>, and return a new or reposition the
|
||||
* backBuffer. When a backbuffer is returned, the tile's markup is not
|
||||
* available any more.
|
||||
*
|
||||
* Returns:
|
||||
* {HTMLDivElement} the tile's markup in a cloned element, or undefined if
|
||||
* no backbuffer is currently available or needed
|
||||
*/
|
||||
renderTile: function() {
|
||||
if (OpenLayers.Tile.Image.prototype.renderTile.apply(this, arguments) &&
|
||||
this.useIFrame) {
|
||||
// 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);
|
||||
delete form;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: initImgDiv
|
||||
* Creates the imgDiv property on the tile.
|
||||
*/
|
||||
initImgDiv: function() {
|
||||
updateBackBuffer: function() {
|
||||
this.url = this.layer.getURL(this.bounds);
|
||||
var usedIFrame = this.useIFrame;
|
||||
this.useIFrame = this.maxGetUrlLength !== null && !this.layer.async &&
|
||||
this.url.length > this.maxGetUrlLength;
|
||||
if (this.imgDiv != null) {
|
||||
var nodeName = this.imgDiv.nodeName.toLowerCase();
|
||||
if ((this.useIFrame && nodeName == "img") ||
|
||||
(!this.useIFrame && nodeName == "div")) {
|
||||
// switch between get and post
|
||||
this.removeImgDiv();
|
||||
this.imgDiv = null;
|
||||
var fromIFrame = usedIFrame && !this.useIFrame;
|
||||
var toIFrame = !usedIFrame && this.useIFrame;
|
||||
if (fromIFrame || toIFrame) {
|
||||
// switch between get (image) and post (iframe)
|
||||
this.clear();
|
||||
if (this.imgDiv && this.imgDiv.parentNode === this.frame) {
|
||||
this.frame.removeChild(this.imgDiv);
|
||||
}
|
||||
this.imgDiv = null;
|
||||
if (fromIFrame) {
|
||||
// remove eventPane
|
||||
this.frame.removeChild(this.frame.firstChild);
|
||||
this.resetBackBuffer();
|
||||
}
|
||||
}
|
||||
if (this.useIFrame) {
|
||||
if (this.imgDiv == null) {
|
||||
var eventPane = document.createElement("div");
|
||||
|
||||
if(OpenLayers.BROWSER_NAME == "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");
|
||||
|
||||
this.imgDiv = document.createElement("div");
|
||||
this.imgDiv.appendChild(eventPane);
|
||||
|
||||
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;
|
||||
}
|
||||
this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
|
||||
|
||||
} else {
|
||||
OpenLayers.Tile.Image.prototype.initImgDiv.apply(this, arguments);
|
||||
if (!this.useIFrame) {
|
||||
OpenLayers.Tile.Image.prototype.updateBackBuffer.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createIFrame
|
||||
* Create the IFrame which shows the image.
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} Iframe
|
||||
*/
|
||||
createIFrame: function() {
|
||||
var id = this.id+'_iFrame';
|
||||
var iframe;
|
||||
if(OpenLayers.BROWSER_NAME == "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('<iframe name="'+id+'">');
|
||||
|
||||
// IFrames in InternetExplorer are not transparent, if you set the
|
||||
// backgroundColor transparent. This is a workarround to get
|
||||
// transparent iframes.
|
||||
iframe.style.backgroundColor = '#FFFFFF';
|
||||
iframe.style.filter = 'chroma(color=#FFFFFF)';
|
||||
}
|
||||
else {
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.style.backgroundColor = 'transparent';
|
||||
|
||||
// iframe.name needs to be an unique id, otherwise it
|
||||
// could happen that other iframes are overwritten.
|
||||
iframe.name = id;
|
||||
}
|
||||
iframe.id = id;
|
||||
|
||||
// some special properties to avoid scaling the images and scrollbars
|
||||
// in the iframe
|
||||
iframe.scrolling = 'no';
|
||||
iframe.marginWidth = '0px';
|
||||
iframe.marginHeight = '0px';
|
||||
iframe.frameBorder = '0';
|
||||
|
||||
OpenLayers.Util.modifyDOMElement(iframe, id,
|
||||
new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
|
||||
|
||||
//bind a listener to the onload of the iframe so that we
|
||||
// can register when a tile has finished loading.
|
||||
var onload = function() {
|
||||
//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");
|
||||
}
|
||||
};
|
||||
OpenLayers.Event.observe(iframe, 'load',
|
||||
OpenLayers.Function.bind(onload, this));
|
||||
|
||||
return iframe;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createImage
|
||||
* Creates the content for the frame on the tile.
|
||||
*/
|
||||
createImage: function() {
|
||||
if (this.useIFrame === true) {
|
||||
if (!this.frame.childNodes.length) {
|
||||
var eventPane = document.createElement("div"),
|
||||
style = eventPane.style;
|
||||
style.position = "absolute";
|
||||
style.width = "100%";
|
||||
style.height = "100%";
|
||||
style.zIndex = 1;
|
||||
style.backgroundImage = "url(" + this.blankImageUrl + ")";
|
||||
this.frame.appendChild(eventPane);
|
||||
}
|
||||
|
||||
var id = this.id + '_iFrame', iframe;
|
||||
if (parseFloat(navigator.appVersion.split("MSIE")[1]) < 9) {
|
||||
// Older IE versions do 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('<iframe name="'+id+'">');
|
||||
|
||||
// IFrames in older IE versions are not transparent, if you set
|
||||
// the backgroundColor transparent. This is a workaround to get
|
||||
// transparent iframes.
|
||||
iframe.style.backgroundColor = '#FFFFFF';
|
||||
iframe.style.filter = 'chroma(color=#FFFFFF)';
|
||||
}
|
||||
else {
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.style.backgroundColor = 'transparent';
|
||||
|
||||
// iframe.name needs to be an unique id, otherwise it
|
||||
// could happen that other iframes are overwritten.
|
||||
iframe.name = id;
|
||||
}
|
||||
|
||||
// some special properties to avoid scaling the images and scrollbars
|
||||
// in the iframe
|
||||
iframe.scrolling = 'no';
|
||||
iframe.marginWidth = '0px';
|
||||
iframe.marginHeight = '0px';
|
||||
iframe.frameBorder = '0';
|
||||
|
||||
iframe.style.position = "absolute";
|
||||
iframe.style.width = "100%";
|
||||
iframe.style.height = "100%";
|
||||
|
||||
if (this.layer.opacity < 1) {
|
||||
OpenLayers.Util.modifyDOMElement(iframe, null, null, null,
|
||||
null, null, null, this.layer.opacity);
|
||||
}
|
||||
this.frame.appendChild(iframe);
|
||||
this.imgDiv = iframe;
|
||||
return iframe;
|
||||
} else {
|
||||
return OpenLayers.Tile.Image.prototype.createImage.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createRequestForm
|
||||
* Create the html <form> element with width, height, bbox and all
|
||||
@@ -198,20 +149,16 @@ OpenLayers.Tile.Image.IFrame = {
|
||||
var cacheId = this.layer.params["_OLSALT"];
|
||||
cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
|
||||
form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
|
||||
|
||||
// insert the iframe, which has been removed to avoid back-button
|
||||
// problems
|
||||
this.imgDiv.insertBefore(this.createIFrame(), this.imgDiv.firstChild);
|
||||
|
||||
form.target = this.id+'_iFrame';
|
||||
form.target = this.id + '_iFrame';
|
||||
|
||||
// adding all parameters in layer params as hidden fields to the html
|
||||
// form element
|
||||
var imageSize = this.layer.getImageSize();
|
||||
var params = OpenLayers.Util.getParameters(this.url);
|
||||
var imageSize = this.layer.getImageSize(),
|
||||
params = OpenLayers.Util.getParameters(this.url),
|
||||
field;
|
||||
|
||||
for(var par in params) {
|
||||
var field = document.createElement('input');
|
||||
field = document.createElement('input');
|
||||
field.type = 'hidden';
|
||||
field.name = par;
|
||||
field.value = params[par];
|
||||
@@ -219,6 +166,31 @@ OpenLayers.Tile.Image.IFrame = {
|
||||
}
|
||||
|
||||
return form;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: setImgSrc
|
||||
* Sets the source for the tile image
|
||||
*
|
||||
* Parameters:
|
||||
* url - {String}
|
||||
*/
|
||||
setImgSrc: function(url) {
|
||||
if (this.useIFrame === true) {
|
||||
if (url) {
|
||||
var form = this.createRequestForm();
|
||||
this.frame.appendChild(this.imgDiv);
|
||||
this.frame.appendChild(form);
|
||||
form.submit();
|
||||
this.frame.removeChild(form);
|
||||
} else if (this.imgDiv.parentNode === this.frame) {
|
||||
// we don't reuse iframes to avoid caching issues
|
||||
this.frame.removeChild(this.imgDiv);
|
||||
this.imgDiv = null;
|
||||
}
|
||||
} else {
|
||||
OpenLayers.Tile.Image.prototype.setImgSrc.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user