how to get element inside frame? (to draw canvas) - javascript

Page for Example:
http://google.com/recaptcha/api2/demo
If i open the image 'myid' the frame will be - EXAMPLE:frame2
now what i want to do, is to draw canvas of 'myid' inside the 'frame2'.
here is the code that i have: (draw by element id)
var canvas = window.document.createElementNS('http://www.w3.org/1999/xhtml', 'html:canvas');
var selection_element = window.document.getElementById("myid");
var selection;
var de = window.document.documentElement;
var box = selection_element.getBoundingClientRect();
var new_top = box.top + window.pageYOffset - de.clientTop;
var new_left = box.left + window.pageXOffset - de.clientLeft;
var new_height = selection_element.offsetHeight;
var new_width = selection_element.offsetWidth;
selection={
top:new_top,
left:new_left,
width:new_width,
height:new_height,
};
canvas.height = selection.height;
canvas.width = selection.width;
var context = canvas.getContext('2d');
context.drawWindow(
window,
selection.left,
selection.top,
selection.width,
selection.height,
'rgba(255, 255, 255, 0)'
);
var canvasdata = canvas.toDataURL('','').split(',')[1];

To append item to frame you need to call that by id. In this HTML:
<iframe id="frm1"></iframe>
<iframe id="frm2"></iframe>
If you use this code:
$(document).ready(function ()
{
var frames = window.frames;
for (var i = 0; i < frames.length; i++)
{
var fi = frames[i]
$(fi).load(function ()
{
$(this).contents().find('body').append("<span>Hello World!</span>");
});
}
});
Does not work, But this one works:
<html>
<head>
<title></title>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
</head>
<body>
<iframe id="frm1"></iframe>
<iframe id="frm2"></iframe>
<script>
$(document).ready(function ()
{
var frm1 = window.frames["frm1"];
$(frm1).load(function ()
{
$(frm1).contents().find('body').append("<span>Hello World!</span>");
});
});
</script>
</body></html>
I tried to create a code snippet, but it seems it has problem with frames.
You can copy the exact HTML and test that.

Related

HTML CANVAS - Preload Issue or OnLoad issue - Why do I have to click twice?

I have an HTML page with 2 canvases side-by-side. The left one has a clickable upper region. The right one is where all the drawing takes place. I want the user to click the region on the left, which will load a new image on the right, and replace the one that is already there, but I have to click twice for the new image to show up. Why is this? See code.
THE HTML
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
#centerAll {
margin-left:auto;
margin-right:auto;
width:1300px;
}
</style>
</head>
<body>
<div id="centerAll">
<canvas id="TheLeftCanvas" width="300" height="500"
style="border:2px solid #999999;"></canvas>
<canvas id="TheRightCanvas" width="900" height="500"
style="border:2px solid #999999;"></canvas>
<script type="text/javascript" src="whyClickTwiceForImage.js">
</script>
</div>
</body>
</html>
AND THE JAVASCRIPT
window.addEventListener("load", eventWindowLoaded, false);
function eventWindowLoaded () {
canvasApp();
}
function canvasApp() {
var rightCanvas = document.getElementById("TheRightCanvas");
//THE EMPTY CANVAS ON THE RIGHT, WHICH DRAWS THINGS
var rightCtx = rightCanvas.getContext("2d");
var leftCanvas = document.getElementById("TheLeftCanvas");
//THE EMPTY CANVAS ON THE LEFT, WHICH HANDLES USER CLICKS
var leftCtx = leftCanvas.getContext("2d");
var currentMouseXcoor = 0;
var currentMouseYcoor = 0;
var imagesToLoad = 0; //USED TO PRE-LOAD SOME OTHER VISUALS, BEFORE THE USER STARTS
var imagesLoaded = 0;
var picturesTheUserCanChoose = ["pic01.png", "pic02.png",
"pic03.png", "pic04.png", "pic05.png"];
var nameOfPicTheUserChose = "pic05.png"; //LET'S JUST SAY "pic05.png" IS A PLACEHOLDER PICTURE... TO START OFF
var legitMouseClick = 0; //DID THE USER CLICK IN THE UPPER REGION OF THE LEFT CANVAS?
var loaded = function(){ // "LOADED" AND "LOAD IMAGE" ARE USED TO PRELOAD ALL THOSE OTHER VISUALS BEFORE THE USER STARTS
imagesLoaded += 1;
if(imagesLoaded === imagesToLoad){
imagesToLoad = 0;
imagesLoaded = 0;
drawScreen(); // OK... ALL LOADED.... SO DRAW THE SCREEN
}
}
var loadImage = function(url){ // "LOADED" AND "LOAD IMAGE" ARE USED TO PRELOAD ALL THOSE OTHER PICS BEFORE THE USER STARTS
var image = new Image();
image.addEventListener("load",loaded);
imagesToLoad += 1; // ADD THE NUMBER TO THE IMAGES NEEDED TO BE LOADED
image.src = url;
return image; // ...AND RETURN THE IMAGE
}
//--------------------------------------------------------------
leftCanvas.addEventListener('mouseup', function(evt) { var
mousePos = doMouseUp(leftCanvas, evt);
currentMouseXcoor = mousePos.x; currentMouseYcoor =
mousePos.y; processMousePosition();}, false);
//--------------------------------------------------------------
function drawScreen(){
clearScreen();
rightCtx.drawImage(picture1,0,0,100,100);
}
//THIS FUNCTION PRESUMABLY LOADS IMAGES ON-THE-FLY... BUT WHY DOES THE LEFT CANVAS REGION HAVE TO BE CLICKED TWICE FOR THE NEW IMAGE TO SHOW?
function processMousePosition() {
if(currentMouseYcoor >= 0 && currentMouseYcoor <= 50){
//IF THE CLICK IS IN THE UPPER REGION OF THE LEFT CANVAS
nameOfPicTheUserChose = picturesTheUserCanChoose[0];
//WE'LL SAY THE USER CHOSE THE VERY FIRST PIC IN THE ARRAY
picture1.src = ("picturesFolder/"+ nameOfPicTheUserChose);
picture1.onload = legitMouseClick = 1;//I JUST MADE UP FOR SOMETHING TO HAPPEN WHEN THE NEW PICTURE LOADS???
alert(nameOfPicTheUserChose); // THE ALERT CORRECTLY SHOWS THE NAME OF THE FIRST PIC IN THE ARRAY
}
drawScreen();
}
function doMouseUp(leftCanvas, evt){
var rect = leftCanvas.getBoundingClientRect();
return { x: evt.clientX - rect.left, y: evt.clientY - rect.top};
}
function clearScreen(){
rightCtx.clearRect(0, 0, 900, 500);
leftCtx.clearRect(0, 0, 300, 500);
}
//var someOtherVisual1 =
//loadImage("backgroundArtFolder/someOtherVisual1.jpg");
//var someOtherVisual2 =
//loadImage("backgroundArtFolder/someOtherVisual2.png");
//var someOtherVisual3 =
//loadImage("backgroundArtFolder/someOtherVisual3.png");
//var someOtherVisual4 =
//loadImage("backgroundArtFolder/someOtherVisual4.png");
//var someOtherVisual5 =
//loadImage("backgroundArtFolder/someOtherVisual5.png");
var picture1 = loadImage("picturesFolder/pic05.png");
//LET'S JUST PRELOAD "pic05.png" AS A PLACEHOLDER... TO START OFF
}
You can change the image load on click in js file picture1.src = ("picturesFolder/"+ nameOfPicTheUserChose); to picture1 = loadImage("picturesFolder/"+nameOfPicTheUserChose); and picture1.onload = legitMouseClick = 1; to 'legitMouseClick = 1'

making a variable string a function name

I was wondering if there was a way to make a var value a function. I'm currently working on a project that makes scripts and runs the code, but when all the function names are the same instead of the two scripts running independent code their writing the same code in unison. If you could show me how to do this it would be a huge help! But I'm not exactly sure if its possible. None the less heres some code
var update = setInterval(function(){
checkDotPop();
sc();
}, 1);
var canvas = document.getElementById("canvas");
var body = document.getElementById("body");
totalDots = 2;
aliveDots = 1;
//styling
body.style.border = "0px";
canvas.style.backgroundColor = "black";
function checkDotPop(){
while(aliveDots != totalDots){
makeDot();
aliveDots++;
}
}
function makeDot(){
var scr = document.createElement("script");
scr.setAttribute("id", "dot" + totalDots);
document.body.appendChild(scr);
var script = document.getElementById("dot" + totalDots);
script.innerHTML = "var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var rand1; var rand2; function changeRand(){rand1 = Math.floor(Math.random() * 300) + 1; rand2 = Math.floor(Math.random() * 300) + 1;} function sc(){ changeRand(); context.fillStyle = 'red'; context.fillRect(rand1, rand2, 10, 10); context.fill();";
}
<!DOCTYPE html>
<html>
<head>
</head>
<body id="body">
<canvas id="canvas" height="500px" width="500px"/>
</body>
</html>
It'll say that "sc is not defined" but in the version I have (using notepad) sc is a gobal function and can be called from script to script
You where missing a closing bracket for your sc function.
var update = setInterval(function(){
checkDotPop();
sc();
}, 1);
var canvas = document.getElementById("canvas");
var body = document.getElementById("body");
totalDots = 2;
aliveDots = 1;
//styling
body.style.border = "0px";
canvas.style.backgroundColor = "black";
function checkDotPop(){
while(aliveDots != totalDots){
makeDot();
aliveDots++;
}
}
function makeDot(){
var scr = document.createElement("script");
scr.setAttribute("id", "dot" + totalDots);
document.body.appendChild(scr);
var script = document.getElementById("dot" + totalDots);
script.innerHTML = "var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var rand1; var rand2; function changeRand(){rand1 = Math.floor(Math.random() * 300) + 1; rand2 = Math.floor(Math.random() * 300) + 1;} function sc(){ changeRand(); context.fillStyle = 'red'; context.fillRect(rand1, rand2, 10, 10); context.fill();}";
}
<!DOCTYPE html>
<html>
<head>
</head>
<body id="body">
<canvas id="canvas" height="500px" width="500px"/>
</body>
</html>

drawing more on the canvas without having to create more script tags

I've been attempting to create a ecology simulation and so far its been going good. The code below does work I'm just wondering if theres an easier way to draw more items on the canvas with code instead of manually doing it. The way I'm doing it makes me consider the lag because I will be adding a lot to the code (e.g. move, detected, reproduce, chase, run, etc). Thank you for seeing this
//This tag will regulate the spawning of new sheep/wolves
var totalWolves = 0;
var totalSheep = 0;
var canavs = document.getElementById("canvas");
var body = document.getElementById("body");
//styler
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
function spawnWolves(){
totalWolves++;
var name = "wolf" + totalWolves;
var scrpt = document.createElement("SCRIPT");
document.body.appendChild(scrpt);
scrpt.setAttribute("id", name);
var script = document.getElementById(name);
script.innerHTML = "var rand3 = Math.floor(Math.random() * 100) + 1; var rand4 = Math.floor(Math.random() * 100) + 1; var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.fillStyle = 'red'; context.fillRect(rand3, rand4, 10, 10); context.fill();";
}
spawnWolves();
spawnWolves();
spawnWolves();
<!DOCTYPE html>
<html>
<head>
<title>AI spawn test</title>
</head>
<body id="body">
<canvas id="canvas" width="1366px" height="768px"/>
<script>
</script>
</body>
</html>
Your solution seems very complicated ...
Please, take a look at the following code.
<!DOCTYPE html>
<html>
<title>AI spawn test</title>
<canvas id="canvas" width="110" height="110"></canvas>
<script>
var ctx = canvas.getContext("2d");
var drawRect=function(rects){
for (var i=1; i<=rects; i++){
var rand3=Math.floor(Math.random() * 100) + 1;
var rand4=Math.floor(Math.random() * 100) + 1;
ctx.fillStyle='red';
ctx.fillRect(rand3, rand4, 10, 10)
}
}
drawRect(20);
</script>
This type of 'replication' is done by using loop. There are several loop types, but their explanation is too broad. You can browse the net.
I gave you 2 examples below - with for loop and with while loop.
//This tag will regulate the spawning of new sheep/wolves
var totalWolves = 0;
var totalSheep = 0;
var canavs = document.getElementById("canvas");
var body = document.getElementById("body");
//styler
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
function spawnWolves(){
totalWolves++;
var name = "wolf" + totalWolves;
var scrpt = document.createElement("SCRIPT");
document.body.appendChild(scrpt);
scrpt.setAttribute("id", name);
var script = document.getElementById(name);
script.innerHTML = "var rand3 = Math.floor(Math.random() * 100) + 1; var rand4 = Math.floor(Math.random() * 100) + 1; var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.fillStyle = 'red'; context.fillRect(rand3, rand4, 10, 10); context.fill();";
}
for(var i=0; i<12; i++)
{
spawnWolves();
}
var maxWolves=9;
while(totalWolves < maxWolves)
{
spawnWolves();
}
<!DOCTYPE html>
<html>
<head>
<title>AI spawn test</title>
</head>
<body id="body">
<canvas id="canvas" width="1366px" height="768px"/>
<script>
</script>
</body>
</html>
The first loop will run until its internal counter i goes from 0 to 12 and will call the function exactly 12 times.
The second loop will run as long as the condition totalWolves < maxWolves is true. totalWolves is your counter you increase in your function and maxWolves is the limit when you want the loop to stop.
Because these 2 examples are added here one after another the second wont work. After the first one executes you will already have 12 wolves and the second loop will not enter because 12 < 9 is false.

Running processing code in canvas by getting the code from textarea

I am trying to get the processing code from textbox and make it running in canvas but i don't know what is happening can someone help me? When i debug it's says ctx.compile(); is not a function how can i make it work propperly? Here is the code i use.
<!DOCTYPE Html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles/style2.css" >
<script src="processing-1.4.1.js"></script>
<script type="text/javascript">
function submitTryit() {
var text = document.getElementById("textareaCode").value;
var ifr = document.createElement("iframe");
ifr.setAttribute("frameborder", "0");
ifr.setAttribute("id", "iframeResult");
document.getElementById("iframewrapper").innerHTML = "";
document.getElementById("iframewrapper").appendChild(ifr);
var ifrw = (ifr.contentWindow) ? ifr.contentWindow : (ifr.contentDocument.document) ? ifr.contentDocument.document : ifr.contentDocument;
ifrw.document.open();
ifrw.document.write(text);
ifrw.document.close();
canvas();
if (ifrw.document.body && !ifrw.document.body.isContentEditable) {
ifrw.document.body.contentEditable = true;
ifrw.document.body.contentEditable = false;
}
function canvas() {
var ifrr = document.getElementById('iframeResult');
var iframediv = (ifrr.contentWindow.document) ? ifrr.contentWindow.document : (ifrr.contentDocument.document) ? ifrr.contentDocument.document : ifrr.contentDocument;
var canv = document.createElement('CANVAS');
canv.setAttribute('id', 'mycanvas');
var ctx = canv.getContext("2d");
ctx.compile();
iframediv.body.appendChild(canv);
}
}
function compile(){
var processingCode = document.getElementById('textCode').value;
var jsCode = Processing.compile(processingCode).sourceCode;
}
</script>
</head>
<body>
<div class="container">
<!--Iframe-->
<div class="iframecontainer">
<div id="iframewrapper" class="iframewrapper">
</div>
</div>
<!--PJS text field-->
<div class="PJStextwraper">
<div class="overPJStext">
</div>
<textarea id="textCode" spellcheck="false" autocomplete="off" wrap="logical"> int x,y,w;
float vx,vy;
void setup() {
size(300,200);
x = int(random(width));
y = int(random(height));
vx = random(5);
vy = random(5);
w = int(10+random(10));
}
void draw() {
background(140,70,60);
ellipse(x,y,w,w);
x += vx;
y += vy;
//
if(x > width || x < 0) {
vx *= -1;
}
if(y > height || y < 0) {
vy *= -1;
}
}
</textarea>
</div>
<button class="BT" type="button" onclick="submitTryit()">Run ยป</button>
</div> <!-- End container-->
</body>
</html>
The error "ctx.compile(); is not a function" is expected since you are trying to call a function that does not exist on the 2d canvas context. If I understand correctly, you are trying to run your own compile function and render it on the canvas you just created.
To do so, you need to change a few things, try the following and see if it works:
function canvas() {
var ifrr = document.getElementById('iframeResult');
var iframediv = (ifrr.contentWindow.document) ? ifrr.contentWindow.document : (ifrr.contentDocument.document) ? ifrr.contentDocument.document : ifrr.contentDocument;
var canv = document.createElement('canvas');
canv.setAttribute('id', 'mycanvas');
// The ctx will be created in an instance of Processing.
// So no need for the following line.
// var ctx = canv.getContext("2d");
compile(canv);
iframediv.body.appendChild(canv);
}
// Here you can pass the canvas where you want to render the code.
function compile(canv) {
var processingCode = document.getElementById('textCode').value;
var jsCode = Processing.compile(processingCode).sourceCode;
// Now that you have the code in JS, you can create an instance of Processing.
// But, what you get from the compiler is a string,
// so you need to convert the string to JS.
// For instance, I use here eval(jsCode)
var processingInstance = new Processing(canv, eval(jsCode));
}

How to display whole PDF (not only one page) with PDF.JS?

I've created this demo:
http://polishwords.com.pl/dev/pdfjs/test.html
It displays one page. I would like to display all pages. One below another, or place some buttons to change page or even better load all standard controls of PDF.JS like in Firefox. How to acomplish this?
PDFJS has a member variable numPages, so you'd just iterate through them. BUT it's important to remember that getting a page in pdf.js is asynchronous, so the order wouldn't be guaranteed. So you'd need to chain them. You could do something along these lines:
var currPage = 1; //Pages are 1-based not 0-based
var numPages = 0;
var thePDF = null;
//This is where you start
PDFJS.getDocument(url).then(function(pdf) {
//Set PDFJS global object (so we can easily access in our page functions
thePDF = pdf;
//How many pages it has
numPages = pdf.numPages;
//Start with first page
pdf.getPage( 1 ).then( handlePages );
});
function handlePages(page)
{
//This gives us the page's dimensions at full scale
var viewport = page.getViewport( 1 );
//We'll create a canvas for each page to draw it on
var canvas = document.createElement( "canvas" );
canvas.style.display = "block";
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
//Draw it on the canvas
page.render({canvasContext: context, viewport: viewport});
//Add it to the web page
document.body.appendChild( canvas );
//Move to next page
currPage++;
if ( thePDF !== null && currPage <= numPages )
{
thePDF.getPage( currPage ).then( handlePages );
}
}
Here's my take. Renders all pages in correct order and still works asynchronously.
<style>
#pdf-viewer {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.1);
overflow: auto;
}
.pdf-page-canvas {
display: block;
margin: 5px auto;
border: 1px solid rgba(0, 0, 0, 0.2);
}
</style>
<script>
url = 'https://github.com/mozilla/pdf.js/blob/master/test/pdfs/tracemonkey.pdf';
var thePdf = null;
var scale = 1;
PDFJS.getDocument(url).promise.then(function(pdf) {
thePdf = pdf;
viewer = document.getElementById('pdf-viewer');
for(page = 1; page <= pdf.numPages; page++) {
canvas = document.createElement("canvas");
canvas.className = 'pdf-page-canvas';
viewer.appendChild(canvas);
renderPage(page, canvas);
}
});
function renderPage(pageNumber, canvas) {
thePdf.getPage(pageNumber).then(function(page) {
viewport = page.getViewport({ scale: scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({canvasContext: canvas.getContext('2d'), viewport: viewport});
});
}
</script>
<div id='pdf-viewer'></div>
The pdfjs-dist library contains parts for building PDF viewer. You can use PDFPageView to render all pages. Based on https://github.com/mozilla/pdf.js/blob/master/examples/components/pageviewer.html :
var url = "https://cdn.mozilla.net/pdfjs/tracemonkey.pdf";
var container = document.getElementById('container');
// Load document
PDFJS.getDocument(url).then(function (doc) {
var promise = Promise.resolve();
for (var i = 0; i < doc.numPages; i++) {
// One-by-one load pages
promise = promise.then(function (id) {
return doc.getPage(id + 1).then(function (pdfPage) {
// Add div with page view.
var SCALE = 1.0;
var pdfPageView = new PDFJS.PDFPageView({
container: container,
id: id,
scale: SCALE,
defaultViewport: pdfPage.getViewport(SCALE),
// We can enable text/annotations layers, if needed
textLayerFactory: new PDFJS.DefaultTextLayerFactory(),
annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory()
});
// Associates the actual page with the view, and drawing it
pdfPageView.setPdfPage(pdfPage);
return pdfPageView.draw();
});
}.bind(null, i));
}
return promise;
});
#container > *:not(:first-child) {
border-top: solid 1px black;
}
<link href="https://npmcdn.com/pdfjs-dist/web/pdf_viewer.css" rel="stylesheet"/>
<script src="https://npmcdn.com/pdfjs-dist/web/compatibility.js"></script>
<script src="https://npmcdn.com/pdfjs-dist/build/pdf.js"></script>
<script src="https://npmcdn.com/pdfjs-dist/web/pdf_viewer.js"></script>
<div id="container" class="pdfViewer singlePageView"></div>
The accepted answer is not working anymore (in 2021), due to the API change for var viewport = page.getViewport( 1 ); to var viewport = page.getViewport({scale: scale});, you can try the full working html as below, just copy the content below to a html file, and open it:
<html>
<head>
<script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>
<head>
<body>
</body>
<script>
var url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf';
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://mozilla.github.io/pdf.js/build/pdf.worker.js';
var currPage = 1; //Pages are 1-based not 0-based
var numPages = 0;
var thePDF = null;
//This is where you start
pdfjsLib.getDocument(url).promise.then(function(pdf) {
//Set PDFJS global object (so we can easily access in our page functions
thePDF = pdf;
//How many pages it has
numPages = pdf.numPages;
//Start with first page
pdf.getPage( 1 ).then( handlePages );
});
function handlePages(page)
{
//This gives us the page's dimensions at full scale
var viewport = page.getViewport( {scale: 1.5} );
//We'll create a canvas for each page to draw it on
var canvas = document.createElement( "canvas" );
canvas.style.display = "block";
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
//Draw it on the canvas
page.render({canvasContext: context, viewport: viewport});
//Add it to the web page
document.body.appendChild( canvas );
var line = document.createElement("hr");
document.body.appendChild( line );
//Move to next page
currPage++;
if ( thePDF !== null && currPage <= numPages )
{
thePDF.getPage( currPage ).then( handlePages );
}
}
</script>
</html>
The following answer is a partial answer targeting anyone trying to get a PDF.js to display a whole PDF in 2019, as the api has changed significantly. This was of course the OP's primary concern. inspiration sample code
Please take note of the following:
extra libs are being used -- Lodash (for range() function) and polyfills (for promises)....
Bootstrap is being used
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div id="wrapper">
</div>
</div>
</div>
<style>
body {
background-color: #808080;
/* margin: 0; padding: 0; */
}
</style>
<link href="//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf_viewer.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf_viewer.js"></script>
<script src="//cdn.polyfill.io/v2/polyfill.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
<script>
$(document).ready(function () {
// startup
});
'use strict';
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
alert("Please build the pdfjs-dist library using\n" +
" `gulp dist-install`");
}
var url = '//www.pdf995.com/samples/pdf.pdf';
pdfjsLib.GlobalWorkerOptions.workerSrc =
'//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf.worker.js';
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) {
// please be aware this uses .range() function from lodash
var pagePromises = _.range(1, pdf.numPages).map(function(number) {
return pdf.getPage(number);
});
return Promise.all(pagePromises);
}).then(function(pages) {
var scale = 1.5;
var canvases = pages.forEach(function(page) {
var viewport = page.getViewport({ scale: scale, }); // Prepare canvas using PDF page dimensions
var canvas = document.createElement('canvas');
canvas.height = viewport.height;
canvas.width = viewport.width; // Render PDF page into canvas context
var canvasContext = canvas.getContext('2d');
var renderContext = {
canvasContext: canvasContext,
viewport: viewport
};
page.render(renderContext).promise.then(function() {
if (false)
return console.log('Page rendered');
});
document.getElementById('wrapper').appendChild(canvas);
});
},
function(error) {
return console.log('Error', error);
});
</script>
If you want to render all pages of pdf document in different canvases, all one by one synchronously this is kind of solution:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PDF Sample</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="pdf.js"></script>
<script type="text/javascript" src="main.js">
</script>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body id="body">
</body>
</html>
main.css
canvas {
display: block;
}
main.js
$(function() {
var filePath = "document.pdf";
function Num(num) {
var num = num;
return function () {
return num;
}
};
function renderPDF(url, canvasContainer, options) {
var options = options || {
scale: 1.5
},
func,
pdfDoc,
def = $.Deferred(),
promise = $.Deferred().resolve().promise(),
width,
height,
makeRunner = function(func, args) {
return function() {
return func.call(null, args);
};
};
function renderPage(num) {
var def = $.Deferred(),
currPageNum = new Num(num);
pdfDoc.getPage(currPageNum()).then(function(page) {
var viewport = page.getViewport(options.scale);
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
if(currPageNum() === 1) {
height = viewport.height;
width = viewport.width;
}
canvas.height = height;
canvas.width = width;
canvasContainer.appendChild(canvas);
page.render(renderContext).then(function() {
def.resolve();
});
})
return def.promise();
}
function renderPages(data) {
pdfDoc = data;
var pagesCount = pdfDoc.numPages;
for (var i = 1; i <= pagesCount; i++) {
func = renderPage;
promise = promise.then(makeRunner(func, i));
}
}
PDFJS.disableWorker = true;
PDFJS.getDocument(url).then(renderPages);
};
var body = document.getElementById("body");
renderPDF(filePath, body);
});
First of all please be aware that doing this is really not a good idea; as explained in https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#allthepages
How to do it;
Use the viewer provided by mozilla;
https://mozilla.github.io/pdf.js/web/viewer.html
modify BaseViewer class, _getVisiblePages() method in viewer.js to
/* load all pages */
_getVisiblePages() {
let visible = [];
let currentPage = this._pages[this._currentPageNumber - 1];
for (let i=0; i<this.pagesCount; i++){
let aPage = this._pages[i];
visible.push({ id: aPage.id, view: aPage, });
}
return { first: currentPage, last: currentPage, views: visible, };
}
If you want to render all pages of pdf document in different canvases
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="pdf.js"></script>
<script src="jquery.js"></script>
</head>
<body>
<h1>PDF.js 'Hello, world!' example</h1>
<div id="canvas_div"></div>
<body>
<script>
// If absolute URL from the remote server is provided, configure the CORS
// header on that server.
var url = 'pdff.pdf';
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = 'worker.js';
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) {
var __TOTAL_PAGES = pdf.numPages;
// Fetch the first page
var pageNumber = 1;
for( let i=1; i<=__TOTAL_PAGES; i+=1){
var id ='the-canvas'+i;
$('#canvas_div').append("<div style='background-color:gray;text-align: center;padding:20px;' ><canvas calss='the-canvas' id='"+id+"'></canvas></div>");
var canvas = document.getElementById(id);
//var pageNumber = 1;
renderPage(canvas, pdf, pageNumber++, function pageRenderingComplete() {
if (pageNumber > pdf.numPages) {
return;
}
// Continue rendering of the next page
renderPage(canvas, pdf, pageNumber++, pageRenderingComplete);
});
}
});
function renderPage(canvas, pdf, pageNumber, callback) {
pdf.getPage(pageNumber).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport({scale: scale});
var pageDisplayWidth = viewport.width;
var pageDisplayHeight = viewport.height;
//var pageDivHolder = document.createElement();
// Prepare canvas using PDF page dimensions
//var canvas = document.createElement(id);
var context = canvas.getContext('2d');
canvas.width = pageDisplayWidth;
canvas.height = pageDisplayHeight;
// pageDivHolder.appendChild(canvas);
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext).promise.then(callback);
});
}
</script>
<html>
The accepted answer works perfectly for a single PDF. In my case there were multiple PDFs that I wanted to render all pages for in the same sequence of the array.
I adjusted the code so that the global variables are encapsulated in an object array as follows:
var docs = []; // Add this object array
var urls = []; // You would need an array of the URLs to start.
// Loop through each url. You will also need the index for later.
urls.forEach((url, ix) => {
//Get the document from the url.
PDFJS.getDocument(url).then(function(pdf) {
// Make new doc object and set the properties of the new document
var doc = {};
//Set PDFJS global object (so we can easily access in our page functions
doc.thePDF = pdf;
//How many pages it has
doc.numPages = pdf.numPages;
//Push the new document to the global object array
docs.push(doc);
//Start with first page -- pass through the index for the handlePages method
pdf.getPage( 1 ).then(page => handlePages(page, ix) );
});
});
function handlePages(page, ix)
{
//This gives us the page's dimensions at full scale
var viewport = page.getViewport( {scale: 1} );
//We'll create a canvas for each page to draw it on
var canvas = document.createElement( "canvas" );
canvas.style.display = "block";
var context = canvas.getContext('2d');
canvas.height = viewport.viewBox[3];
canvas.width = viewport.viewBox[2];
//Draw it on the canvas
page.render({canvasContext: context, viewport: viewport});
//Add it to an element based on the index so each document is added to its own element
document.getElementById('doc-' + ix).appendChild( canvas );
//Move to next page using the correct doc object from the docs object array
docs[ix].currPage++;
if ( docs[ix].thePDF !== null && docs[ix].currPage <= docs[ix].numPages )
{
console.log("Rendering page " + docs[ix].currPage + " of document #" + ix);
docs[ix].thePDF.getPage( docs[ix].currPage ).then(newPage => handlePages(newPage, ix) );
}
}
Because the entire operation is asynchronous, without a unique object for each document, global variables of thePDF, currPage and numPages will be overwritten when subsequent PDFs are rendered, resulting in random pages being skipped, documents entirely skipped or pages from one document being appended to the wrong document.
One last point is that if this is being done offline or without using ES6 modules, the PDFJS.getDocument(url).then() method should change to pdfjsLib.getDocument(url).promise.then().
Make it to be iterate every page how much you want.
const url = '/storage/documents/reports/AR-2020-CCBI IND.pdf';
pdfjsLib.GlobalWorkerOptions.workerSrc = '/vendor/pdfjs-dist-2.12.313/package/build/pdf.worker.js';
const loadingTask = pdfjsLib.getDocument({
url: url,
verbosity: 0
});
(async () => {
const pdf = await loadingTask.promise;
let numPages = await pdf.numPages;
if (numPages > 10) {
numPages = 10;
}
for (let i = 1; i <= numPages; i++) {
let page = await pdf.getPage(i);
let scale = 1.5;
let viewport = page.getViewport({ scale });
let outputScale = window.devicePixelRatio || 1;
let canvas = document.createElement('canvas');
let context = canvas.getContext("2d");
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
canvas.style.width = Math.floor(viewport.width) + "px";
canvas.style.height = Math.floor(viewport.height) + "px";
document.getElementById('canvas-column').appendChild(canvas);
let transform = outputScale !== 1
? [outputScale, 0, 0, outputScale, 0, 0]
: null;
let renderContext = {
canvasContext: context,
transform,
viewport
};
page.render(renderContext);
}
})();

Categories