I'm writing a live video website, which use a third-party tools to play the video.
To simplify my problem, I embedded all the live video components into a single HTML page. It looks like this.
<iframe data-v-140cfad2="" width="800" height="500" src="/backend/render/live?uid=047a911d83&vid=254084" id="haha"></iframe>
When the page was loaded, it played video normally. However, I write following commands in Chrome console.
a = document.getElementById('haha')
a.hidden = true;//or a.style.display = 'none'
Not only the video window disappeared (as I wish), the audio disappeared (that is not I want). I don't know how It stopped, and if there is any way can still run the video in the background.
Update :
Change the size of iframe into 0px * 0px is a way to move the iframe into background. However it does not fit my situation.
I was using vue.js & element-ui. The iframe was inside a el-tabs components, which means all the hidden operations was automatically done after the tab change. I don't know how to prevent such default operation.
Backend iframe code :
(() => {
window.onload = function() {
let ctx = document.getElementById('player');
let uid = ctx.getAttribute('uid');
let vid = ctx.getAttribute('vid');
let cfg = {
uid: uid,
vid: vid,
height: 500,
width: 800,
};
console.log(">>>",cfg);
player = polyvObject('#player').
livePlayer(cfg);
}
})();
<!DOCTYPE html>
<html>
<head>
<script src="http://player.polyv.net/script/player.js"></script>
<script src="http://player.polyv.net/livescript/liveplayer.js"></script>
<script src="/backend/js/live.js"></script>
<link rel="stylesheet" href="/backend/css/live.css">
</head>
<body>
<div id="player" uid="#{uid}" vid="#{vid}"></div>
</body>
</html>
This bug will not happen when iframe embed a MP4 file, or a normal web page. Only happens on my own page. (that strange, because I don't understand how the functions INSIDE the iframe was trigger by the hidden style OUTSIDE iframe).
I solve this problem by modifying the element-ui components to avoid using v-show when hiding components. Details show in the solution posted by myself.
Thanks for all people answering my problem :)
Hide the iFrame
.hiddeniFrame{
width:0px;
height:0px;
}
Or move it away off the screen
At last, I solve my own problem by an ugly approach.
The iframe works fine when style visibility='hidden' was set. So I just rewrite the el-tab-pane in the element-ui.
The initial version of el-tab-pane was:
<template>
<div
class="el-tab-pane"
v-if="(!lazy || loaded) || active"
v-show="active"
role="tabpanel"
:aria-hidden="!active"
:id="`pane-${paneName}`"
:aria-labelledby="`tab-${paneName}`"
>
<slot></slot>
</div>
</template>
A did a little modification as follow (the v-visible was contained by npm vue-visible package) [TabPane]
<template>
<div
class="el-tab-pane"
v-if="(!lazy || loaded) || active"
v-show="active || fly"
v-visible="active || !fly"
role="tabpanel"
:aria-hidden="!active"
:id="`pane-${paneName}`"
:aria-labelledby="`tab-${paneName}`"
>
<slot></slot>
</div>
</template>
In my own code, I replaced the el-tab-pane to my DIY TabPane, adding a props named fly to indicate whether to use v-show or the v-visible to hide the components.
It should be backend issue, so it will be great to update question with iframe content. I've reproduce your situation audio still playing after hiding iframe
setTimeout(() => { document.getElementById('test').hidden = true; }, 10000 )
<iframe src="https://www.instagram.com/p/Bn5ar2uBd2C/embed/" width="640" height="880" id="test"></iframe>
Related
Chrome v75 appears to have introduced a bug whereby if you replace an iFrame's src programatically, it will replace the entire page instead of the iFrame.
This didn't happen on v74 and I can't get a test case to work (yet), it just fails in our site. (The site hasn't changed since going from v74 to v75, only Chrome has changed)
It appears to work fine the first time but then when you change it again (in our case viewing report drill downs) it causes the entire page (i.e. the iFrame's Parent) to load the src you were trying to load into the iFrame.
It also doesn't matter if you use pure Javascript or (in our case) JQuery, both cause the same issue.
EDIT: After a few hours detective work, I've found the bug. Setting the tag in the iFrame's content causes Chrome to load the iFrame's content into it's parent rather than the iFrame itself.
I've setup a Plunker account with a demo: https://plnkr.co/edit/UQ0gBY?plnkr=legacy&p=info
Just so I can post the link to Plunker, here is the code for the main file & the iframe content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function onLoaded() {
// find element
let button = document.getElementById("button");
button.addEventListener("click",function(e){
// Add a random number on the end as a cache buster
document.getElementById('frame-finance-custom').src = 'test2.html?rnd=' + Math.random();
},false);
};
document.addEventListener('DOMContentLoaded', onLoaded, false);
</script>
</head>
<body>
<div>IFrame Src Changing Test</div>
<div>
<div id="div-frame-finance-custom" style="float:left;width:33%">
<iframe id="frame-finance-custom" name="frame-finance-custom" class="iframe"
style="border:1px solid black; width: 100%; height: 350px; overflow-y: scroll; vertical-align: top;">
no data
</iframe>
</div>
<div style="float:left;margin-left:1em;">
Detail: Loading an iframe page with a <Base> tag in it with target set to "_parent" will cause any refresh of that frame to replace the parent document<BR>
<BR>Instruction: <UL><LI>Click the 'Update Frame' Button, this will load test2.html into the frame. <LI>Click it again & it will replace the iframe's parent with the content of the iFrame.</UL>
<BR>Confirmation: Remove the <Base> tag from the header of test2.html & reload, it will work as expected.
</div>
</div>
<br clear=both>
<div>
<button id="button">
Update Frame
</button>
</div>
</body>
</html>
IFrame Content (test2.html):
<!DOCTYPE html>
<html lang="en">
<head>
<base target="_parent"/>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>This is the frame content</div>
</body>
</html>
Note, using their new layout it doesn't work, but using their legacy layout it does. Feel free to save the files locally and use chrome directly too.
Ok, so this turned out to be a bug in Chrome rather than anything else, so yes, strictly not a SO question, but seeing as SO ranks so well in Google (other search engines are available), I thought it better to leave it here as a solution rather than simply delete it, just incase anyone else has a similar problem.
The reason is outlined as an edit in my question, the solution is to remove the <base target="_parent"> tag from the iFrame and programatically add the 'target="_parent"' attribute to any links in the iFrame.
We do this via jQuery, I'm sure its just as easy via vanilla Javascript.
$('a').attr('target','_parent');
Add that to the javascript that runs when a page has loaded and it'll replace add target="_parent" to any links on the page.
e.g.
<script>
function onLoaded() {
// find all links and add the target attribute
$('a').attr('target','_parent');
};
document.addEventListener('DOMContentLoaded', onLoaded, false);
</script>
As #Kaiido says in his comment, its apparently fixed in Chrome v77, but this isn't the current (as of June 2019) stable release, so we've had to add the workaround into production so that our CRM works with Chrome v75. Thanks to #Kaiido for confirming that.
This question already has answers here:
How can I make the browser wait to display the page until it's fully loaded?
(16 answers)
Closed 4 years ago.
Both Firefox and Chrome is rendering my pages way too early, which results in my a couple of frames where you first see the header, then the content, and then the footer. It's a very very unpleasant page loading experience.
The way I get around this right now is this, which is such a silly workaround I would like to avoid. It also causes the page to flash white in Chrome.
<!DOCTYPE html>
<html>
<head>...</head>
<body>
<div id="render-all-at-once" style="opacity:0; min-height:100%;">
content
</div>
<script>
document.getElementById("render-all-at-once").style.opacity = 1;
</script>
</body>
</html>
The problem is basically this:
<script>
function sleep(millis) {
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while (curDate - date < millis);
}
</script>
<div>
This will be rendered in the first frame.
</div>
<script>
sleep(3000);
</script>
<div>
And only after that first frame has been rendered will you see this line. You don't see the first line for 3 seconds as
you might, but you do see it flash, right before both lines are displayed.
</div>
<!---
I would like the browser to not render anything until
the entire entire document has been processed.
--->
In isolated tests, the above code seem to work as expected - both lines will be rendered at the same time after 3 seconds. But as soon I start adding a couple of random style-sheets to the page, the problem starts occurring.
I can't seem to narrow it down to any particular style-sheet or style. I can't figure out what's causing it. I've both tried loading all styles sheets from , or just having all of them inlined in a style element. This doesn't make any difference. I'm testing this using Chrome as it seems to happen more frequently there.
Does anyone have any experience with this sort of problem, or have any ideas what's causing it, and know of any way to prevent it?
What I like to do is wrap my content in a div and set it to display:none.
Then, I defer my CSS loading and in my CSS file, and set that wrap div to display:block.
I also compress all my CSS files into one single file (for better loading).
<!DOCTYPE html>
<html>
<head>
<style>
.wrap {
display: none;
}
</style>
</head>
<body>
<div class="wrap">
content
</div>
<noscript id="deferred-styles">
<link rel="stylesheet" type="text/css" href="compressed.css" />
</noscript>
<script>
var loadDeferredStyles = function() {
var addStylesNode = document.getElementById("deferred-styles");
var replacement = document.createElement("div");
replacement.innerHTML = addStylesNode.textContent;
document.body.appendChild(replacement);
addStylesNode.parentElement.removeChild(addStylesNode);
};
var raf = requestAnimationFrame || mozRequestAnimationFrame ||
webkitRequestAnimationFrame || msRequestAnimationFrame;
if(raf) {
raf(function() {
window.setTimeout(loadDeferredStyles, 0);
});
} else {
window.addEventListener('load', loadDeferredStyles);
}
</script>
</body>
</html>
Use the network tab in developer tools to see the process & response of each request. First, the HTML is fully received and parsed by the browser which then looks for remote objects to load top-down: stylesheets, images, javascript, etc.
So, to have complete control over how things appear, send an HTML document that looks exactly as you'd like the initial view to be (ex: a blank white document, achieved with inline CSS or a <style> tag that targets <body>). Then use a line of Javascript to listen for the load event and update your display, for example:
<!doctype html>
<html>
<link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/stackoverflow/primary.css">
<body style="display: none;">
<h1>Headline</h1>
</body>
<script>
window.addEventListener("load", function(event) {
document.querySelector("body").style.display = "block";
});
</script>
</html>
I'm building a site that can only be seen through an iframe. I also added a script that auto resize height can be adjusted.
But loading my blog so the added weight of having to load two pages at once. To cope, I apply the OnClick to load the iframe.
Auto Resize But it turned out to not work.
Load Iframe code:
<script type="text/javascript">
function okeBos() {
document.getElementById("iframeControl").innerHTML='<iframe scrolling="no" src="http://name-domain.com" style="border: 0; width: 100%;"></iframe>';document.getElementById("starApps").style.display="none";
};
</script>
<div id="iframeControl"></div><div id="starApps"><span onclick="okeBos()">Load Iframe</span></div>
Do you know how to work the Auto Resize for tricks like this? Please help me, thanks ..
EDIT
The following code snippet Resize My
Stored at sites that are loaded:
<script src='http://britha.com/Upload/MyFile/iframeResizer.contentWindow.min.js' type='text/javascript'></script>
<script>
var iFrameResizer = {
messageCallback: function(message){
}
}
</script>
Stored at the site containing the iframe:
<script src="http://britha.com/Upload/MyFile/iframeResizer.js" type="text/javascript"></script>
<script type="text/javascript">
iFrameResize({
log : true,
enablePublicMethods : true,
enableInPageLinks : true,
});
</script>
UPDATE
What I know about iframes is that they are usually the last on the DOM to load, so you have to expect a lag sometimes. I have neglected to ask if you can even load an iframe successfully by normal means (i.e. in the markup (HTML)). Anyways, I strongly suggest that you load your iframe the normal way because it won't be recognized by the iframe-resizer plugin. It has to coordinate between 2 pages, calculate, and adjust so I'm pretty sure it takes loading times into account. An iframe that pops up whenever the user decides to press a button is like 5 years to a computer (not scientific fact just an exaggeration).
I have made a Plunker and used the example provided by this repository and I added some of my own tests as well. Here is the most important code:
Parent Page
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="http://cdn.jsdelivr.net/iframe-resizer/3.5.3/iframeResizer.min.js"></script>
<script>
iFrameResize({options});
Child Page
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="http://cdn.jsdelivr.net/iframe-resizer/3.5.3/iframeResizer.contentWindow.min.js"></script>
<script>
MOST IMPORTANT: DO NOT CREATE THE IFRAME DYNAMICALLY
PLUNKER
OLD
Please explain how it doesn't work. It functions in this Snippet...How am I supposed to know what to fix if I do not have the auto-resize script?
SNIPPET
<script>
function okeBos() {
document.getElementById("iframeControl").innerHTML='<iframe scrolling="no" src="http://name-domain.com" style="border: 0; width: 100%;"></iframe>';
document.getElementById("starApps").style.display="none";
};
</script>
<div id="iframeControl"></div>
<div id="starApps">
<span onclick="okeBos()">Load Iframe</span>
</div>
I'm trying to replicate this: http://wistia.com/blog/fullscreen-video-homepage
on my site, but even working with just the base demo that they give, is running me into issues. If I simply download the sample from that page and open the video, it works fine, but if I do anything as seemingly simple as swapping the background video with the foreground video, it breaks, let alone replacing those videos with my own videos (which is my eventual goal with all of this).
Here's what I'm doing.
Replacing this in the javascript:
overlayVideo: 'fji9juvptr',
overlayVideoDiv: '#wistia_fji9juvptr',
backgroundvideo: 'z1ggfo8f86',
backgroundideoDiv: '#wistia_z1ggfo8f86'
with this:
overlayVideo: 'z1ggfo8f86',
overlayVideoDiv: '#wistia_z1ggfo8f86',
backgroundvideo: 'fji9juvptr',
backgroundideoDiv: '#wistia_fji9juvptr',
and replacing this in the HTML:
<div id="wistia_z1ggfo8f86" class="wistia_embed backgroundVideo" style="width:920px;height:518px;"></div>
<div id="wistia_fji9juvptr" class="wistia_embed overlayVideo" style="width:1920px;height:1080px;"></div>
with this:
<div id="wistia_fji9juvptr" class="wistia_embed backgroundVideo" style="width:920px;height:518px;"></div>
<div id="wistia_z1ggfo8f86" class="wistia_embed overlayVideo" style="width:1920px;height:1080px;"></div>
And that's enough to break it. My guess is that something about the two videos is different that causes the z1ggfo8f86 video to work as the background but not the fji9juvptr video, but I can't tell what that difference is.
I also tried just changing the names of the divs (I changed the "a" in "wistia" to an "o"), but that also broke it so I assume those div names are processed somehow by Wistia.
Any ideas on what I'm missing?
I never wanted an overlay video or buttons or any of that garbage - all I wanted was the background video - I simplified this code so it makes better sense - just change the wistiaVideoID in the javascript object and make sure the id="wistia_q4bmpyxfll" on the DIV in the HTML matches it which is important. Also change the settings for that wistia video on their website so there is no sound, autoplay, and loop...
<!doctype html>
<html lang="en">
<head>
<style>
body {
margin: 0;
padding: 0;
}
#video_container {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
z-index: 1;
opacity: 1;
}
</style>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="video_container">
<div id="wistia_q4bmpyxfll"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script charset='ISO-8859-1' src='https://fast.wistia.com/assets/external/E-v1.js'></script>
<script charset='ISO-8859-1' src='https://fast.wistia.com/labs/crop-fill/plugin.js'></script>
<script type="text/javascript">
var fullScreenVideo = {
wistiaVideoID: 'q4bmpyxfll',
embedVideo: function(){
var videoOptions = {};
Wistia.obj.merge(videoOptions, {plugin: {cropFill: {src: "//fast.wistia.com/labs/crop-fill/plugin.js"}}});
wistiaEmbed = Wistia.embed(this.wistiaVideoID, videoOptions);
},
fixTextPosition: function(){
var width = $(window).width();
var height = $(window).height();
$("#video_container").css("width", width).css("height", height);
}
};
$(document).ready(function() {
fullScreenVideo.fixTextPosition();
});
$(window).resize(fullScreenVideo.fixTextPosition);
fullScreenVideo.embedVideo();
</script>
</body>
</html>
Are your videos the same aspect ratio as the ones in the Tutorial?
To double check, in Wistia, follow these steps on the video content page where you found your video ID.
Video Actions > Embed & Share >
Choose any of the embed options and inspect the code for "height" and "" values, and update your style values for #backgroundVideo and #overlayVideo
I ended up figuring this out.
Of the two videos they use in the Tutorial, the Background one had configured (in Wistia) auto-play and loop, whereas the overlay video (for good reason) did not. Swapping them thus broke auto-play, and since the background video has no way to make it play, it'd just appear to not work at all (and the overlay video would auto-play when the page was loaded, so you'd hear it in the background despite no video being visible.
The solution is to either edit the video in Wistia's configuration properties to have the background one load and the foreground one not, or use the Embed API to set the settings in the JavaScript itself so you don't have to worry about what the video's default settings are.
I'm loading a content dynamically to the <iframe>
<iframe style='border:none;' id='abc' src="http://localhost:39217/Home/GetContent/some_dynamic_code"></iframe>
after a success response, in that iframe is that content
<html>
<head>
<script type="text/javascript">
function onPageLoad() {
if (document.readyState === "complete") {
var cont = document.getElementById("abc");
alert(cont);
}
}
</script>
</head>
<body onload='onPageLoad()'>
<a target="_blank" href='http://lorem'>
<img class='abc' style='max-width:300px; max-height: 38px;' alt='' src='/Images/image.png' />
</a>
</body>
</html>
That iframe will be using outside my site (by users), but I want to have the ability to change the <img> src. But, I need also to change the width/height of the iframeafter I change the image. So, how can I get the access to that iframe using JS ? That code above alerts me null
I made an example for you here: http://jsfiddle.net/KRaWU/2/
I use jQuery to achieve that and I suggest you do the same.
// this will find a button within an iframe
var obj = $('iframe').contents().find('.actionButton').find('input[type="submit"]');
// this will change the value of the button, and you can see that the text is changed.
obj.attr('value', 'LOG ME IN');
You can analogically find an img and change its src.
JS interaction between iFrames and their parents is for what I know impossible or at least troublesome. I know there is somewhere a property window.frames and maybe even frame.parent but in general, JS interaction like that is impossible. I think you should consider another type of solution (like an ajaxcall maybe, if that could satisfy your needs).