on scroll page with iframe inside iframe - javascript

I have a simple video player which is inserted into page within an iframe, now I want when the video player is visible play the video otherwise pause the video. to achieve that am using the intersection observer function.
Here is html skeleton
<body>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</body>
Here is js
var configFromParent = null;
window.addEventListener("message", function (event) {
var data = event.data;
if (data.action == "config") {
configFromParent = data;
}
var observer = new IntersectionObserver(function(entries) {
//console.log(entries);
if(entries[0]['isIntersecting'] === true) {
if(entries[0]['intersectionRatio'] === 1)
document.querySelector("#message").textContent = 'Target is fully visible in screen';
else if(entries[0]['intersectionRatio'] > 0.5){
$("#videoplayer")[0].play();
document.querySelector("#message").textContent = 'More than 50% of target is visible in screen';
}
else{
document.querySelector("#message").textContent = 'Less than 50% of target is visible in screen';
}
}
else {
$("#videoplayer video")[0].pause();
}
}, { threshold: [0, 0.5, 1] });
observer.observe(document.querySelector(".videoplayer"));
});
Now when scrolling my page nothing is happening, but when I change the parent src link to child iframe link everything works perfectly, but I want the iframe to be inside a parent iframe and when the video player is not visible pause the video otherwise play the video
What do I need to do solve this problem?

Observer is totally functional. https://codesandbox.io/s/loving-zhukovsky-chdds?file=/index.html this sandbox contains you html setup (not secure ofcourse). Scroll page down to see how message changes.
Secure frames behave in the same manner. You don't have to worry about it. But don't forget that IE may have no observer, you should handle it.
And I still assume that the problem in the post messaging

Related

WkWebview javascript animation froze when screen locked

Xcode 12.3 iOS 12.4+ iPhone Application
I have a view controller which contains wkwebview which gets initialized on startup. This is on the framework side. An enclosing app adds this view onto their view controller as a subview. The app is purely HTML and javascript-based app. We render HTML pages based on user interaction. Everything works fine except for an issue with the Lock Screen
On a particular screen, there is some animation running while updating some values on the screen as well. When the app is moved to the background, the app runs fine but when I Lock the Screen and come back to the app, the animation and all processing on the screen are frozen. I would have to start the process back from the home screen.
I noticed that both moving to background and lock screen have the same state changes such as did enter the background and will enter foreground but in one case, everything is frozen. Could someone please let me know what might be the problem and what would be a solution in this scenario?
Thank you.
Edit
This is the animation called on the html page...the screen is expecting some values which is sent from framework once done processing
let showNextItemJS = """
function startNextAnimation() {
var box = document.querySelector('\(boxElement)');
if(box) {
var thisItem = box.querySelector('\(diagnosticItem)');
var statusStr = '\(statusStr)'
if (thisItem) {
thisItem.classList.add('start');
if (statusStr != 'none') {
thisItem.classList.add(statusStr);
}
}
} else {
var thisItem = document.querySelector('\(diagnosticItem)');
var statusStr = '\(statusStr)'
if (thisItem) {
thisItem.classList.add('start');
if (statusStr != 'none') {
thisItem.classList.add(statusStr);
}
}
}
};
function stopLastAnimaation() {
var box = document.querySelector('\(boxElement)');
if(box) {
var lastItem = box.querySelector('\(lastDiagnosticItem)');
if (lastItem) {
lastItem.classList.add('finish');
}
} else {
var lastItem = document.querySelector('\(lastDiagnosticItem)');
if (lastItem) {
lastItem.classList.add('finish');
}
}
};
startNextAnimation()
stopLastAnimaation()
"""
callJavaScript(showNextItemJS)

How To Create A Timed Button For A Video Using Wistia API

Hi I am trying to get a button to appear beneath my video after 30 mins and 30 seconds. When I contacted Wistia support they gave me this link and told me they were not coders and couldn't help me further. I don't know anything about javascript and I do know a bit of CSS. I read a post on another website here and copied it to my site hoping that it would work. I added the javascript code beneath the inline embed of my video, and then put the CSS in the customize additional css editor in wordpress.
When I did it part of it worked and the button I had there disappeared, but when I tried to trigger it at the 30min 30sec mark it never appeared and I haven't been able to get it to appear at all. Here is a link to the page for you to view it and below is the code that I have used to embed the video as well as the css to hide the button. Any help would be greatly apprecited as I am very new to this.
Here is the code I used on the video embed:
<script src="https://fast.wistia.com/embed/medias/c5khj4dcbi.jsonp" async></script><script src="https://fast.wistia.com/assets/external/E-v1.js" async></script><div class="wistia_responsive_padding" style="padding:56.25% 0 0 0;position:relative;"><div class="wistia_responsive_wrapper" style="height:100%;left:0;position:absolute;top:0;width:100%;"><div class="wistia_embed wistia_async_c5khj4dcbi videoFoam=true" style="height:100%;position:relative;width:100%"><div class="wistia_swatch" style="height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;transition:opacity 200ms;width:100%;"><img src="https://fast.wistia.com/embed/medias/c5khj4dcbi/swatch" style="filter:blur(5px);height:100%;object-fit:contain;width:100%;" alt="" aria-hidden="true" onload="this.parentNode.style.opacity=1;" /></div></div></div></div>
<script>
window._wq = window._wq || [];
// target our video by the first 3 characters of the hashed ID
_wq.push({ id: "c5khj4dcbi", onReady: function(video) {
// at 1830 seconds (30.5min x 60 = 1830), do something amazing
video.bind('secondchange', function(s) {
if (s === 1830) {
// Insert code to do something amazing here
// console.log("We just reached " + s + " seconds!");
$( "#mybutton" ).addClass( "ShowMeButton" );
}
});
}});
</script>
And here is the CSS I used on the wordpress editor customize > additional CSS:
.page-id-741 #mybutton {
opacity: 0;
}
.ShowMeButton {
opacity: 1;
filter:alpha(opacity=100);
}
I'm assuming you're skipping through the video to hit the point where the script runs.
Using the Wistia .secondsPlaying() function, it only shows the actual number of seconds the user has played the video for.
The function you're looking for is .time(), which outputs the actual location of the user in the video, in seconds.
Try this:
<script>
var videoTrigger = false;
window._wq = window._wq || [];
_wq.push({ id: 'xxxxxxxx', onReady: function(video) {
video.bind("secondchange", function() {
if (video.time() >= 1830 && videoTrigger !== true) {
videoTrigger = true;
console.log("Run code here");
}
});
}});
</script>
Note that this code will also activate if the user skips past the activation point (as it uses >= and a variable instead of just ===).

IntersectionObserver Lazy Loading not Working

This is my first time attempting Lazy Loading, and I wanted to use IntersectionObserver. Got started by following along with this website. I honestly just want the content of the page to wait to load until it is less than 50% of the viewport's width below the viewport. I'm not sure how to observe all content, so I just selected the classes for the widgets that are being displayed, as they are the main content. Unfortunately my code doesn't seem to be doing much. I added a console.log at the beginning to make sure the file was linked correctly, and I tried to add more console.logs to log when the widget moves in and out of the capture area. The first console.log works, but nothing else happens.
Here is what I have:
console.log('file loaded');
const widgets = document.querySelectorAll('.widget');
const config = {
root: null,
rootMargin: '-50px 0px -55% 0px',
threshold: .5
};
let isLeaving = false;
let observer = new IntersectionObserver(function(entries, self) {
entries.forEach(entry => {
if (entry.isIntersecting) {
// we are ENTERING the "capturing frame". Set the flag.
isLeaving = true;
// Do something with entering entry
console.log("Widget loaded.");
self.unobserve(entry.target);
} else if (isLeaving) {
// we are EXITING the "capturing frame"
isLeaving = false;
// Do something with exiting entry
console.log("Widget is exiting.")
}
});
}, config);
widgets.forEach(widget => {
observer.observe(widget);
});
This code is in it's own js file. Where should I be linking it in the HTML file?
I'd appreciate any help I can get! Let me know if I need to provide more information.

Change HTML 5 autoplayed video source dynamically

On my website https://cravydev.netlify.com I'm trying to change the video dynamically when the different headlines are in viewport.
I'm using a div with HTML 5 autoplay and loop properties, but not able yet to change the video source and load again when the specific headline is on screen. Here are the details.
HTML
<div class="iphone-sticky"></div>
<div class="iphone-video">
<video autoplay loop muted poster="assets/img/poster.png" id="iphonevideo">
<source id="video1" src="assets/img/iphone-video.mp4" type="video/mp4">
<source id="video2" src="assets/img/iphone-video-1.mp4" type="video/mp4">
</video>
JS
//Detect is element is in viewport
$(window).on('resize scroll', function() {
var player = document.getElementById('iphonevideo2');
if ($('#headline2').isInViewport()) {
var source = document.getElementById('video1');
$(source).attr("src", "assets/img/iphone-video-1.mp4");
player.pause();
player.load();
} else if ($('#headline3').isInViewport()) {
var source = document.getElementById('video1');
$(source).attr("src", "assets/img/iphone-video.mp4");
player.pause();
player.load();
}
});
EDIT
I have been able to solve it thanks to Kley comment. Now the problem is that the js logic does not check constantly the viewport visibility of headlines, only once. Also, the video is played while scrolling and the poster image appears, making the whole experience a little bit weird.
Any suggestion to solve that?
Thanks!
Check the page, it's not the viewport ()
I could tell you that you are changing the src every time you scroll while it is visible, this is causing the video to restart. You must make a validation, if it has already been changed the src should not be changed again.
Note that # headline2 is not visible when # headline3 is a bit up.
you have to scroll down until the end of the page to enter this condition.
You could use another smaller element at the beginning of each #headline to do this validation.
you could use the first p of the #headline
For example:
$(window).on('resize scroll', function() {
var player = document.getElementById('iphonevideo2');
if ($('#headline2 p').eq(0).isInViewport()) {
var source = document.getElementById('video1');
var url = "assets/img/iphone-video-1.mp4";
var src = $(source).attr("src");
// validate if you already have the src
if(src==url) return; // if exists src leaves function
$(source).attr("src", url);
player.pause();
player.load();
} else if ($('#headline3 p').eq(0).isInViewport()) {
var source = document.getElementById('video1');
var src = $(source).attr("src");
var url = "assets/img/iphone-video.mp4";
// validate if you already have the src
if(src==url) return; // if exists src leaves function
$(source).attr("src", url);
player.pause();
player.load();
}
})

Detecting scroll event of Iframe called by AJAX reqest

i have a link in my main page that uses ajax to retrieve a PDF which is displayed in an Iframe, i am trying to detect scroll event of the PDF document and display a message or do something. i have tried different solutions from other solutions on stackoverflow and google search in general and couldn't find a good solution.
Main.php
<html>
<!--ajax request-->
<script type="text/javascript">
$(document).on('click','#nextpdf',function(event) {
event.preventDefault();
var reg = $(this).attr("href");
var str = reg.split('?')[1];
$.ajax({
type: "GET",
url: '../functions/pdfreader.php',
data: 'pdfxs='+str+'',
cache:false,
async: false,
success: function(data) {
// data is ur summary
$('.refresh').html(data);
return false;
}
});//end of ajax
});
</script>
<?php
while($obj = $c_content->fetch())
{
$title = $obj['lecture_title'];
echo '<article class="comment2">
//pdf link
<div class="comment2-body">
<div class="text" style="color:#999;padding-right:130px;">
<p><a href="../functions/pdfreader.php?'.$title.'""
style="color:#999" id="nextpdf">'.$title.'</a></p>
</div>
</div>
</article>
';
}
?>
</html>
pdfreader.php
//detect iframe pdf scroll
<script type="text/javascript">
$("myiframe").load(function () {
var iframe = $("myiframe").contents();
$(iframe).scroll(function () {
alert('scrolling...');
});
});
</script>
<?php
........
while($obj = $gettrend->fetch())
{
$coursefile = $obj['lecture_content'];
//this is my iframe
echo '<div class="mov_pdf_frame"><iframe id="myiframe"
src="https://localhost/einstower/e-learn/courses/pdf/'.$coursefile.'"
id="pdf_content"
width="700px" height="800px" type="application/pdf">
</iframe></div>';
}
?>
The major problem here is that nothing happens when i scroll the pdf document, how can i detect scrolling?
i found this fiddle that works but i cant view the javascript solution. http://fiddle.jshell.net/czw8pbvj/1/
First off, $("myiframe") isn't finding anything, so it attaches a load event to nothing. 1) change it to $("#myiframe") or $("iframe").
Here's a working fiddle (for iframe scroll detection)
UPDATE: to detect the scroll within PDF document, you can't use iframe. For that, you need embed or object tags AND a JS-enabled PDF document (hopefully its your PDFs..), who can send messages to your page's JS (see this answer).
Unfortunately, I couldn't find a scroll event in Adobe's Acrobat API Reference. It lists only these events:
Event type: Event names
App: Init
Batch: Exec
Bookmark: Mouse Up
Console: Exec
Doc: DidPrint, DidSave, Open, WillClose, WillPrint, WillSave
External: Exec
Field: Blur, Calculate, Focus, Format, Keystroke, Mouse Down, Mouse Enter, Mouse Exit, Mouse Up, Validate
Link: Mouse Up
Menu: Exec
Page: Open, Close
Screen: InView, OutView, Open, Close, Focus, Blur, Mouse Up, Mouse Down, Mouse Enter, Mouse Exit
So, basically, I think what you want just isn't possible as for now, at least with default rendering. With custom rendering (https://github.com/mozilla/pdf.js) it could be possible, though I'm not sure.
Apparently, it could be done with page scroll (see this issue). So back to iframes solution. :^D
Because this question is asked a long time ago, i think i need to help with my experience before.
The answer is: You can not
Why? because PDF is rendered by external apps, such as adobe pdf reader, foxit or else. And you can not attach event on them.
if you are using adobe reader, The only you can do is goto page, change zoom etc. Full example you can read here: https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdf_open_parameters.pdf#page=8 (see. i bring you to page 8 directly instead to first page).
But, hei.. how if our client using another apps? we will confused more
The way to do this is only build your own pdf viewer.
we can using js library, like: http://www.bestjquery.com/2012/09/best-jquery-pdf-viewer-plugin-examples/
but here i only will show you to use pdf.js which created by mozilla.
main.php
<style>
.preview{
display:none;
width: 400px;
height: 400px;
border: 1px solid black;
}
</style>
file/test.pdf<br>
file/test1.pdf<br>
<div class="preview">
<iframe id="myiframe" frameborder="0" width="400px" height="400px" >not support iframe</iframe>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$(document).on('click', '#nextpdf', function(e){
e.preventDefault();
$('#myiframe').attr('src', $(this).attr('href'));
$('.preview').show();
});
//handle iframe on scroll
$('#myiframe').on('load', function () {
$(this).contents().scroll(function () {
console.log('scrolled');
}).click(function(){
console.log('clicked');
});
});
});
</script>
pdfreader.php
<?php
$path = 'file/';
$pdf = isset($_GET['pdfxs']) ? $path . $_GET['pdfxs'] : '';
if(!file_exists($pdf) || !mime_content_type($pdf) =='application/pdf') die('file not found');
?>
<div id="pdf-container">
<div id="pdf-box"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<script>
$(function(){
//original script : https://gist.github.com/fcingolani/3300351
function renderPDF(url, canvasContainer, options) {
var options = options || { scale: 1 };
function renderPage(page) {
var viewport = page.getViewport(options.scale);
var canvas = $(document.createElement('canvas'));
var renderContext = {
canvasContext: canvas[0].getContext('2d'),
viewport: viewport
};
canvas.attr('width', viewport.width).attr('height', viewport.height);
canvasContainer.append(canvas);
page.render(renderContext);
}
function renderPages(pdfDoc) {
for(var num = 1; num <= pdfDoc.numPages; num++)
pdfDoc.getPage(num).then(renderPage);
}
PDFJS.disableWorker = true;
PDFJS.getDocument(url).then(renderPages);
}
renderPDF('<?=$pdf;?>', $('#pdf-box'));
});
</script>
Note: i put pdf on folder file/
in main.php you will notice that you can attach event scroll (and click too) to the pdf. because our pdf is not rendered by external apps now.
and the last part is, if you read pdfreader.php carefully, you will notice that you no need iframe anymore. You just need div, and then you can fully handle all event that do you want to your pdf : like scroll, click, change page, zoom, etc. why?? because your pdf is redered as canvas now (pdf.js render your pdf as HTML5 canvas). see full example of pdf.js
Please try this
iframe.on( "scroll", handler )
$("#frame").scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height())
alert('Bottom reached');
});
I found this in the JSFiddle that was referenced in the Fiddle you linked. The HTML field is empty. This CSS was in there, too.
body {
height: 1500px;
}
In the fiddle that you linked, the <iframe> has an ID of frame. I figured you can use the jQuery selector like $("#frame").
I think this will help you.
$("#myiframe").load(function () {
$(this).contents().scroll(function () {
//your code here
});
});

Categories

Resources