Can't access canvas element in iframe - javascript

I got a iframe and I want to select a canvas element in this iframe. But it doesn't work. I'm using the following code.
This is my iframe
<body>
<div id="canvasdiv" width="300" height="300"></div>
</body>
This is my parent page
<iframe name="iframe" id="iframe" frameborder="0" width="325" height="325" src="..."></iframe>
With javascript I add a canvas with some properties. For example the id.
canvas.node.id = "canvas";
In my parent page I got the following javascript.
var iframe = document.getElementById("iframe");
alert(iframe);
var iframe_canvas = iframe.contentDocument || iframe.contentWindow.document;
alert(iframe_canvas);
var canvas = iframe_canvas.getElementById("canvas");
alert(canvas);
Result:
iframe = iframe element
iframe_canvas = html element
canvas = null
Does somebody know why I can't access the canvas element? =(

I'm sorry, but I solved the problem. Thanks for all the replies. =)
To test the getElementById function I called it by $(document).ready. But at this time the iframe wasn't rendered by the browser. That's why I could access the iframe it self but not the elements of the iframe. Now I assigned the function to a button and it works.

According to your HTML, this line of code:
var canvas = iframe_canvas.getElementById("canvas");
should be this to target the proper id value in your div:
var canvas = iframe_canvas.getElementById("canvasdiv");

You're omitting the code that adds the <canvas> element itself. Are you sure its id is canvas?
If you are, then you might be running into same-origin policy problems regarding accessing contents of iframes.

your code is fine expect for one part.
replace
getElementById("canvas")
with
getElementById("canvasdiv");

Related

Adobe XD embedded app-prototype causes page to 'jump' down to mid-page after loading

I use Squarespace for my portfolio site. They have a "block" that allows me to use embedded Adobe XD code (below) to show my app prototype. The prototype works fine but when the page loads, it automatically shifts half way down the page to the prototype. link to page
<center>
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0">
</iframe>
</center>
I would like for my page to remain at the top when fully loaded instead of jumping down mid-page to the prototype. I've tried countless solutions such as using sandbox, lazy loading, and loading on scroll view. I've tried using "data src=""" as well among other options.
Unfortunately none of these solutions worked. The only time it doesn't jump down to the prototype is when it doesn't load at all (which happened with lazy loading, loading on scroll). How can I fix this? I'm able to use HTML, CSS, and JavaScript as well.
My best guess is to delay loading the prototype until it's in view. The only other option would be placing the prototype at the top of the page, which is not what I want (it messes up the flow of the project).
Any help is greatly appreciated!
Option 1: Use the "sandbox" attribute.
This appears to be a known issue within the Adobe Community site, with a solution proposed using the sandbox iframe attribute.
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0" sandbox="allow-same-origin allow-forms allow-scripts"></iframe>
Or, possibly even more restrictive (which may cause the iframe not to work):
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0" sandbox></iframe>
Option 2: Use the "onload" attribute with "scroll()"
If neither of the above work, you could try using the onload attribute to force the scroll position:
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0" onload="scroll(0,0);"></iframe>
Option 3: Load the iframe only when in view.
If neither option 1 or 2 work, you could only load the iframe once it is already in view for the user (once they have scrolled down). For browsers that don't support IntersectionObserver, keep the external link as you have it. For browsers that do, hide the link and load the iframe. Insert the following via a code block above the image block that has your external link:
<iframe id="nautilab" width="0" height="0" frameborder="0" allowFullScreen></iframe>
Then insert the following via sitewide footer code injection
<script>
(function() {
var target,
io,
ioCallback,
ioOptions,
linkBlock;
// Exit if id "nautilab" not found.
target = document.querySelector('#nautilab');
if (!target) {
return;
}
// Check for IntersectionObserver Support: https://github.com/w3c/IntersectionObserver/issues/296#issuecomment-452230176
if (!('IntersectionObserver' in window) ||
!('IntersectionObserverEntry' in window) ||
!('intersectionRatio' in window.IntersectionObserverEntry.prototype)) {
target.style.display = "none";
return;
}
// Because IntersectionObserver is supported, hide external link to prototype.
linkBlock = document.querySelector('#block-yui_3_17_2_1_1574114822673_377170');
linkBlock.style.display = "none";
// Loads the iframe when the 'target' is in view.
ioCallback = function(entries, observer) {
entries.forEach(function(entry) {
if (entry.intersectionRatio) {
observer.disconnect();
target.height = "736"
target.width = "414";
target.src = "https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982";
}
});
};
ioOptions = {
root: null,
rootMargin: "0px",
threshold: 1
};
// Observe for 'target' to be in view.
io = new IntersectionObserver(ioCallback, ioOptions);
io.observe(target);
})();
</script>
You'll still have to center the prototype using CSS, which shouldn't be too difficult.

Encoded URI doesn't work like the src attribute for iframe in IE11

I try to generate src attribute for the iframe on the fly doing this:
var iframe = document.createElement('iframe');
var html = '<html> <head></head> <body></body> </html>';
var eventListener = '<script>window.addEventListener("message", someListenerFunction)</script>';
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html) + encodeURI(eventListener);
iframe.sandbox = 'allow-scripts';
This actually works fine in chrome/firefox/safari, but it doesn't work with ie11. Inside the iframe window it returns:
Cannot display the webpage
And in the console I get the error:
SCRIPT5: Access is denied.
File: unknowprotocol.htm, Line:1, Column:1
The problem I think in the encoded URI address.
The reason I do this - I need to generate lots of iframes and I don't want to create a static webpages for each of them.
Hope for your help. Thank you in advance.

Need to disable Javascript within an iFrame

I'm building a portfolio site; it's a one pager with a lightbox functionality. So, basically I am showing HTML5 ads I have built, which I am embedding in an iFrame. These ads have audio, so when I close out of the lightbox the audio continues to play. Now I have tried different methods but have been unsuccessful. I have tested one method which worked, where I removed the src of the iFrame (ONE iFrame which I assigned an ID). Like so:
**HTML:**
<iframe id="test" class="iframe-src" src="media/rogue-nation/300x250-progressive-post/index.html" width="300" height="250" style="border:none"></iframe>
**JavaScript:**
var test;
var lightbox;
test = document.getElementById('test');
lightbox = document.getElementById('lightbox');
lightbox.addEventListener("click", closeLightbox, false);
function closeLightbox() {
...
test.src = "none";
}
So...my questions are:
What is the "best" way to apply this method to each iFrame depending on which one was interacted with (tried, getElementsByClassName but was unsuccessful)
Is there a way to disable the scripts within an iFrame so I don't have to use this method, as I am not so crazy about it
Also, please don't post jQuery solutions or advise me to use jQuery, as it will not be helpful because I am writing plain JavaScript
Thanks in advance!
If your iframe content lives on the same domain it is easy. You could do something like this when your lightbox closes:
function closeLightbox() {
// get the iframe which is playing audio
var iframe = document.getElementById('iframe');
// make sure you can reference the audio element on the iframe
// e.g. with an id.
var sound = iframe.contentWindow.document.getElementById('sound');
sound.pause();
sound.currentTime = 0;
// then close the lightbox with some other code
// ...
}
JSBin Demo

Onload iframe in Javascript wont work

<body style="margin:0px;padding:0px;overflow:hidden" onload="img.src='http://sjabbo.net/logo.png?'+(+new Date())">
<img id="img"
onload="iframe.src='http://sjabbo.net'"
onerror="iframe.src='offline.html'"
width="0px" height="0px">
<iframe width="100%" height="1000px"></iframe>
</body>
So, if the local user has an internet connection, then the iframe should change to "http://sjabbo.net" but if not, then "offline.html"
but it does not seem to work.
How about this:
<body style="margin:0px;padding:0px;overflow:hidden">
<img id="img" src="http://sjabbo.net/logo.png"
onload="document.getElementById('iframe').src='http://sjabbo.net'"/>
<iframe src="offline.html" id="iframe" width="100%" height="1000px"></iframe>
</body>
You could introduce "testing" page like this:
<body style="margin:0px;padding:0px;overflow:hidden">
<img id="img" src="http://sjabbo.net/logo.png"
onload="document.getElementById('iframe').src='http://sjabbo.net'"
onerror="document.getElementById('iframe').src='offline.html'"/>
<iframe src="testing.html" id="iframe" width="100%" height="1000px"></iframe>
</body>
First, you can't just use "img", because, to JavaScript, it's not defined anywhere globally. If you want to access the image by its ID, you need to do the following. Also, I'm guessing you want to have a timestamp instead of the long date. Put something like this in your onload:
document.getElementById('img').src = 'http://sjabbo.net/logo.png?' + (new Date()).getTime()
Do the same with your iframe (you'll have to assign it an ID first).
I don't think you've understood how web works.
You don't need to add an onload to every element that has a child. Each element is created one after another. So for now remove all your onloads.
You seem to want to wait to know if your image gets loaded correctly or not. Depending on this you want to activate your iframe.
You'll want to create a javascript tag ( or for good practice, create a js file ).
var img = document.getElementById('img'),
iframe = document.getElementById('iframe'); //add iframe as an id to your iframe
img.onload = function(){
//this is called when the image is finished loading.
iframe.src = 'http://sjabbo.net';
};
img.onerror = function(){
//this is called when the image wasn't able to load properly
iframe.src = 'offline.html'; //To be honest this doesn't make much sense
//You should instead just hide the iframe and the image
iframe.style.visibility = 'none';
img.style.visibility = 'none';
};
img.src = 'http://sjabbo.net/logo.png?' + (new Date()).getTime();
For future programming please try to seperate your js and css from your html. It is not good practice what you are currently doing.

Update textures in X3DOM model dynamically

I am developing a Web 3D app and I produced some code in Javascript that implements the following tag to an external .html file with the model in it, within an iframe.
In the <appearance> element in the X3D code block of the external .html file:
<texture id="XXX" repeats="true" repeatt="true" url="" scale="true"
hidechildren="true">
<img src="" attr=".../BMW.jpg" style="display: none; visibility: hidden;">
</texture>
Javascript code that places the above code in the appropriate block in the iframe after I click on a button:
ogl = true;
function toggleTexture(){
if (!ogl) {
var t = document.createElement("Texture");
t.setAttribute("id", "XXX");
t.setAttribute("repeatS", "true");
t.setAttribute("repeatT", "true");
var imgElement = document.createElement("img");
imgElement.setAttribute("src", "../HomeFurniture/assets/BMW.jpg");
t.appendChild(imgElement);
var iframe = document.getElementById("frame");
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
innerDoc.getElementById("anApp").appendChild(t);
innderDoc.x3dom.reload();
} else {
var iframe = document.getElementById("frame");
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
var ot = innerDoc.getElementById("anApp");
ot.removeChild(innerDoc.getElementById('XXX'));
}
return false;
}
The result in the debugging of Chrome browser shows that the piece of code needed is inserted, but the actual model is not updated with the appropriate texture.
There must be something that I miss, but I cannot find the solution. Any help would be appreciated.
FIXED: The problem was Google Chrome. I tested the Web app in Mozilla Firefox and everything works :)
Additionally, I tried the Javascript code in the child html file and it works in Chrome. It just refuses to work when the parent html file load the child html file within an iframe block.

Categories