Access elements of embedded document - javascript

I want to be able to access classes from an embedded vimeo video. My iframe looks like this:
HTML
<iframe id="vimeo" src="//player.vimeo.com/video/85509673?portrait=0&badge=0&color=a82a2a" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
I am trying to add a click event to the play-button-cell class like so:
jQuery
var embeddedContent = $("#vimeo");
console.log(embeddedContent);
var doc = embeddedContent.contentDocument; // get the inner DOM
console.log(doc);
console.log(doc.jQuery(".play-button-cell"));
doc.jQuery(".play-button-cell").click(function(){
alert('ok!');
});
and I get the following error message in the console:
Uncaught TypeError: Cannot call method 'jQuery' of undefined
play-button-cell does exist because I can see it when I "inspect element" on the play button.
How can I access a class in the embedded content? Is this possible?
DEMO

It is not do-able, unless:
Your page is hosted on vimeo.com, or
vimeo.com allows your domain to execute cross-domain interaction.
This is done for security reasons - Think... visiting a page that a person hosted. And the person placed in IFRAME on their blog, use JavaScript to post a Facebook status on your behave - That's bad, isn't it?
This security measure is called Same Origin Policy (For security reasons.) You can find more information here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript
P.S. If you debug the code, you should see $('#vimeo').contentDocument returns NULL (Or throws an exception depends on the browser you use.)

Related

How to play and pause Spotify embed with JAVASCRIPT?

Can someone explain me how can I play and pause this spotify embed object?
I have tried to find the id of the player but I couldn't.
URL → https://open.spotify.com/embed-podcast/show/5iKz9gAsyuQ1xLG6MFLtQg
This is the iframe code:
<iframe src="https://open.spotify.com/embed/show/5iKz9gAsyuQ1xLG6MFLtQg?utm_source=generator&amp&size=detail&theme=light" style="border:0px #ffffff none;" name="myiFrame" scrolling="yes" frameborder="1" marginheight="0px" marginwidth="0px" height="100%" width="100%" allowfullscreen=""></iframe>
Thanks!!
It is odd that I couldn't find this documented anywhere, but I was able to look through the embed code to figure out that it listens for postMessage events for cross-origin communication and your request is possible.
The general code would be:
// Get a reference to the embed iframe element
const spotifyEmbedWindow = document.querySelector('iframe[src*="spotify.com/embed"]').contentWindow;
spotifyEmbedWindow.postMessage({command: 'toggle'}, '*');
The above code should start the embed playing if it is paused or stopped, and pause it if it is already playing.
There are some other commands, but they probably aren't what you are looking for ('play', for example, actually restarts the player to the start of the track, and there is no explicit 'pause' command).
PS: It looks like Spotify has actually implemented this communication both ways - you can receive updates from the embed (for example, if you want to know if someone has paused it), by listening for 'message' events in the parent window.
You would use code like this, but it won't work because of cross-origin issues:
document.querySelector('iframe').contentWindow.document.body.querySelector('#play-button')
But you get: Uncaught DOMException: Permission denied to access property "document" on cross-origin object
So I believe this cannot be achieved - but I'd be happy to be proven wrong.
As of 2023, Spotify provided their own APIs to achieve play/pause/seek/etc:
https://developer.spotify.com/documentation/embeds/references/iframe-api

Cannot access iframe DOM elements without first selecting it with developer tools

I'm making a chrome extension which accesses the video elements on web pages. This is the iframe and child video element.
When attempting to get access to the iframe DOM using (this is in the content script running on the page):
function GetIframeDocument(){
var iframe = document.getElementById("vilos-player");
var doc = iframe.contentWindow.document;
var videoElement = doc.getElementByid("player_html5_api");
}
I get the error:
Uncaught DOMException: Blocked a frame with origin "https://www.crunchyroll.com" from accessing a cross-origin frame.
at <anonymous>:1:21
However, if I go into chrome developer tools and make the video element a global variable (like this). I can then apply javascript to the element in the console without running into the cross-origin frame error (as seen here).
How can I access the video element in my script without running into the error? If I can access it in the console and it can be seen in the page elements in developer tools.
I do not know what you need to do, but obviously get a link to the video.
Recommend that you inject your javascript using a chrome extension. During the creation of the extension, set the parameter
all_frames = true
https://developer.chrome.com/extensions/content_scripts
then your code will be on all pages and on iframe too.
As we can read in docs
The HTML Inline Frame element () represents a nested browsing context, embedding another HTML page into the current one.
So, iframe element has its own window object, and for access it you can use predefined method contentWindow().
See method description and W3Schools example.

Return console.log info from iframe in javascript

Have an issue where an iframe with external source loads a page with errors thrown in console. What i'm looking for is a solution to grab these errors and determine what information to show based on them. There are multiple iframes loading within the page.
So, the code outside the iframe should track and collect the console info. How can I achieve this? Thanks!
Just an example I get this error in console:
Refused to display 'http://[url]/' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.
I would like to catch this error and infrom user that the webpage could not load properly.
If you have an access to iframe's code, you can actually post messages to window.parent depending on errors and handle them on your side. Take a look at that at Mozilla's window.postMessage

iframe contentWindow not working

<script>
function getDef() {
document.getElementById("defCanvas").innerHTML=document.getElementById("invisibleDefFrame").contentWindow.document.getElementsByClassName("def-content")[0].innerText;
}
</script>
<button onclick="getDef();">Get Definition</button>
<iframe style="display:none;" id="invisibleDefFrame" src="http://dictionary.reference.com/browse/amalgamation?s=t"></iframe>
<p id="defCanvas"></p>
This is my code for a program that should return the definition of a word, but instead does nothing. What should I do to fix it? Thanks.
Because of cross-domain security, I suspect that you are not able to access the HTML of that iframe from within your own page via Javascript.
See this previous answer.
I believe that the only way to do what you are trying to do - scrape results from another website and display them on your own - is to make the request via your own web server, parse the results and present it to the user.
You can't access the iframe this way!
You will get an Uncaught SecurityError: Blocked a frame with origin
Read this detailed answer

Get IFrame innerHTML using JavaScript

I'm trying to get an IFrame inner HTML using below code.
<iframe src="http://www.msn.com"
width="100%" height="100%" marginwidth="0"
scrolling="no" frameborder="0" id="divInfo"
onreadystatechange="MyFunction(this);"></iframe>
JavaScript code is
function MyFunction(frameObj)
{
if (frameObj.readyState == "complete")
{
alert(frameObj.document.body.innerHTML);
}
}
But the alert shows me the html of current document. How can i get the inner HTML of iframe when the frmae ready state is complete.
If i use alert(frameObj.contentWindow.document.body.innerHTML); it gives me Access is denied error.
Thanks in advance.
Access is denied error is caused by the same origin policy.
Since your page is hosted on http://www.example.com/ (For example), if you try to access details on http://www.msn.com/, the browser won't let you since they are from 2 different domains.
However, if you are trying to access data from the same domain - Hosting page: http://www.example.com/index.html, IFrame's page: http://www.example.com/iframe.html, then you should be able to get the content.
For more information on the Same Origin Policy, here's a link: http://en.wikipedia.org/wiki/Same_origin_policy
BTW, you may want to use frameObject.contentDocument instead
<script type="text/javascript">
function documentIsReady(frameObject) {
alert(frameObject.contentDocument.body.innerHTML);
}
</script>
... and you can also use the onload instead of onreadystatechange...
<iframe src="iframe.html" onload="documentIsReady(this);"></iframe>
You can't read the contents of an <iframe> that has content from a different domain than that of the parent page.
You can only do that if it adheres to the same origin policy (meaning the iframe is at the same server as the parent document).
Anyway, this was answered here :)
As has been said previously, you cannot get the contents of an <iframe> if its source is not from the same origin.
This also applies to most other ways of getting external content, such as using ajax to load source code from another page. ie: $('#div').load('http://www.google.com');
To load external content, the content must comply with the same origin policy.
This means that the content must be on the same protocol and host.
Wikipedia Article Linked Above:
httpː//www.example.com/dir/page2.html --> Success Same protocol and host
httpː//www.example.com/dir2/other.html --> Success Same protocol and host
httpː//username:password#www.example.com/dir2/other.html --> Success Same protocol and host
httpː//www.example.com:81/dir/other.html --> Failure Same protocol and host but different port
https://www.example.com/dir/other.html --> Failure Different protocol
http://en.example.com/dir/other.html --> Failure Different host
http://example.com/dir/other.html --> Failure Different host (exact match required)
http://v2.www.example.com/dir/other.html --> Failure Different host (exact match required)
Simply put, it must be on the same website. So while example.com/hello.html can load content from example.com/goodbye.html, it could not load content from google.com/content.html
Also, it must be on the same domain. Sub domains are considered to VOID the same domain policy so while weebly.com/hello.html can load content from weebly.com/goodbye.html, it could not load content from user1.weebly.com/content.html
There are of course workarounds, as usual, but that's another story all together. Actually, this is quite relevant to the question. So here is a wonderful questions 'thread' on all the ways to bypass it.

Categories