Detecting scroll event of Iframe called by AJAX reqest - javascript

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
});
});

Related

postMessage function not working with window.onload?

OK, so here's the setup. I have an expandable banner that swaps out the HTML of the smaller initial banner to the larger expanding banner. (In this test it expands from 160px wide to 600px wide.) I also have the second HTML page jump to a specific scene in my exported Tumult Hype (An HTML 5 animation program) files.
The function
"postToHype()"
uses postMessage to pass off to the second HTML document HypeExample to tell it to open to the second scene of the document. So in theory, what happens is the ad not only expands and loads the second HTML document, but it also then jumps to the second scene in that document.
This is working for me; it triggers the "postToHype()" function when I mouseover the ad. This also works when I tested using a button which also triggers the
"combine()"
function. The "combine()" function ALSO triggers the function
"autoExpand()"
which opens the ad for 7 seconds and then closes it again.
What I can't get to work is having window.onload call the "combine();" function. When window.onload fires "combine()" , "autoExpand()" works but "postToHype()" does not. Why does the button click and onmouseover work with my "postToHype()" function, but "window.onload" does not?
Not all of the code is shown here (such as the linked .js libraries) but I tried to include the most pertinent bits. Any and all ideas are greatly appreciated.
<head>
<script type="text/javascript">
var exampleHTMLToPage = ExpandableBanners.banner("exampleHTMLToPage", "HypeExample.html", 600, 600);
exampleHTMLToPage.setCloseImage("images/close.png", 'right', 'bottom');
exampleHTMLToPage.animated = true;
exampleHTMLToPage.setDirection('down', 'right');
animated = true;
exampleHTMLToPage.expandOnClick = false;
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded",function(){documentReady=true;
});}
else if (!window.onload) window.onload = function(){documentReady=true;}
</script>
<script type="text/javascript">
function autoExpand() {
setTimeout("ExpandableBanners.openAd('exampleHTMLToPage')",0000);
setTimeout("ExpandableBanners.closeAd('exampleHTMLToPage')",7000);
}
</script>
<script> function combine() {
autoExpand();
postToHype();
} </script>
<script>
function postToHype(){
document.getElementById('exampleHTMLToPage_expanded_media').contentWindow.postMessage(['start', 'Scene2'], '*')
}
</script>
</head>
<body>
<div onmouseover="postToHype()" id="exampleHTMLToPage" style="width:150px; height:600px; background-color:rgb(30,167,221); position:relative; color:white; font-weight:bold">
<div style="display:inline-block;
width:140px; font-size:22px; margin-top:20px; margin-left:5px; margin-right:5px;">This is an HTML banner RK V7. Click to see exported HYPE interactive that loaded inside.</div>
</div>
<button onclick="combine();">Click me</button>
</body>
<script>
window.onload = function(){
combine();
};</script>
Change it lite this:
<script type="text/javascript">
function autoExpand() {
setTimeout("ExpandableBanners.openAd('exampleHTMLToPage')",0000);
setTimeout("ExpandableBanners.closeAd('exampleHTMLToPage')",7000);
}
function postToHype(){
document.getElementById('exampleHTMLToPage_expanded_media').contentWindow.postMessage(['start', 'Scene2'], '*')
}
function combine() {
autoExpand();
postToHype();
}
</script>
You need to defining the function postToHype() before you are calling it. And it is better to just use one script tag and write all your code in it.

some calls to javascript functions inside iframe have no effect

I have a slider which contains iframes. The slider is based on bxslider and the iframes each contain a separate highcharts chart. Now I want to achieve something which sounded simple: I want to redraw the chart once the slide changes.
After some searching, I found a helpful question which explained the redrawing. That works fine inside the frame. Actually I have created a button inside the frame, which redraws it. So far so good. However, whenever I try to call the redraw function from the main page, that contains the slider, then nothing happens. I have tried setting alerts (these are shown), logging variables (all seems fine) and even sending a click event to the button that redraws the chart (the event is triggered, but the chart is not redrawn). What am I missing here?
UPDATE:
I looked at this from different angles and also read a lot of similar questions. The point is that the call is actually working, but it seems like the Highcharts methods are not executed. All the data seems to be there, so it is not a scope problem. Is there maybe a security policy that might prevent code in an external js file from running or such (without generating any errors)?
main code:
<body>
<ul class="bxslider">
<li><iframe src="/xcid/dashboard/index_project_budget" width="100%" height="800px" id="iframe1" marginheight="0" frameborder="0"></iframe></li>
<li><iframe src="/xcid/dashboard/index_utilization" width="100%" height="800px" id="iframe2" marginheight="0" frameborder="0"></iframe></li>
</ul>
<script>
function callChild () {
var el = document.getElementById("iframe2");
el.contentWindow.redraw(); //tried this first
$("#iframe2").contents().find("#button").trigger("click"); //tried this, too
}
$(document).ready(function(){
$(".bxslider").bxSlider({
auto: true,
pause: 8000,
onSlideAfter: function(){
callChild();
}
});
});
</script>
</body>
iframe2 main code:
<div id="main-panel">
<div id="main">
<h1><?php echo $title; ?></h1>
<div id="chart-container" style="width: 800px; height: 400px; margin: 0 auto"><!-- Chart container --></div>
<div id="button">WHY?</div>
</div>
</div>
<script>
var data = <?php echo $chart['series']; ?>;
var options = <?php echo $chart['options']; ?>;
renderto ('#chart-container', data, options);
var chart = $('#chart-container').highcharts();
function clearChart() {
while(chart.series.length > 0) {
chart.series[0].remove(false);
}
chart.redraw();
}
function redrawChart() {
for (i=0;i < data.length; i++) {
chart.addSeries(data[i], false);
}
chart.redraw();
}
function redraw() {
clearChart();
redrawChart();
}
$("#button").click(function(){
console.log ("button clicked");
redraw();
});
</script>

html2canvas - no screenshot for iframe

I have a task where i need to load a URL (e.g www.yahoo.com) , on my webpage, and take screenshot. I am using html2canvas for screenshot and appending it to the body of the page.
The page specified by the URL is successfully loaded in an iframe inside a div element. But when i try to take screenshot of that, the iframe area comes blank.
Below is the code for previewURL and screenshot.
//to preview the URL content
function previewUrl(url,target){
//use timeout coz mousehover fires several times
clearTimeout(window.ht);
window.ht = setTimeout(function(){
var div = document.getElementById(target);
div.innerHTML = '<iframe style="width:100%;height:100%;" frameborder="0" src="' + url + '" />';
},20);
}
function pic() {
html2canvas(document.body, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
};
And the HTML part goes here :
<body>
<input type="button" class="clear-button" onclick="pic();" value="Take Screenshot" >
Hover to load
<div id="div1"></div>
</body>
The screenshot looks something like this :
I am stuck and don't understand why is this happening. I want something similar to this which can load URL and then onclick can give me screenshot.
The problem here is that you are not pointing correctly to the part of the iframe that you want to take the screenshot, instead you are pointing directly to the document body.
you can try this:
var body = $(iframe).contents().find('body')[0];
html2canvas(body, {
onrendered: function( canvas ) {
$("#content").empty().append(canvas);
},
Hope this helps!
Seems like it's not possible:
The script doesn't render plugin content such as Flash or Java applets. It doesn't render iframe content either.
http://html2canvas.hertzen.com/documentation.html#limitations
This code worked 4 me:
setTimeout(() => {
html2canvas($('#'+idd2).contents().find('body')[0], {
allowTaint : true,
logging: true,
profile: true,
useCORS: true
}).then(function(canvas) {
document.getElementById('screen').appendChild(canvas);
}); }, 3000);

How to load image on demand

I have this simple image zoom jQuery. Here is a Demo example. It uses the elevateZoom jQuery.
The code behind is very simple:
<img id="zoom_05" src='small_image1.png' data-zoom-image="large_image1.jpg"/>
<script>
$vc("#zoom_05").elevateZoom({
zoomType : "inner",
cursor: "crosshair"
});
</script>
My question, is how can i make the large image load on demand, only when the mouse is over it. Please have a look at this demo example and let me know what i need to add in the code.
img element (id="zoom_05") above, would not load large_image1.jpg on its own.
Large image load happens because elevateZoom() looks into its data-zoom-image value and immediately loads it. One way around this behaviour is to defer elevateZoom() until user hover's over the small image for the first time. Quick example:
jQuery( function () {
var elevate_zoom_attached = false, $zoom_05 = $("#zoom_05") ;
$zoom_05.hover(
// hover IN
function () {
if ( ! elevate_zoom_attached ) {
$zoom_05.elevateZoom({
zoomType : "inner",
cursor : "crosshair"
});
elevate_zoom_attached = true ;
};
},
// hover OUT
function () {
if ( elevate_zoom_attached) { // no need for hover any more
$zoom_05.off("hover");
}
}
);
}) ;
Mind you this is an quick, on-top-of-my-head code, but should work ...
Also in this case elevateZoom() action might not be immediate while large image loading is going on.
I used this idea to initiate zoom on any number of images on the same page by adding a zoom class to the image. It works without any HOVER OUT
<img class="zoom" src="myimage.png" data-zoom-image="mybigimage.png"/>
$('.zoom').hover(
// hover IN
function () {
var currImg = $(this); //get the current image
if (!currImg.hasClass('zoomon')) { //if it hasn't been initialized
currImg.elevateZoom(); //initialize elevateZoom
currImg.addClass('zoomon'); //add the zoomon class to the img so it doesn't re-initialize
}
})

$.mobile.changePage() changes page with No data(white screen)?

i have many links in my page each with two attributes that are format & src.
<a class="play" src="'.$p['video_path'].'" format="'.$p['video_type'].'"></a>
what its clicked i get its 2 attr and make HTML in js like this.
$(".play").live('click',function() {
var src = $(this).attr('src');
var fmt = $(this).attr('format');
var html = '<video width="200" height="240" controls> <source src="'+src +'" type="video/'+ fmt +'"> </video>';
$("#myVideoDiv").html(html);
$.mobile.changePage( $("#myVideoDiv"), { transition: 'pop' } );
});
<div data-role="dialog" id="myVideoDiv"></div>
when i clicked on any video link my browser url changes like this
http://pp.local/maps/maps/40295472#&ui-state=dialog
but nothing displaying just a white screen.
although its working $("#myVideoDiv").html( html ); i can see the HTML through Firbug.
No error or Warning in Firebug:(
Basically what i need to do is that i want to show each video in jquery Mobile dialog like we do in normal jquery UI like the code below.i need to do same thing here too but with jquery mobile dialog.
$(".watchVideo").live('click', function() {
if( $('div.ui-dialog').length ) {
$('div.ui-dialog').remove();
}
var path = $(this).attr('rel');
var title = $(this).attr('title');
var $dialog = $('<div>', {
title: 'Title'
}).dialog({
autoOpen: false,
modal: true,
width: 600,
height: 500,
closeOnEscape: false
});
var tab = '<table id="video_player" style="margin: 10px 10%;"><tr><td><object codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"><param value="'+path+'" name="src"><param value="true" name="autoplay"><param value="true" name="controller"><embed pluginspage="http://www.apple.com/quicktime/download/" controller="true" style="height:300px;width:400px;background-color:#D9EBFB" autoplay="true" target="myself" src="'+path+'"></object></td></tr></table>';
$('<div id="updateContent">').html( tab ).appendTo( $dialog );
$dialog.dialog('open');
return false;
});
I have successfully recreated your problem, unfortunately I can't be 100 % sure this is the problem. I think you have a an error with your page/dialog setup.
Take a look at my working example, try to use it in your app: http://jsfiddle.net/Gajotres/5REkc/. This example uses dialog as a video container:
$('#index').live('pagebeforeshow',function(e,data){
$('#show-video').live('click', function(e) {
$('#video-content').append('<video width=450px height=300px controls="controls"><source src="http://dev.swinginsam.com/_files/testvid_01.ogv" type="video/ogg"></video>');
$.mobile.changePage("#second", { transition: "slide"});
});
});
I have also created another example for you. This one is much better and it uses popup as a video container. Unlike dialog popup will resize to accommodate video tag: http://jsfiddle.net/Gajotres/vscrU/.
$('#index').live('pagebeforeshow',function(e,data){
$('#show-video').live('click', function(e) {
$('#popup-video').append('<video width=600px height=300px controls="controls"><source src="http://dev.swinginsam.com/_files/testvid_01.ogv" type="video/ogg"></video>');
$('#popup-video').popup("open");
});
});
<div data-role="popup" id="popup-video" data-tolerance="15,15" class="ui-content"</div>
Data tolerance is here so popup can have a padding. Without it video player is overflowing popup container.
One more thing, I can see you are using php for content generation. In this case popup is much better solution. Unlike dialog (which acts as another page, and is a another page), popup is a part of a single page, so i has a much better usability in server side generation.
WARNING:
My examples will only work in firefox browser. I have used only a ogg video source. Video sources are taken from this post.

Categories

Resources