postMessage function not working with window.onload? - javascript

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.

Related

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

While Removing div using javascript, the backgroundimage stayed

I am having a problem with the background-image inside a div.
I am trying to program a html-webgame, using mainly canvas. So as a result, my index looks like this.
<head>
<title>Cardgame</title>
<link rel="stylesheet" type="text/css" href="resoursces/css/index.css">
</head>
<body>
<div class='game_object' id='game_object'>
<canvas class='main_canvas' id='main_canvas'>Error</canvas>
</div>
<script type="text/javascript" src='main.js'></script>
</body>
The problem comes along like this:
window.onload = (function() {
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
drawing();
} resizeCanvas();
})();
in the function "drawing()" i am doing 2 things.
The first one is to remove all divs, i have created so far,
and the second is the i am drawing all div's new with new x-coordinate, y-coordinat, hight and width. So it looks like this
function drawing() {
delete_div();
create_div();
}
function delete_div() {
battlefield_div.style.removeAttribute("backgroundImage", false);
battlefield_div.parentNode.removeChild(battlefield_div);
}
funtciont create_div() {
var board_div= document.createElement("div");
board_div.setAttribute("id", "board");
board_div.style.position = 'absolute';
board_div.style.top = board.y1+"px";
board_div.style.left = board.x2+"px";
board_div.style.height = board.y2 - board.y1+"px";
board_div.style.width = board.x1 - board.x2+"px";
board_div.style.zIndex = '2';
board_div.style.backgroundImage="url(resoursces/images/board.png)";
board_div.style.backgroundSize = "100% 100%";
game_object.appendChild(board_div);
}
This game is a cardgame and i wanted to make it to resize when ever you change the height and the width of the browser without loosing its function. The divs i am creating are part of the functionality.
Everything works fine with it, except one thing: Whenever you resice the browser, the divs are getting remove and new ones are calculated but the background-images is still there. So when you resized your browser like 4 times, you are just seeing the background-images.
What am i doing wrong?
Can anyone help me?

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>

jQuery/Javascript: Button - replaces images

I have little knowledge of JavaScript and need some help. I have this code (below) which when the countdown finishes, it replaces the image with a new one.
I wanted to modify this so that instead of a countdown - a button (img) is pressed instead. Here's my design to get an idea: Design.
I'm guessing I'll need 4 imageloaders instead of just one this time (one for each box) and some code to make it so that when the "older ->" button is clicked it triggers the loading of images?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript" charset="UTF-8"></script>
<script src="js/jquery.countdown.js" type="text/javascript" charset="UTF-8"></script>
<script type="text/javascript">
<!-- The ready() function will force the browser to run wait running the javascript until the entire page has loaded -->
$(document).ready(function() {
// The jquery code for constructing and starting the counter
// has been wrapped inside a function so we can call it whenever we want to
function startCounter(imageLoader){
$('#counter_2').countdown({
image: 'img/digits.png',
startTime: '00:03',
timerEnd: function(){ callback(imageLoader) },
format: 'mm:ss'
})
}
// Takes care of whatever need to be done every time
function callback(imageLoader){
// Replace image
$('#image').attr('src', imageLoader.nextImage());
// Clear the finished counter, so a new can be constructed in its place
$('#counter_2').empty();
// Construct a new counter and starts it
startCounter(imageLoader);
}
function ImageLoader(images){
this.images = images;
this.current = 0;
this.nextImage = function(){
this.current = (this.current+1) % this.images.length;
return this.images[this.current];;
}
}
// Fill in images in this array
imageLoader = new ImageLoader(['img/turd.png', 'img/guitar.gif', 'img/carrot.jpg', 'img/puppy.jpg']);
// Set everything off! (Construct a new counter and starts it)
startCounter(imageLoader);
});
</script>
<style type="text/css">
div.counter{
font-size: 36px;
font-weight: bold;
line-height: 77px;
}
</style>
</head>
<body>
<div id="counter_2" class="counter"></div>
<img id="image" src="img/turd.png" alt="Hot steaming turd">
</body>
</html>
Thanks everyone, I'm really stuck and really appreciate your help.

jQuery and javascript code on same page doesn't work

I have a problem about jQuery and javascript code; when I write this jQuery below between </head> and <body>
<script type="text/javascript">
var $j = jQuery.noConflict();
$j(document).ready(function(){
$j('#page_effect').fadeIn(3000);
});
</script>
and then write javascript code in body tag
<script src="bubbles.js"></script>
<script type="text/javascript">
bubblesMain(new Object({
type : 'linear',
minSpeed : 100,
maxSpeed : 400,
minSize : 30,
maxSize : 55,
num : 100,
colors : new Array('#FF0000','#FFFFFF','#FFCC99', '#FF33CC')
}));
</script>
then jQuery code can work , but javascript code doesn't work. Finally I found that when I resize the browser after the first loading, it's OK to run.
the bubble.js is to automatically create a canvas element and then raises some bubbles with animation inside canvas.
the partly code is on below :
function bubblesMain(obj){
bubbleResize();
bubbles = new bubbleObject(obj);
bubbles.createBubbles();
setInterval(start,1000/60);
};
//WHEN WINDOW HEIGHT IS CHANGED, REMAKE THE CANVAS ELEMENT
window.onresize = function(event) {
bubbleResize();
}
function bubbleResize(){
var height = parseInt(document.getElementById("canvasBubbles").clientHeight);
var width = parseInt(document.getElementById("canvasBubbles").clientWidth);
document.getElementById("canvasBubbles").innerHTML = '<canvas id="canvas" width="'+width+'px" height="'+height+'px"></canvas>';
}
function start(){
var canvas = document.getElementById("canvas");
canvas.width = canvas.width;
bubbles.move();
bubbles.draw();
};
and I have a <div id="canvasBubbles"></div> indise html.
Then after I added the following code into bubbles.js, It's work to run.
window.onload = function(event) {
bubbleResize();
}
I wonder if someone can suggest a smarter solution to this? thank you.
As stated in the other answers, the <script> tags should be the last thing before the </body> tag. See this question.
The problem with where you've put the tags is that the body of the HTML page hasn't loaded and is therefore not available for manipulation. The reason the window.onload and window.onresize work is because they are called later, when the body of the document is available for manipulation with JS.
Given the details provided in your question, you don't need the jQuery.noConflict() statement.
Here is an alternate version of your code that should do the same thing but with a bit more efficiency. Put it at the end of the body element, just before the </body> tag. I haven't tested it since I don't have all the scripts needed (bubbles, etc).
<!-- this goes at the end of your body element, just before the closing tag -->
<script type="text/javascript" src="bubbles.js"></script>
<script type="text/javascript">
$.ready(function(){
var canvasWrap,
canvasElm,
bubbles;
init();
setInterval(update, 1000/60);
window.onresize = resize;
$('#page_effect').fadeIn(3000);
function init(){
canvasWrap = document.getElementById("canvasBubbles");
canvasElm = document.createElement('canvas');
canvasElm.setAttribute('id', 'canvas');
canvasElm.setAttribute('width', canvasWrap.clientWidth);
canvasElm.setAttribute('height', canvasWrap.clientHeight);
canvasWrap.appendChild(canvasElm);
bubbles = new bubbleObject({
type: 'linear',
minSpeed: 100,
maxSpeed: 400,
minSize: 30,
maxSize: 55,
num: 100,
colors: ['#FF0000','#FFFFFF','#FFCC99', '#FF33CC']
});
bubbles.createBubbles();
update(); // you might not need this
}
function resize() {
canvasElm.setAttribute('width', canvasWrap.clientWidth);
canvasElm.setAttribute('height', canvasWrap.clientHeight);
}
function update(){
// canvasElm.width = canvasElm.width; // is this a hack for something?
bubbles.move();
bubbles.draw();
};
});
</script>
You can write all this inside <body>...</body> or inside <head> ... </head>
NOT works between </body> and <head> tag (maybe works for some less formal browser like old IE).
Script tags should always go at the bottom of the page directly before the tag unless the codes needs to be executed before then for some reason.
And as far as I know, the jQuery noConflict() method is only required when you are using two different libraries that both use the dollar sign, aka jQuery and MooTools, on the same page. You can use jQuery and vanilla javascript without having to use noConflict without any problems.

Categories

Resources