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>
Related
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
});
});
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.
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);
APPLICATION
Above I have an application which contains videos in a slider. There are 2 videos in the slider. Please pla the first video and then without stopping the video, click on "Next" in the slider to slide to the next video and play that video. You can tell that both videos are playing at the same time.
My question is that is it possible to stop a video playing when it has been slided?
I am using jwplayer for playing video and basic jquery slider for slider.
Code is below:
<div id="banner-video_<?php echo $key; ?>">
<ul class="bjqs">
<?php
foreach ($arrVideoFile[$key] as $v) { ?>
<li><div id="myElement-<?php echo $key.'-'.$i; ?>">Loading the player...
<script type="text/javascript">
jwplayer("myElement-<?php echo $key.'-'.$i; ?>").setup({
file: "<?php echo 'VideoFiles/'.$v; ?>",
width: 480,
height: 270
});
<?php $i++; ?>
</script>
</div>
</li>
<?php } ?>
</ul>
</div>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#banner-video_<?php echo $key; ?>').bjqs({
animtype : 'slide',
height : 300,
width : 700,
responsive : true,
randomstart : false,
automatic : false
});
});
</script>
<?php
}
//end:procedure video
?>
you should add the command to pause in the source of the bjqs, try using the not minified version it will be easier to modify and when you are happy with it you can minify it again.
so in bjqs on line 422 you will find
$c_wrapper.on('click','a',function(e){
e.preventDefault();
var direction = $(this).attr('data-direction');
if(!state.animating){
if(direction === vars.fwd){
go(vars.fwd,false);
}
if(direction === vars.prev){
go(vars.prev,false);
}
}
});
add the command to pause all players when a link is clicked like this (using code from your example) :
$c_wrapper.on('click','a',function(e){
e.preventDefault();
jwplayer("myElement-70-0").pause();
jwplayer("myElement-70-1").pause();
var direction = $(this).attr('data-direction');
if(!state.animating){
if(direction === vars.fwd){
go(vars.fwd,false);
}
if(direction === vars.prev){
go(vars.prev,false);
}
}
});
if you want to make it dynamic you can loop through the elements of the slider..as long as you use a rule for naming the video elements, something like this
$('li.bjqs-slide').each( function(index) {
jwplayer("myElement-70-"+index).pause();
});
if you want to have slides that don't contain videos, just add a class to the jwplayer element and use each to that, so let's say all your jwplayer elements have the class .playjw, you would do something like
$('.playjw').each( function(index) {
jwplayer("myElement-70-"+index).pause();
});
hope it helps!
The JQuery plugin "basic-jquery-slider" doesn't have events notification when the navigation texts "perv" and "next" are clicked, but you can hooked them using the data-direction attribute.
According to the JwPlayer documentation, you can drive your video like using jwplayer()
The API describes all possibilities
$('[data-direction="forward"]').click(function(){
jwplayer().pause();
});
$('[data-direction="previous"]').click(function(){
jwplayer().pause();
});
I test to pause the video using console and it works. Bind the click event to the button should work too.
When the slide animation is triggered you need to call jwplayer('player').pause(); or jwplayer('player').stop();.
Pretty simple function here but not working. Just started with Javascript so be gentle with me. Also does anyone know of any good community forums for beginners. I feel this is such a simple question to ask on here, but maybe not.
<html>
<head>
<script type="text/javascript">
var img;
function mouseOver()
{
alert(img);
img.src ="button_over.jpg";
}
function mouseOut()
{
img.src ="button_out.jpg";
}
function init()
{
img = document.getElementById("buttonWrapper").getElementsByTagName('img')[0];
}
</script>
</head>
<body onLoad="javascript:init()">
<div id="buttonWrapper">
<img border="0" src="button_out.jpg" width="62" height="74" onmouseover="mouseOver()" onmouseout="mouseOut()" / >
</div>
</body>
</html>
Live demo: http://jsfiddle.net/jTB54/
Just put this code at the bottom of the page (right before </body>) and you won't need an onload handler:
var img = document.getElementById("buttonWrapper").getElementsByTagName('img')[0];
img.onmouseover = function() {
this.src = "button_over.jpg";
}
img.onmouseout = function() {
this.src = "button_out.jpg";
}
I don't know if this will fix your problem, but wouldn't it be easier to do something like this?
<html>
<head>
<script type="text/javascript">
function mouseOver(img)
{
img.src ="button_over.jpg";
}
function mouseOut(img)
{
img.src ="button_out.jpg";
}
</script>
</head>
<body>
<div id="buttonWrapper">
<img border="0" src="button_out.jpg" width="62" height="74" onmouseover="mouseOver(this)" onmouseout="mouseOut(this)" />
</div>
</body>
</html>
JavaScript is a solution for your issue but I would recommend a different approach: Use CSS instead!
Here a tutorial I found on Google:
http://inspectelement.com/tutorials/create-a-button-with-hover-and-active-states-using-css-sprites/
This also will solve the 'preloading issue' you will face, means: When you go with the mouse over the button the hover image needs time to load. the result will be a gap in the displaying of the images (for a half second there will be no image displayed).
I would suggest learning and using JQuery:
http://jquery.com/
There are a lot of good tutorials on the site, and you can Google for more.
Here is a snippet from a site that has a few buttons that have mouseover, mouseup, mousedown, and hover states. Each button state has its own image, of course:
$(function () {
$("#btnPrintSheet").mousedown(function () {
$(this).attr("src", BASE_IMG_PATH + "printDN.gif");
}).mouseup(function () {
$(this).attr("src", BASE_IMG_PATH + "printOV.gif");
}).hover(function () {
$(this).attr("src", BASE_IMG_PATH + "printOV.gif");
}, function () {
$(this).attr("src", BASE_IMG_PATH + "printUP.gif");
});
});
You can add a click event handler to that as well...
The function init() can be removed since we don't really need it.
Below is a shorter version of your code.
<html>
<body>
<div>
<img src="button_out.jpg" width="62" height="74" onmouseover="mouseOver(this)" onmouseout="mouseOut(this)" / >
</div>
</body>
<script>
var mouseOver = img => {
img.src ="button_over.jpg";
}
var mouseOut = img => {
img.src ="button_out.jpg";
}
</script>
</html>
Do yourself a HUGE favor - if you're just getting started with Javascript, learn jQuery. It will drastically simplify what you're trying to do. Go to here
In this case, you can easily tie a click event to your img tag with examples here.