IFrame.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the 2-clause BSD license.
  3. * See license.txt in the OpenLayers distribution or repository for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/Tile/Image.js
  7. */
  8. /**
  9. * Constant: OpenLayers.Tile.Image.IFrame
  10. * Mixin for tiles that use form-encoded POST requests to get images from
  11. * remote services. Images will be loaded using HTTP-POST into an IFrame.
  12. *
  13. * This mixin will be applied to <OpenLayers.Tile.Image> instances
  14. * configured with <OpenLayers.Tile.Image.maxGetUrlLength> set.
  15. */
  16. OpenLayers.Tile.Image.IFrame = {
  17. /**
  18. * Property: useIFrame
  19. * {Boolean} true if we are currently using an IFrame to render POST
  20. * responses, false if we are using an img element to render GET responses.
  21. */
  22. useIFrame: null,
  23. /**
  24. * Property: blankImageUrl
  25. * {String} Using a data scheme url is not supported by all browsers, but
  26. * we don't care because we either set it as css backgroundImage, or the
  27. * image's display style is set to "none" when we use it.
  28. */
  29. blankImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",
  30. /**
  31. * Method: draw
  32. * Set useIFrame in the instance, and operate the image/iframe switch.
  33. * Then call Tile.Image.draw.
  34. *
  35. * Returns:
  36. * {Boolean}
  37. */
  38. draw: function() {
  39. var draw = OpenLayers.Tile.Image.prototype.shouldDraw.call(this);
  40. if(draw) {
  41. // this.url isn't set to the currect value yet, so we call getURL
  42. // on the layer and store the result in a local variable
  43. var url = this.layer.getURL(this.bounds);
  44. var usedIFrame = this.useIFrame;
  45. this.useIFrame = this.maxGetUrlLength !== null &&
  46. !this.layer.async &&
  47. url.length > this.maxGetUrlLength;
  48. var fromIFrame = usedIFrame && !this.useIFrame;
  49. var toIFrame = !usedIFrame && this.useIFrame;
  50. if(fromIFrame || toIFrame) {
  51. // Switching between GET (image) and POST (iframe).
  52. // We remove the imgDiv (really either an image or an iframe)
  53. // from the frame and set it to null to make sure initImage
  54. // will call getImage.
  55. if(this.imgDiv && this.imgDiv.parentNode === this.frame) {
  56. this.frame.removeChild(this.imgDiv);
  57. }
  58. this.imgDiv = null;
  59. // And if we had an iframe we also remove the event pane.
  60. if(fromIFrame) {
  61. this.frame.removeChild(this.frame.firstChild);
  62. }
  63. }
  64. }
  65. return OpenLayers.Tile.Image.prototype.draw.apply(this, arguments);
  66. },
  67. /**
  68. * Method: getImage
  69. * Creates the content for the frame on the tile.
  70. */
  71. getImage: function() {
  72. if (this.useIFrame === true) {
  73. if (!this.frame.childNodes.length) {
  74. var eventPane = document.createElement("div"),
  75. style = eventPane.style;
  76. style.position = "absolute";
  77. style.width = "100%";
  78. style.height = "100%";
  79. style.zIndex = 1;
  80. style.backgroundImage = "url(" + this.blankImageUrl + ")";
  81. this.frame.appendChild(eventPane);
  82. }
  83. var id = this.id + '_iFrame', iframe;
  84. if (parseFloat(navigator.appVersion.split("MSIE")[1]) < 9) {
  85. // Older IE versions do not set the name attribute of an iFrame
  86. // properly via DOM manipulation, so we need to do it on our own with
  87. // this hack.
  88. iframe = document.createElement('<iframe name="'+id+'">');
  89. // IFrames in older IE versions are not transparent, if you set
  90. // the backgroundColor transparent. This is a workaround to get
  91. // transparent iframes.
  92. iframe.style.backgroundColor = '#FFFFFF';
  93. iframe.style.filter = 'chroma(color=#FFFFFF)';
  94. }
  95. else {
  96. iframe = document.createElement('iframe');
  97. iframe.style.backgroundColor = 'transparent';
  98. // iframe.name needs to be an unique id, otherwise it
  99. // could happen that other iframes are overwritten.
  100. iframe.name = id;
  101. }
  102. // some special properties to avoid scaling the images and scrollbars
  103. // in the iframe
  104. iframe.scrolling = 'no';
  105. iframe.marginWidth = '0px';
  106. iframe.marginHeight = '0px';
  107. iframe.frameBorder = '0';
  108. iframe.style.position = "absolute";
  109. iframe.style.width = "100%";
  110. iframe.style.height = "100%";
  111. if (this.layer.opacity < 1) {
  112. OpenLayers.Util.modifyDOMElement(iframe, null, null, null,
  113. null, null, null, this.layer.opacity);
  114. }
  115. this.frame.appendChild(iframe);
  116. this.imgDiv = iframe;
  117. return iframe;
  118. } else {
  119. return OpenLayers.Tile.Image.prototype.getImage.apply(this, arguments);
  120. }
  121. },
  122. /**
  123. * Method: createRequestForm
  124. * Create the html <form> element with width, height, bbox and all
  125. * parameters specified in the layer params.
  126. *
  127. * Returns:
  128. * {DOMElement} The form element which sends the HTTP-POST request to the
  129. * WMS.
  130. */
  131. createRequestForm: function() {
  132. // creation of the form element
  133. var form = document.createElement('form');
  134. form.method = 'POST';
  135. var cacheId = this.layer.params["_OLSALT"];
  136. cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
  137. form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
  138. form.target = this.id + '_iFrame';
  139. // adding all parameters in layer params as hidden fields to the html
  140. // form element
  141. var imageSize = this.layer.getImageSize(),
  142. params = OpenLayers.Util.getParameters(this.url),
  143. field;
  144. for(var par in params) {
  145. field = document.createElement('input');
  146. field.type = 'hidden';
  147. field.name = par;
  148. field.value = params[par];
  149. form.appendChild(field);
  150. }
  151. return form;
  152. },
  153. /**
  154. * Method: setImgSrc
  155. * Sets the source for the tile image
  156. *
  157. * Parameters:
  158. * url - {String}
  159. */
  160. setImgSrc: function(url) {
  161. if (this.useIFrame === true) {
  162. if (url) {
  163. var form = this.createRequestForm();
  164. this.frame.appendChild(form);
  165. form.submit();
  166. this.frame.removeChild(form);
  167. } else if (this.imgDiv.parentNode === this.frame) {
  168. // we don't reuse iframes to avoid caching issues
  169. this.frame.removeChild(this.imgDiv);
  170. this.imgDiv = null;
  171. }
  172. } else {
  173. OpenLayers.Tile.Image.prototype.setImgSrc.apply(this, arguments);
  174. }
  175. },
  176. /**
  177. * Method: onImageLoad
  178. * Handler for the image onload event
  179. */
  180. onImageLoad: function() {
  181. //TODO de-uglify opacity handling
  182. OpenLayers.Tile.Image.prototype.onImageLoad.apply(this, arguments);
  183. if (this.useIFrame === true) {
  184. this.imgDiv.style.opacity = 1;
  185. this.frame.style.opacity = this.layer.opacity;
  186. }
  187. },
  188. /**
  189. * Method: createBackBuffer
  190. * Override createBackBuffer to do nothing when we use an iframe. Moving an
  191. * iframe from one element to another makes it necessary to reload the iframe
  192. * because its content is lost. So we just give up.
  193. *
  194. * Returns:
  195. * {DOMElement}
  196. */
  197. createBackBuffer: function() {
  198. var backBuffer;
  199. if(this.useIFrame === false) {
  200. backBuffer = OpenLayers.Tile.Image.prototype.createBackBuffer.call(this);
  201. }
  202. return backBuffer;
  203. }
  204. };