| <!DOCTYPE html> |
| <html> |
| <body> |
| <style> |
| body { |
| width: 100%; |
| height: 100%; |
| margin: 0; |
| } |
| |
| iframe { |
| width: 400px; |
| height: 400px; |
| margin: 300%; |
| border: 0; |
| padding: 0; |
| overflow: scroll; |
| } |
| |
| input { |
| margin: 0; |
| padding: 0; |
| border: 0; |
| height: 1px; |
| font-size: 1px; |
| } |
| </style> |
| <p> Single <iframe> which is positioned out of view. </p> |
| <iframe> |
| </iframe> |
| <p> Iframe should be positioned way above </p> |
| <script> |
| window.loaded = false; |
| window.notifyBrowser = false; |
| const kInfinity = 1000000; |
| const kMarginOfError = 1; |
| const tinyTimeout = 50; |
| |
| window.addEventListener("load", () => { |
| document.scrollingElement.scrollTop = kInfinity; |
| document.scrollingElement.scrollLeft = kInfinity; |
| window.loaded = true; |
| if (window.notifyBrowser) |
| notifyWhenLoaded(); |
| }); |
| |
| function notifyWhenLoaded() { |
| if (loaded) |
| window.domAutomationController.send("LOADED"); |
| else |
| window.notifyBrowser = true; |
| } |
| |
| // Waits until the |visualViewport| reaches the given size (approximately). |
| // Notifies the browser when this happens. |
| function notifyVisualViewportChanged(width, height) { |
| if ((Math.abs(visualViewport.width - width) < kMarginOfError) && |
| (Math.abs(visualViewport.height - height) < kMarginOfError)) { |
| return window.domAutomationController.send("SIZED"); |
| } |
| |
| window.setTimeout(() => { |
| notifyVisualViewportChanged(width, height); |
| }, tinyTimeout); |
| } |
| |
| function isEmptyRect(rect) { |
| return (rect.width * rect.height) === 0; |
| } |
| |
| function intersect(rect1, rect2) { |
| let minX1 = rect1.x, maxX1 = minX1 + rect1.width |
| minY1 = rect1.y, maxY1 = minY1 + rect1.height, |
| minX2 = rect2.x, maxX2 = minX2 + rect2.width, |
| minY2 = rect2.y, maxY2 = minY2 + rect2.height; |
| |
| return !(isEmptyRect(rect1) || |
| isEmptyRect(rect2) || |
| (minX1 > maxX2) || |
| (minX2 > maxX1) || |
| (minY1 > maxY2) || |
| (minY2 > maxY1)); |
| } |
| |
| function visualViewportAsRect() { |
| return { |
| x: visualViewport.offsetLeft, |
| y: visualViewport.offsetTop, |
| width: Math.round(visualViewport.width), |
| height: Math.round(visualViewport.height) |
| }; |
| } |
| |
| function rectAsString(rect) { |
| return `${rect.x},${rect.y},${rect.width},${rect.height}`; |
| } |
| |
| function addFocusedInputField() { |
| var input = document.createElement("input"); |
| input.value="some text"; |
| document.body.insertBefore(input, document.body.firstChild); |
| input.focus(); |
| } |
| |
| // Waits until the given element is inside the |visualViewport|. |
| function notifyWhenVisible(el) { |
| if (intersect(el.getBoundingClientRect(), visualViewportAsRect())) { |
| window.domAutomationController.send("VISIBLE"); |
| } else { |
| window.setTimeout(() => { |
| notifyWhenVisible(el); |
| }, tinyTimeout); |
| } |
| } |
| </script> |
| </body> |
| </html> |