So we have a product that contains multiple videos with progressbars (think of it like an instagram story)
This product is placed inside iframe on partner websites. The behaviour of this "story" is to play by default. The progressbars are animated with css.
The problem is that if the iframe is outside of viewport, the video will start playing but the progressbar will start animating only after the iframe enters the viewport
I replicated the issue here: https://codepen.io/capraruioan/pen/VwXXNNz
hit the "reload iframe" button, wait a few seconds and scroll down and you will see the progressbar will start only when the iframe entered the viewport
Here is the code:
<button onclick="resetIframe()">reload iframe</button>
scroll down to see animations
<iframe id="iframe" style="margin-top: 110vh; height: 100px; display: block;" src="https://clipr.opsolutions.ro/animation.html" frameborder="0"></iframe>
and js
var url = "https://clipr.opsolutions.ro/animation.html"
function resetIframe() {
iframe.src = ""
window.setTimeout(() => {
iframe.src = url
console.log("done")
}, 100)
}
I cannot find anything on webkit docs about this or how to avoid/bypass it
I've added video connectivity and audio connectivity in the multi-user part but, having small issues.
When I'm disconnecting it should hide the plane which is there for showing the video and share screen.
When I click on the screen sharing plane it should scale to the whole screen and then we can able to see minimize and close buttons also.
let cameraEnabled = false;
const cameraBtnEle = document.getElementById('camera-btn');
// Screen share status
let screenEnabled = false;
// Screen share button element
const screenBtnEle = document.getElementById('screen-btn');
// On mobile remove elements that are resource heavy
const isMobile = AFRAME.utils.device.isMobile();
function onConnect () {
console.log("onConnect", new Date());
// Handle camera button click (Off and On)
cameraBtnEle.addEventListener('click', function() {
NAF.connection.adapter.enableCamera(!cameraEnabled);
cameraEnabled = !cameraEnabled;
cameraBtnEle.textContent = cameraEnabled ? 'Hide Camera' : 'Show Camera';
});
// Handle screen button click (Off and On)
screenBtnEle.addEventListener('click', function() {
if (screenEnabled) {
NAF.connection.adapter.removeLocalMediaStream("screen");
screenEnabled = false;
if(screenEnabled == false){
console.log("This is for share screen ++++++++++++++++++",shareScreen);
shareScreen.setAttribute("visible","false")
}
screenBtnEle.textContent = 'Share screen';
} else {
navigator.mediaDevices.getDisplayMedia().then((stream) => {
NAF.connection.adapter.addLocalMediaStream(stream, "screen");
screenEnabled = true;
screenBtnEle.textContent = 'Stop Screen';
});
}
});
}
const shareScreen = document.querySelector("#shareScreen")
const videoScreen = document.querySelector("#videoScreen")
console.log("This is for share screen ++++++++++++++++++",videoScreen);
if(!cameraEnabled){
videoScreen.setAttribute("visible",false)
}
This is for onConnect function.
<div class="actions">
<button id="camera-btn" type="button" class="button">Hide Camera</button>
<button id="screen-btn" type="button" class="button">Share screen</button>
</div>
These are the buttons.
<template id="avatar-template">
<a-entity class="avatar" player-info>
<a-plane resize-on-click id="videoScreen" color="#FFF" width="4" height="3" position="0 .6 0" material="side: back" networked-video-source></a-plane>
<a-plane resize-on-click id="shareScreen" color="#FFF" width="2" height="1" position="0 .7 -0.001" material="side: back" networked-video-source="streamName: screen"></a-plane>
This is a-plane I'm using.
Please help me with this.
I used the youtube-api code I found and embedded it in a WordPress site. Essentially, it should autoplay an embedded Youtube video set to loop, that is muted and have CC. When I test it, it works except for the looping part. When I open the website on a different browser, nothing shows. I tried the one as well but it does not let me mute the video. Help?!
<div id="muteYouTubeVideoPlayer"></div>
<script async src="https://www.youtube.com/iframe_api"></script>
<script>
function onYouTubeIframeAPIReady() {
var player;
player = new YT.Player('muteYouTubeVideoPlayer', {
videoId: 'ofVRwYmc9WA', // YouTube Video ID
width: 600, // Player width (in px)
height: 316, // Player height (in px)
playerVars: {
autoplay: 1, // Auto-play the video on load
controls: 1, // Show pause/play buttons in player
showinfo: 0, // Hide the video title
modestbranding: 1, // Hide the Youtube Logo
loop: 1, // Run the video in a loop
fs: 0, // Hide the full screen button
cc_load_policy: 1, // Hide closed captions
iv_load_policy: 3, // Hide the Video Annotations
autohide: 0 // Hide video controls when playing
},
events: {
onReady: function(e) {
e.target.mute();
}
}
});
}
// Written by #labnol
</script>
So, I finally found someone to help me with this. We are using Powerpack for BeaverBuilder on WordPress.
You just need to add this code to the functions.php file of your current theme's folder:
add_filter( 'pp_video_embed_url', function($embed_url) {
if ( false !== strpos( $embed_url, 'youtube' ) ) {
$embed_url .= '&cc_load_policy=1';
}
return $embed_url;
});
I have created an inline popup for my custom Wordpress theme using Magnific Popup and the wp_audio_shortcode() function. It works beautifully, except that the audio keeps playing when I close the popup. (Embedded video stops exactly as expected, which is great!)
I read this post magnific-popup, how to play an audio file when popup open and stop playing when closing it and it didn't quite address my problem; I get several javascript errors.
Any help would be greatly appreciated!
Here is the HTML for the popup window that my function renders. I have removed extraneous things like web addresses and multi-line headlines.
THE LINK PEOPLE CLICK:
<span class="pop-up-wrapper"><h2 class="homecard-title">Link Text</h2></span>
THE POPUP THAT APPEARS:
<div id="popup-3" class="pop-up-post zoom-anim-dialog">
<div class="pop-up-left"><img src="graphic.jpg" class="pop-up-back-image"></div>
<div class="pop-up-right">
<h2 class="homecard-title">Headline Here<br><span class="play-wrapper" id="audio-3"><!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
<audio class="audio-3" id="audio-104-1" preload="none" style="width: 100%;" controls="controls"><source type="audio/mpeg" src="http://vivenne:8888/wp-content/uploads/2019/04/Vivienne-Leheny-Hot-Winter-NIghts-Lucas-Mom.mp3?_=1">http://vivenne:8888/wp-content/uploads/2019/04/Vivienne-Leheny-Hot-Winter-NIghts-Lucas-Mom.mp3</audio></span></h2>
</div>
<button title="Close (Esc)" type="button" class="mfp-close">×</button>
</div>
The jquery for Magnific (taken directly from the website):
$('.popup-with-zoom-anim').magnificPopup({
type: 'inline',
fixedContentPos: false,
fixedBgPos: true,
overflowY: 'auto',
closeBtnInside: true,
preloader: false,
midClick: true,
removalDelay: 300,
mainClass: 'my-mfp-zoom-in',
});
When the close button is clicked, I would like the audio to STOP playing, but it continues in the background.
Well folks, I solved it. I abandoned the wp_audio_shortcode(), which made it easier to assign an ID to the <audio> element.
I am happy to provide all of the code, but I think it's confusing out-of-context. Here are the important tidbits…
The magnificPopup container gets a data-ref attribute that matches the audio player's ID contained within it. (I did this with a simple $count variable because there are several popups on the page.)
The important part for the magnificPopup jQuery is this:
callbacks: {
close: function(){
var magnificPopupVar = $.magnificPopup.instance,
magnificPopupSrc = magnificPopupVar.currItem.src,
magnificPopupRef = $(magnificPopupSrc).attr('data-ref'),
audioplayer = document.getElementById('audio-popup-'+magnificPopupRef);
audioplayer.pause();
}
}
In context:
$('.popup-with-zoom-anim').magnificPopup({
type: 'inline',
fixedContentPos: false,
fixedBgPos: true,
overflowY: 'auto',
closeBtnInside: true,
preloader: false,
modal:false,
midClick: true,
removalDelay: 300,
mainClass: 'my-mfp-zoom-in',
callbacks: {
close: function(){
var magnificPopupVar = $.magnificPopup.instance,
magnificPopupSrc = magnificPopupVar.currItem.src,
magnificPopupRef = $(magnificPopupSrc).attr('data-ref'),
audioplayer = document.getElementById('audio-popup-'+magnificPopupRef);
audioplayer.pause();
}
}
});
I hope that's helpful to someone else trying to sort this out!
I'm trying to display an iframe in my mobile web application, but I'm having trouble restricting the size of the iframe to the dimensions of the iPhone screen. The height and width attributes on the iframe element seem to have no effect, strangely. Surrounding it with a div manages to constrain it, but then I'm unable to scroll within the iframe.
Has anyone tackled iframes in mobile safari before? Any ideas where to start?
Yeah, you can't constrain the iframe itself with height and width. You should put a div around it. If you control the content in the iframe, you can put some JS within the iframe content that will tell the parent to scroll the div when the touch event is received.
like this:
The JS:
setTimeout(function () {
var startY = 0;
var startX = 0;
var b = document.body;
b.addEventListener('touchstart', function (event) {
parent.window.scrollTo(0, 1);
startY = event.targetTouches[0].pageY;
startX = event.targetTouches[0].pageX;
});
b.addEventListener('touchmove', function (event) {
event.preventDefault();
var posy = event.targetTouches[0].pageY;
var h = parent.document.getElementById("scroller");
var sty = h.scrollTop;
var posx = event.targetTouches[0].pageX;
var stx = h.scrollLeft;
h.scrollTop = sty - (posy - startY);
h.scrollLeft = stx - (posx - startX);
startY = posy;
startX = posx;
});
}, 1000);
The HTML:
<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" id="iframe" src="url" />
</div>
If you don't control the iframe content, you can use an overlay over the iframe in a similar manner, but then you can't interact with the iframe contents other than to scroll it - so you can't, for example, click links in the iframe.
It used to be that you could use two fingers to scroll within an iframe, but that doesn't work anymore.
Update: iOS 6 broke this solution for us. I've been attempting to get a new fix for it, but nothing has worked yet. In addition, it is no longer possible to debug javascript on the device since they introduced Remote Web Inspector, which requires a Mac to use.
If the iFrame content is not yours then the solution below will not work.
With Android all you need to do is to surround the iframe with a DIV and set the height on the div to document.documentElement.clientHeight. IOS, however, is a different animal. Although I have not yet tried Sharon's solution it does seem like a good solution. I did find a simpler solution but it only works with IOS 5.+.
Surround your iframe element with a DIV (lets call it scroller), set the height of the DIV and make sure that the new DIV has the following styling:
$('#scroller').css({'overflow' : 'auto', '-webkit-overflow-scrolling' : 'touch'});
This alone will work but you will notice that in most implementations the content in the iframe goes blank when scrolling and is basically rendered useless. My understanding is that this behavior has been reported as a bug to Apple as early as iOS 5.0. To get around that problem, find the body element in the iframe and add -webkit-transform', 'translate3d(0, 0, 0) like so:
$('#contentIframe').contents().find('body').css('-webkit-transform', 'translate3d(0, 0, 0)');
If your app or iframe is heavy on memory usage you might get a hitchy scroll for which you might need to use Sharon's solution.
This only works if you control both the outside page and the iframe page.
On the outside page, make the iframe unscrollable.
<iframe src="" height=200 scrolling=no></iframe>
On the iframe page, add this.
<!doctype html>
...
<style>
html, body {height:100%; overflow:hidden}
body {overflow:auto; -webkit-overflow-scrolling:touch}
</style>
This works because modern browsers uses html to determine the height, so we just give that a fixed height and turn the body into a scrollable node.
I have put #Sharon's code together into the following, which works for me on the iPad with two-finger scrolling. The only thing you should have to change to get it working is the src attribute on the iframe (I used a PDF document).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Pdf Scrolling in mobile Safari</title>
</head>
<body>
<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" id="iframe" src="data/testdocument.pdf" />
</div>
<script type="text/javascript">
setTimeout(function () {
var startY = 0;
var startX = 0;
var b = document.body;
b.addEventListener('touchstart', function (event) {
parent.window.scrollTo(0, 1);
startY = event.targetTouches[0].pageY;
startX = event.targetTouches[0].pageX;
});
b.addEventListener('touchmove', function (event) {
event.preventDefault();
var posy = event.targetTouches[0].pageY;
var h = parent.document.getElementById("scroller");
var sty = h.scrollTop;
var posx = event.targetTouches[0].pageX;
var stx = h.scrollLeft;
h.scrollTop = sty - (posy - startY);
h.scrollLeft = stx - (posx - startX);
startY = posy;
startX = posx;
});
}, 1000);
</script>
</body>
</html>
<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" src="url" />
</div>
I'm building my first site and this helped me get this working for all sites that I use iframe embededding for.
Thanks!
Sharon's method worked for me, however when a link in the iframe is followed and then the browser back button is pressed, the cached version of the page is loaded and the iframe is no longer scrollable. To overcome this I used some code to refresh the page as follows:
if ('ontouchstart' in document.documentElement)
{
document.getElementById('Scrolling').src = document.getElementById('SCrolling').src;
}
I implemented the following and it works well. Basically, I set the body dimensions according to the size of the iFrame content. It does mean that our non-iFrame menu can be scrolled off the screen, but otherwise, this makes our sites functional with iPad and iPhone. "workbox" is the ID of our iFrame.
// Configure for scrolling peculiarities of iPad and iPhone
if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1)
{
document.body.style.width = "100%";
document.body.style.height = "100%";
$("#workbox").load(function (){ // Wait until iFrame content is loaded before checking dimensions of the content
iframeWidth = $("#workbox").contents().width();
if (iframeWidth > 400)
document.body.style.width = (iframeWidth + 182) + 'px';
iframeHeight = $("#workbox").contents().height();
if (iframeHeight>200)
document.body.style.height = iframeHeight + 'px';
});
}
Purely using MSchimpf and Ahmad's code, I made adjustments so I could have the iframe within a div, therefore keeping a header and footer for back button and branding on my page. Updated code:
<script type="text/javascript">
$("#webview").bind('pagebeforeshow', function(event){
$("#iframe").attr('src',cwebview);
});
if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1)
{
$("#webview-content").css("width","100%");
$("#webview-content").css("height","100%");
$("#iframe").load(function (){ // Wait until iFrame content is loaded before checking dimensions of the content
iframeWidth = $("#iframe").contents().width();
if (iframeWidth > 400)
$("#webview-content").css("width",(iframeWidth + 182) + 'px');
iframeHeight = $("#iframe").contents().height();
if (iframeHeight>200)
$("#webview-content").css("height",iframeHeight + 'px');
});
}
</script>
and the html
<div class="header" data-role="header" data-position="fixed">
</div>
<div id="webview-content" data-role="content" style="height:380px;">
<iframe id="iframe"></iframe>
</div><!-- /content -->
<div class="footer" data-role="footer" data-position="fixed">
</div><!-- /footer -->
Don't scroll the IFrame page or its content, scroll the parent page. If you control the IFrame content, you can use the iframe-resizer library to turn the iframe element itself into a proper block level element, with a natural/correct/native height. Also, don't attempt to position (fixed, absolute) your iframe in the parent page, or present an iframe in a modal window, especially if it has form elements.
I also suspect that iOS Safari has a non-standards behavior that expands your iframe's height to its natural height, much like the iframe-resizer library will do for desktop browsers, which seem to render responsive iframe content at height 0px or 150px or some other not useful default. If you need to contrain width, try a max-width style inside the iframe.
The solution is to use Scrolling="no" on the iframe.
That's it.