document.querySelector works in console but not on realtime - javascript

I'm creating a simple html page with one audio player inside an iframe.
I need to enamble kind of autoplay for desktop and mobile.
The player is this one:
<div style="width: 100%"><iframe src="https://players.rcast.net/fixedbar1/66549" frameborder="0" scrolling="no" autoplay style="width: 100%"></iframe></div>
I put this block on the bottom of the html page:
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready
setTimeout(function(){
document.querySelector('.play-btn').click();
},3000); //delay is in milliseconds
});
</script>
Using firefox console document.querySelector('.play-btn').click(); works fine, but on runtime i get:
Uncaught TypeError: document.querySelector(...) is null
Any ideas or best ways?
Thanks,
Red

You can do whatever you want in the console but you would only be able to access iframe content programmatically if your iframe domain matches your current domain.
That being said, you can:
Select the iframe, then run query selector on the iframe (you don't even need jQuery for it):
const iframeElement = document.querySelector('iframe');
iframeElement.querySelector('.play-btn').click();
Tips:
You can also play the video/music directly by calling play() on
the media elements. So you can cut out stimulating click on
the button.
querySelector is slower than getElementById, you can assign an id attribute to your iframe/button/media element and find it directly.
It will also help you avoid bugs because querySelector returns the first match. So in case you have multiple iframe or multiple elements with the class .play-btn, it can lead to unexpected behaviour.

you should select iframe at first and get its content window to access all elements on it.
const myIframe = document.querySelector('#iframe_id')
const myIframeDocument =myIframe.contentWindow.document
const myElement = myIframeDocument.body.querySelector('#target_element')
it is noticeable that the iframe should be loaded completely before your process and also domain conflict

Hope this helps:
<iframe id="video1" width="450" height="280" src="http://www.youtube.com/embed/TJ2X4dFhAC0?enablejsapi" frameborder="0" allowtransparency="true" allowfullscreen></iframe>
Play button
<script>
$("#playvideo").click(function(){
$("#video1")[0].src += "?autoplay=1";
});
</script>
I found this on Grepper, but it was from another Stack Overflow post.
If that doesn't help I found a different post that seems to be more related to the error.

Related

Can't attach mousedown event to embed element

I seem to have hit a wall with this crap and can't make sense of it. I have a page with a relatively complex SVG (it has 6 other smalled SVGs embedded into it) in it embeded inside embed tag. When I try to attach a mousedown event to it, it simply doesn't work. Here is the markup:
<body>
<embed type="image/svg+xml" src="images/cog.svg" id="cog">
</embed>
</body>
then in javascript I do
$(function(){
var cog = document.getElementById("cog");
document.addEventListener('mousedown', function(e){
console.log(e);
});
});
It doesn't work. Moreover when i attach events to document, they do not fire when I click on that embed object either!
I searched this thing for 3 hours and everywhere I look it appears as if the embed should support mousedown even without any problem. What is the problem here?
Edit:
If it's any help here is how the full markup looks like (I use Foundation framework):
If CORS aren't an issue, you can try :
document.querySelector('embed').addEventListener('load', function(){
this.getSVGDocument().addEventListener('mousedown', function(){
alert('hello')});
});
According to the specs:
3 . If the previous step determined that the content's type is
image/svg+xml, then run the following substeps:
If the embed element is not associated with a nested browsing context, associate the element with a newly created nested browsing context,[...]
Navigate the nested browsing context to the fetched resource, with replacement enabled, and with the embed element's node document's
browsing context as the source browsing context. (The src attribute of
the embed element doesn't get updated if the browsing context gets
further navigated to other locations.)
The embed element now represents its associated nested browsing context.
But I can't find anything about actually how it should handle events.
Nevertheless, it appears that when its src is set and returns something, the events are captured by the new context (whether reached or created).
See #Marius comment for a demo when no src is set, it fires the event.
I think the embed tag is sandboxed and can't be accessed from external sources. Just use the img tag.
$('#logo').click(function() {
alert('410');
});
img{
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>Click the SVG</h3>
<img id='logo' src="http://dev.w3.org/SVG/tools/svgweb/samples/svg-files/410.svg">

Accessing Iframe Variable in Parent With Javascript

I'm aware there are incredibly similar questions on Stack Overflow already for this, but I've tried MANY of them, and am just getting nothing. I'm trying to grab a variable from the child iframe to use in the parent window.
In child.html head tag
<script type="text/javascript">
var myVar="1";
</script>
In parent.html
<script type="text/javascript">
function load()
{
var scroll="0";
scroll = window.myIframe.myVar;
if (scroll == "0") DO SOMETHING;
else DO SOMETHING ELSE;
}
</script>
<iframe src="child.html" name="myIframe" onload="load()">
<p>Your browser does not support iframes.</p>
</iframe>
And no matter what I try, I cannot get scroll to grab the myVar variable from the child iframe. This is nearly verbatim of examples on Stack Overflow and other forums that people say work perfectly; any ideas what I'm doing wrong?
Edit: They are on the same domain.
Try to access oad() from inside child when the page loads in iframe.
Add in child:
<body onload="parent.load()">
Also, you can change the code to pass and get the variable as parameter in load(prm) .
I tried your code offline and i get an error "unsafe access" while accessing
window.myFrame
local pages can be tricky, however when i put the same files online they work well, domains and ports match.
still i think its a bit weird using name="..." on the iframe, i would be using ID, but that doesn't seem to bother chrome and i got access to the variable with either onload on parent or child.

Can I call a function after the loading of an iframe appended by jquery?

This is my code :
​<div id="myContent​​​​​​​"></div>​
$('#myContent').html('<iframe height="200" frameborder="0" src="www.google.com"></iframe>');​
and I'd like, when the whole page in the frame is totally loaded, call a function, like alert("I'm finished");.
How can I do it?
P.S. dunno why jsfiddle doesnt catch the google page :)
You can do it with the event .load() (Check the api for more info).
Example:
$('#myContent').html('<iframe id="winId" height="200" frameborder="0" src="www.google.com"></iframe>');
$('#winId').load(function() {alert('loaded')})
In a nutshell, unless the iframe has the source url on the same domain/subdomain, checking if it has loaded completely, or expecting any kind of events to be propogated from a frame to the parent window is not possible.
The same domain policy clearly stops developers from doing such stuff.
Though there are a few workarounds ,e.g the code inside the iframe can change its url and keep passing information using hash tags and vice-a-versa.
Create the element, then attach the load event:
var frame = $('<iframe height="200" frameborder="0" src=http://www.google.com />');
$('body').append(frame);
frame.load(function(){
alert('loaded');
});
fiddle:
http://jsfiddle.net/x7EXa/
$('#myContent').html('<iframe height="200" frameborder="0" src="www.google.com" onload="myfunc()"></iframe>');
you should have in the page containing the IFRAME :
function myfunc()
{
alert('.......');
}
edit : the following will Not work.
$('#myContent').on('load','#myIdframe',function (){alert('.....');});
since :
From the documentation: In all browsers, the load event does not bubble. [...] Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event.
heres 2 examples :
1 work and 1 doesn't
http://jsbin.com/emuzop/2/edit#javascript,html
http://jsbin.com/emuzop/3/edit#javascript,html

Stop a Vimeo Video with Jquery

I need to stop a Vimeo video embedded with new oembed api (universal player) but when I try to add an event I get this error:
Uncaught TypeError: Object #<an HTMLIFrameElement> has no method 'addEvent'
But I don't why I get this error, I added jquery and the frogaloop api, also I added ids to the iframes, but it still doesn't work: :(
The full code is here:
http://tv.bisaccia.info
Eli, please edit your post. As Joe said, you are partially misinformed. While postMessage is needed for cross-domain communication, it is implemented through a DOM method added by a call to "Froogaloop.init();"
is_embed_iframe = _this.iframe_pattern.test(cur_frame.getAttribute('src'));
if (is_embed_iframe) {
cur_frame.api = _that.api;
cur_frame.get = _that.get;
cur_frame.addEvent = _that.addEvent;
}
Note: you will need to grab froogaloop.js (or the min variant) from the Vimeo site.
Be sure the iFrame "src" is set prior to calling init(), otherwise froogaloop will do nothing.
As per Mike's suggestion, invoking:
Froogaloop.init();
Does make the control API work. In my case:
<iframe id="player_1" src="http://player.vimeo.com/video/26859570?js_api=1&js_swf_id=player_1&title=0&byline=0&portrait=0" width="620" height="354" frameborder="0"></iframe>
<script>
$(document).ready(function() {
Froogaloop.init();
$("#player_1").moogaloop({
load: function(element) {
$("#segment1").click(function() { element.moogaloop('seekTo', "7"); });
}
});
});
</script>
Weird... Moogaloop's author demo page does work without the init() call. Anyway, worked for me.
Thanks for your time!
This is not the correct answer, but may work for your situation as it did for mine. I simply wanted to stop my Vimeo from playing when I closed its containing DOM element. I was collapsing its container and that hid it visually but the audio continued to play and use browser resources unnecessarily.
What I do now is simply store the iframe in a variable, remove it from the DOM, then replace it immediately. I have NOT tested across browsers, only the latest version of Chrome and Safari Mobile.
var container = $("#VimeoContainer");
var iframe = container.find("iframe");
iframe.remove();
container.append(iframe);
Again, Froogaloop is really the way to go, however I've had issues with it in the past so for this situation I was looking for something simple. Obviously you could do this without JQuery with the same results.
You can't.
There's no DOM addEvent method.
You don't have cross-domain access to Vimeo, so you are not permitted to have JavaScript interface with the iframe's document or abstract view.
If you wanted to interface with Vimeo via JavaScript, you would have to get them to implement a postMessage API that also accepts your domain.

Reload an IFRAME without adding to the history

I'm changing an IFRAME's src in order to reload it, its working fine and firing the onload event when its HTML loads.
But it adds an entry to the history, which I don't want. Is there any way to reload an IFRAME and yet not affect the history?
Using replace() is only an option with your own domain iframes. It fails to work on remote sites (eg: a twitter button) and requires some browser-specific knowledge to reliably access the child window.
Instead, just remove the iframe element and construct a new one in the same spot. History items are only created when you modify the src attribute after it is in the DOM, so make sure to set it before the append.
Edit: JDandChips rightly mentions that you can remove from DOM, modifiy, and re-append. Constructing fresh is not required.
You can use javascript location.replace:
window.location.replace('...html');
Replace the current document with the
one at the provided URL. The
difference from the assign() method is
that after using replace() the current
page will not be saved in session
history, meaning the user won't be
able to use the Back button to
navigate to it.
Like Greg said above, the .replace() function is how to do this. I can't seem to figure out how to reply to his answer*, but the trick is to reference the iFrames contentWindow property.
var ifr = document.getElementById("iframeId");
ifr.contentWindow.location.replace("newLocation.html");
*Just learned I need more reputation to comment on an answer.
An alternative method to recreating the iframe would be to remove the iframe from the DOM, change the src and then re add it.
In many ways this is similar to the replace() suggestion, but I had some issues when I tried that approach with History.js and managing states manually.
var container = iframe.parent();
iframe.remove();
iframe.attr('src', 'about:blank');
container.append(iframe);
One solution is to use the object tag rather than the iframe tag.
Replacing this:
<iframe src="http://yourpage"/>
By this:
<object type="text/html" data="http://yourpage"/>
will allow you to update the data attribute without affecting the history. This is useful if you use a declarative framework such as React.js where you are not supposed to do any imperative command to update the DOM.
More details on differences between iframe and object: Use of Iframe or Object tag to embed web pages in another
Try to use this function to replace old iframe with new iframe which is copied from old one:
function setIFrameSrc(idFrame, url) {
var originalFrame = document.getElementById(idFrame);
var newFrame = document.createElement("iframe");
newFrame.id = originalFrame.getAttribute("id");
newFrame.width = originalFrame.getAttribute("width");
newFrame.height = originalFrame.getAttribute("height");
newFrame.src = url;
var parent = originalFrame.parentNode;
parent.replaceChild(newFrame, originalFrame);
}
Use it like this:
setIFrameSrc("idframe", "test.html");
This way will not add URL of iframe to browser history.
Use the replace method to bypass the addition of the iframe's URL to history:
HTML:
<iframe id="myIframe" width="100%" height="400" src="#"></iframe>
JavaScript:
var ifr = document.getElementById('mIframe')
if (ifr) {
ifr.contentWindow.location.replace('http://www.blabla.com')
}
JDandChips answer worked for me on a cross origin iframe (youtube), here it is in vanilla JS (without JQuery):
const container = iframe.parentElement;
container.removeChild(iframe);
iframe.setAttribute('src', 'about:blank');
container.appendChild(iframe);
The most simple and fast loading solution
Use window.location.replace to not update the history when loading the page or the frame.
For links it looks like this:
<a href="#" onclick="YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>
or
<a href="javascript:YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>
But if you want it not to act from link but to act automatically when loading the frame then from the iframe you should put this in the iframe file body section:
onload="window.location.replace ('http://www.YourPage.com');"
If for some reason the onload does not load in the iframe then put your target frame name instead of window in the syntax like this:
onload="YourTarget.location.replace ('http://www.YourPage.com');"
NOTE: For this script all onclick, onmouseover, onmouseout , onload and href="javascript:" will work.
#JDandChips has a great answer above, but the syntax should be updated from parent() to parentElement:
var container = iframe.parentElement;
iframe.remove();
iframe.attr('src', 'about:blank');
container.append(iframe);

Categories