I've got an assignment to embed relatively small pdf file inside html page and print the entire html pade including the pdf file inside the iframe.
Here is the structure of my html page:
Here is my code:
#media print{
body * {display:block;}
.toPrint{display:block; border:0; width:100%; min-height:500px}
<body>
<button onclick="window.print()">Print</button>
<h3>MUST BE PRINTED</h3>
<p> MUST BE PRINTED</p>
<iframe class="toPrint" src="https://nett.umich.edu/sites/default/files/docs/pdf_files_scan_create_reducefilesize.pdf" style="width:100%; height:97vh;"></iframe>
<h3>MUST BE PRINTED</h3>
<p> MUST BE PRINTED</p>
</body>
Currently I'm printing the page using css #media query. But unfortunately this media query prints the pdf's first page only.
What can I do print the entire pdf file?
The reason it's not printing the whole PDF is because it's in an iframe and the height is fixed. In order to print the whole PDF you'll need the iframe height to match its content height (there should be no scrollbar on the iframe).
Another option is to print only the iframe. Add id to your iFrame:
<iframe id="toPrint" class="toPrint"></iframe>
Focus the iframe and print its content:
var pdfFrame = document.getElementById("toPrint").contentWindow;
pdfFrame.focus();
pdfFrame.print();
Try this, it includes some JS but thats always good.
HTML:
<body>
<h3>MUST BE PRINTED</h3>
<p> MUST BE PRINTED</p>
<div id="pdfRenderer"></div>
<h3>MUST BE PRINTED</h3>
<p> MUST BE PRINTED</p>
</body>
JS:
var pdf = new PDFObject({
url: "https://nett.umich.edu/sites/default/files/docs/pdf_files_scan_create_reducefilesize.pdf",
id: "pdfRendered",
pdfOpenParams: {
view: "FitH"
}
}).embed("pdfRenderer");
This should work. Let me now if i doesnt
Use https://github.com/itext/itextsharp itextsharp or https://github.com/MrRio/jsPDF jsPDF. It is easy to use by plugin
I used Mozilla's pdf.js to solve my problem.
It renders the pdf file on html5 canvas thus it allows to print the whole html page as required.
Here is the code (credit):
<html>
<body>
<script type="text/javascript" src="https://raw.github.com/mozilla/pdf.js/gh-pages/build/pdf.js"></script>
<script type="text/javascript">
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 ctx = canvas.getContext('2d');
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
canvas.height = viewport.height;
canvas.width = viewport.width;
canvasContainer.appendChild(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);
}
</script>
<h3>MUST BE PRINTED</h3>
<p> MUST BE PRINTED</p>
<div id="holder"></div>
<h3>MUST BE PRINTED</h3>
<p> MUST BE PRINTED</p>
<script type="text/javascript">
renderPDF('yourFile.pdf', document.getElementById('holder'));
</script>
</body>
</html>
Here is a simpler solution using javascript.
<body>
<h3 id='first_h3'>MUST BE PRINTED</h3>
<p id ='first_paragraph'> MUST BE PRINTED</p>
<div id="pdfRenderer"></div>
<h3 id='second_h3'>MUST BE PRINTED</h3>
<p id='second_paragraph'> MUST BE PRINTED</p>
<input type="submit" value="Print All"
onclick="javascript:printPage()"
/>
</body>
<script>
pages =[] // initiate an empty list here
function printPage() {
var first_h3 = document.getElementById('first_h3');
// get the first h3 tag and
// then push its innerHTML into the list
pages.push(first_h3.innerHTML);
var first_paragraph = document.getElementById('first_paragraph');
// get the first paragraph and
// then push its innerHTML into the list
pages.push(first_paragraph.innerHTML);
var pdfRenderer = document.getElementById('pdfRenderer');
// get the pdfRenderer and
// then push its innerHTML into the list
pages.push(pdfRenderer.contentWindow.document.body.innerHTML);
var second_h3 = document.getElementById('second_h3');
// get the second h3 tag and
// then push its innerHTML into the list
pages.push(second_h3.innerHTML);
var second_paragraph = document.getElementById('second_paragraph');
// get the second paragraph and
// then push its innerHTML into the list
pages.push(second_paragraph.innerHTML);
if (pages && pages.length) {
// this if statement, just checks to ensure our list is not empty before running the code.
// here is the magic, we now set the parent window to be equal to all the concatenated innerHTML
window.content.document.body.innerHTML = pages;
// then we print this new window that contains all the different parts in the exact order we pushed them into the list.
window.print();
}
else {
// do nothing
}
}
</script>
With this solution avoid the problem of the iframe being cut off if it exceeds one page. Secondly, you get only one print dialogue box even if you have multiple iframes.
Related
i tried to gather every possible solution to get my code working, but unfortunately I am stuck.
I want to scrape the values from two different graphs, which are generated from JavaScript in the background.
https://us.soccerway.com/matches/2019/12/14/england/premier-league/liverpool-fc/watford-football-club/3029238/
The section I am interested is actually the two graphs in the middle of the page.
"The general game stats chart" and the chart pie to the right.
the html code is presented below:
<div class="block clearfix block_match_stats_plus_chart-wrapper" id="page_match_1_block_match_stats_plus_chart_15-wrapper">
<h2>General Game Stats Chart</h2>
<div class="content ">
<div class="block_match_stats_plus_chart real-content clearfix " id="page_match_1_block_match_stats_plus_chart_15">
<iframe src='/charts/statsplus/3029238/' style='width: 550px; height: 300px; overflow-y: hidden;' frameborder='no' allowtransparency="true" scrolling="no"> </iframe>
</div>
</div>
</div>
<script type="text/javascript" charset="utf-8">
(function() {
var block = new Block('page_match_1_block_match_stats_plus_chart_15', 'block_match_stats_plus_chart', null);
TimestampFormatter.format('page_match_1_block_match_stats_plus_chart_15');
})();
Using a MSXML request should work. Loading only the page with the chart is probably the fastest way to get that information. It looks like you just need what appears to be the game ID 3029238 in order to generate the chart at https://us.soccerway.com/charts/statsplus/
Option Explicit
Sub Scrape_Stats()
Dim Clip As Object: Set Clip = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim html As Object: Set html = CreateObject("htmlfile")
Dim Text As String
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://us.soccerway.com/charts/statsplus/3029238/", False
.Send
While .readyState <> 4: DoEvents: Wend
html.body.InnerHTML = .responseText
Text = html.body.getElementsByTagName("Table")(0).outerhtml
End With
Clip.SetText Text
Clip.PutInClipboard
ws.Range("A2:H1000").ClearContents
ws.Range("A2").Select
ws.PasteSpecial Format:="Unicode Text"
Set Clip = Nothing
End Sub
You are looking at the "Match" page while the charts actually loaded from an iFrame
This is the source you should be looking at: https://us.soccerway.com/charts/statsplus/3029238/
And this is the JavaScript function you should scrape the data from
<script type="text/javascript" charset="utf-8">
window.addEvent('domready', function() {
var chart = new PieChart('Possession');
chart.addSeries('Possession', [{"name":"Watford FC","y":39},{"name":"Liverpool FC","y":61,"sliced":true}]);
chart.highChartsOptions.plotOptions.pie.topmargin = '20';
chart.highChartsOptions.plotOptions.pie.size = "80%";
chart.highChartsOptions.plotOptions.pie.center = ['50%', '55%'];
chart.render('page_chart_1_chart_statsplus_1_chart_possession_1-wrapper');
});
</script>
I would like to load .php in iframe. I have (more than) 10 php files in a folder with index.html,which has the iframe. In this i frame I would like load the .php files randomly (withou repeat-If all 10 files shown then show the messgae "No More") when user click Next... How do I write this javascript.
My index.html looks like this . This file and all the .php files placed in the same folder.
<!DOCTYPE HTML>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" type="text/css" href="main.cs" />
</head>
<body class="is-demo">
<header id="demo-header">
<div class="details">
<div class="inner">
<h1>one.php title</h1>
</div>
</div>
<ul class="actions">
<li><a href="index.php" ><span>Home Page</span></a></li>
<li><span>Previous</span></li>
<li><span>Next</span></li>
</ul>
</header>
<script>
var iframe = document.getElementById("demo-iframe");
var pages = ["one.htm", "two.htm", "three.htm",
"four.htm", "five.htm", "six.htm",
"seven.htm", "eight.htm","nine.htm",
"ten.htm"];
function choose_random_page() {
if(pages.length>0) {
var r = Math.floor(Math.random(pages.length));
var ranom_page = pages.slice(r,1);
iframe.src = random_page;
} else {
alert("No more pages to load");
}
}
</script>
<div id="demo-main">
<iframe id="demo-iframe" src="" data-responsive="1">-</iframe>
</div>
</body>
</html>
Put all your pages to array, mix it, change the iframe src with javascript, exclude page from array after that.
var locations = ['a.php', 'b.php', 'c.php'];
for(var i = 0; i < locations.length; i++){
// I put code for changing locations inside setTimeout, but you can change it with your logic.
setTimeout(function(){
document.getElementById('demo-iframe').src = locations[i];
}, i * 1000)
}
One way to acheive that is to have all possible pages in an array, in any order.
Then once the function triggered to choose the random page, it should do the following:
a- check if pages array still has pages to choose from
b- select a random index between 0 and the number of elements in the array
c- slice the element from that array out and load iframe source with the value
var iframe = document.getElementById("demo-iframe");
var pages = ["one.php", "two.php", "three.php",
"four.php", "five.php", "six.php",
"seven.php", "eight.php","nine.php",
"ten.php"];
function choose_random_page() {
if(pages.length>0) {
var r = Math.floor(Math.random(pages.length));
var ranom_page = pages.slice(r,1);
iframe.src = random_page;
} else {
alert("No more pages to load");
}
}
<iframe id="demo-iframe">
I have looked for duplicate questions, however many refer to adding data to XML
please forgive me if I have missed something here but I need some help
so far I have this:
html page
<!DOCTYPE html>
<html>
<head>
<title>Template</title>
<script type="text/javascript" src="script/controlpanelAdmin.js"></script>
<script type="text/javascript" src="script/controlpanelModerator.js"></script>
<script type="text/javascript" src="script/jquery-1.12.0.js"></script>
<link rel="stylesheet" href="script/css.css" />
</head>
<body>
<fieldset id="control_panel">
<legend>Control Panel</legend>
</fieldset>
<p id="content"> Content </p>
</body>
</html>
controlpanelAdmin.js
window.onload = function() {
var controlpanel = document.getElementById("control_panel");
var para = document.createElement("p");
var att = document.createAttribute("admin");
var br = document.createElement("br");
var txt = document.createTextNode("Admin Control Panel");
controlpanel.appendChild(para);
para.setAttribute("id", att);
para.appendChild(txt);
para.appendChild(br);
}
controlpanelModerator.js
window.onload = function() {
var controlpanel = document.getElementById("control_panel");
var para = document.createElement("p");
var att = document.createAttribute("mod");
var br = document.createElement("br");
var txt = document.createTextNode("Moderator Control Panel");
controlpanel.appendChild(para);
para.setAttribute("id", att);
para.appendChild(txt);
para.appendChild(br);
}
When the page loads, 'Admin Control Panel' is written into the fieldset tag
but is then replaced by: 'Moderator Control Panel'
I cannot for the life of me think how to append both lines (and maybe other data as well) into one element
When the page loads, 'Admin Control Panel' is written into the fieldset tag but is then replaced by: 'Moderator Control Panel'
That can't happen. Admin Control Panel should never appear in the page.
script/controlpanelAdmin.js loads. It causes a value to be assigned to window.onload.
script/controlpanelModerator.js loads. It causes that value to be overwritten with a new one.
The page finishes loading
The load event fires
The function defined in script/controlpanelModerator.js is called
Don't assign values to window.onload. Use addEventListener instead.
addEventListener("load", function () { ... });
You've got two onload functions competing. Can you merge them into one function?
I have following page as coded:
mypage.html:
<html><script>var a=document.createElement('p');
a.innerHTML="hello world";
document.body.appendChild(a);</script>
<body>
<p>testing 1 2 3....</p></body>
</html>
When I pull the information with find.html which has following code.
<script>
window.onload =finder();
function finder(){
var iframe=document.createElement('iframe');
iframe.width=1;
iframe.height=1;
iframe.src='mypage.html';
iframe.setAttribute('id', 'iframer');
document.body.appendChild(iframe);
setTimeout(
function() {
var e = document.getElementById("iframer");
var frameHTML = e.contentDocument; var serializer = new XMLSerializer(); var content = serializer.serializeToString(frameHTML); alert(content);
} , 30000);
}
</script>
the final result is showing as in alert popup:
<html><script>var a=document.createElement('p');
a.innerHTML="hello world";
document.body.appendChild(a);</script>
<body>
<p>testing 1 2 3....</p></body>
</html>
That is not what I am looking for. I am looking to get contents as following which have been render in browser, i need to get all rendered and generated dynamic source code only for inspection, how can i code to get rendered HTML source code:
<body>
<p>hello world</p>
<p>testing 1 2 3....</p>
</body>
Give the IFrame an id attribute.
The contentDocument object actually varies among different browsers. Also, for security reasons, you can only get the content of an IFrame on the same domain.
var IFrame_DOM;
var iframe = document.getElementById('iframer'); // The ID of the IFrame
if (iframe.contentDocument)
{
IFrame_DOM = iframe.contentDocument; // Get DOM in Chrome / Gecko
}
else if (iframe.contentWindow)
{
IFrame_DOM = iframe.contentWindow.document; // Internet Explorer
}
if (IFrame_DOM)
{
// Successfully got the DOM
// Use the DOM in code here
}
else
{
alert('Unsupported Browser. Couldn\'t read DOM.');
}
why you don't use the xml serializer like this :
var serializer = new XMLSerializer();
var content = serializer.serializeToString('yourIframeObject;);
content variable contain the iframe contents including <!DOCTYPE html> , <HTML> and <head>
I'm trying to use Google's Images API to search an image and put it into my html document as a div. This is what I have so far, but nothing seems to be appearing. This is parts from http://code.google.com/apis/imagesearch/v1/devguide.html. This is my first time using an API, so I'm not sure what is really going on.
<html>
<head>
<title>Art Project FTW</title>
</head>
<body>
<br>
<br>
<form name="upload" method="post" action="parse_image.php" enctype="multipart/form-data">
<input type="file" name="Image"><br>
<input type="submit" value="Upload Image">
</form>
<script type="text/javascript" src="https://www.google.com/jsapi?key=xxx"></script>
<script type="text/javascript" charset="utf-8">
google.load('search', '1');
function searchComplete(searcher) {
// Check that we got results
if (searcher.results && searcher.results.length > 0) {
// Grab our content div, clear it.
var contentDiv = document.getElementById('content');
contentDiv.innerHTML = '';
// Loop through our results, printing them to the page.
var results = searcher.results;
for (var i = 0; i < results.length; i++) {
// For each result write it's title and image to the screen
var result = results[i];
var imgContainer = document.createElement('div');
var title = document.createElement('h2');
// We use titleNoFormatting so that no HTML tags are left in the title
title.innerHTML = result.titleNoFormatting;
var newImg = document.createElement('img');
// There is also a result.url property which has the escaped version
newImg.src = result.tbUrl;
imgContainer.appendChild(title);
imgContainer.appendChild(newImg);
// Put our title + image in the content
contentDiv.appendChild(imgContainer);
}
}
}
function onload() {
// Our ImageSearch instance.
var imageSearch = new google.search.ImageSearch();
// Restrict to extra large images only
imageSearch.setRestriction(google.search.ImageSearch.RESTRICT_IMAGESIZE,
google.search.ImageSearch.IMAGESIZE_MEDIUM);
// Here we set a callback so that anytime a search is executed, it will call
// the searchComplete function and pass it our ImageSearch searcher.
// When a search completes, our ImageSearch object is automatically
// populated with the results.
imageSearch.setSearchCompleteCallback(this, searchComplete, [imageSearch]);
// Find me a beautiful car.
imageSearch.execute("Subaru STI");
}
google.setonloadCallback(onload);
</script>
</body>
</html>
Thanks in advance!
It can't work because you are looking for a HTMLElement that has the ID='content', you haven´t anyone element with that ID
Try putting your js functions within <head></head>