How to show the Annotation links on pdfJs - pdf.js

I have implement the pdfjs library to show the pdf in my application.
I have shown the pdf successfully. But the links on the pdf are not clickable. As i want o click the links to visit on the link.
pdf vsrsion : 2.10.377
Below is my code hope you will understand.
<div id="canvasPDFViewer" class="canvasPDFViewer"></div>
<div class="annotationLayer" id=”annotation-layer”></div>
This is the js I have include.
<script defer>
window.pdfjsLib.GlobalWorkerOptions.workerSrc = '/_js/pdf.worker.min.js';
</script>
This is the code how i am showing the pdf, the pdf is visible but, the links are not clickable.
let loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) {
let totalPageNumber = pdf.numPages;
for(let pageNumber = 1; pageNumber <= totalPageNumber; pageNumber++) {
pdf.getPage(pageNumber).then(function(page) {
let scale = 1;
let viewport = page.getViewport({ scale: scale }); // Prepare canvas using PDF page dimensions
let canvas = document.createElement("canvas"); // Render PDF page into canvas context
canvas.height = viewport.height;
canvas.width = viewport.width;
let canvasContext = canvas.getContext("2d");
let renderContext = {
canvasContext: canvasContext,
viewport: viewport
};
//page.render(renderContext);
page.render(renderContext).promise.then(function() {
return page.getAnnotations();
}).then(function(annotationData) {
if(annotationData.length == 0)
return;
var pdf_canvas = $(canvas).offset();
$("#annotation-layer").css({ left: pdf_canvas.left + "px", top: pdf_canvas.top + "px", height: pdf_canvas + "px", width: pdf_canvas + "px" });
pdfjsLib.AnnotationLayer.render({
viewport: viewport.clone({ dontFlip: true }),
div: $("#annotation-layer").get(0),
annotations: annotationData,
page: page
});
});
document.getElementById("canvasPDFViewer").appendChild(canvas);
});
}
}, function (reason) {
// PDF loading error
// console.error(reason);
});
And the error is i am getting.
pdf.min.js:22 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'externalLinkTarget')
at LinkAnnotationElement.render (pdf.min.js:22:1)
at Function.render (pdf.min.js:22:1)
at eval (eval at <anonymous> (jquery.min.js:2:1), <anonymous>:32:48)
Why i am getting the error.
I have tried the solution with below link.
[https://usefulangle.com/post/94/javascript-pdfjs-enable-annotation-layer]
But no luck.

Related

How i can extract svg element with text pdf js

I need extarct svg element with text from pdf. But if i did like this:
PDF:
Pdf link https://dropfiles.org/2dTlpxTN
const PDF_PATH = "https://dropfiles.org/2dTlpxTN";
const PAGE_NUMBER = 1;
const PAGE_SCALE = 1.5;
const SVG_NS = "http://www.w3.org/2000/svg";
pdfjsLib.GlobalWorkerOptions.workerSrc =
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
function buildSVG(viewport, textContent) {
// Building SVG with size of the viewport (for simplicity)
const svg = document.createElementNS(SVG_NS, "svg:svg");
svg.setAttribute("width", viewport.width + "px");
svg.setAttribute("height", viewport.height + "px");
// items are transformed to have 1px font size
svg.setAttribute("font-size", 1);
// processing all items
textContent.items.forEach(function (textItem) {
// we have to take in account viewport transform, which includes scale,
// rotation and Y-axis flip, and not forgetting to flip text.
const tx = pdfjsLib.Util.transform(
pdfjsLib.Util.transform(viewport.transform, textItem.transform),
[1, 0, 0, -1, 0, 0]
);
const style = textContent.styles[textItem.fontName];
// adding text element
const text = document.createElementNS(SVG_NS, "svg:text");
text.setAttribute("transform", "matrix(" + tx.join(" ") + ")");
text.setAttribute("font-family", style.fontFamily);
text.textContent = textItem.str;
svg.append(text);
});
return svg;
}
async function pageLoaded() {
// Loading document and page text content
const loadingTask = pdfjsLib.getDocument({ url: PDF_PATH });
const pdfDocument = await loadingTask.promise;
const page = await pdfDocument.getPage(PAGE_NUMBER);
const viewport = page.getViewport({ scale: PAGE_SCALE });
const textContent = await page.getTextContent();
// building SVG and adding that to the DOM
const svg = buildSVG(viewport, textContent);
document.getElementById("pageContainer").append(svg);
// Release page resources.
page.cleanup();
}
document.addEventListener("DOMContentLoaded", function () {
if (typeof pdfjsLib === "undefined") {
// eslint-disable-next-line no-alert
alert("Please build the pdfjs-dist library using\n `gulp dist-install`");
return;
}
pageLoaded();
});
I extracted text with out Font and i extract all text. I need extract text as image.
If i do this:
pdfDoc_.getPage(pageNumber).then(function (page) {
var canvasEl = document.createElement('canvas');
var context = canvasEl.getContext('2d');
var viewport = page.getViewport({scale: imagesSetting_reader.scaleText});
canvasEl.height = viewport.height;
canvasEl.width = viewport.width;
var back;
var renderContext = {
canvasContext: context,
background:back,
viewport: viewport
};
page.render(renderContext).promise.then(function () {
resolve(canvasEl.toDataURL("image/png"));
})
});
It extracted text and background image.
if i do like this :
page.getOperatorList().then(opList => {
var svgGfx = new pdfjsLib.SVGGraphics(page.commonObjs, page.objs);
return svgGfx.getSVG(opList, viewport);
}).then(svg => {
console.log(svg)
return svg;
});
And extracted text from svg, i got error :
error on line 1 at column 101: Namespace prefix svg on svg is not defined
How i can extract only svg text with font and convert it to image ?
Like this:

Render PDF inline mobile and desktop

Hi
i'm struggling browsing a pdf inline well on mobile and Desktop
env is vite 3.1.3, rails 7.0.4
Desktop i brought to run on all Browsers by mozilla/pdfjs but on mobile it doesnt show anything.
My Code is (on Rails)
view
<canvas id="the-canvas"></canvas>
javascript
// NPM
import * as pdfjsLib from 'pdfjs-dist/build/pdf'
window.showMozillaPdf = function () {
var pdfData = atob(gon.doc_b64);
console.log(pdfjsLib)
pdfjsLib.GlobalWorkerOptions.workerSrc = '/documents/pdfjs_worker';
console.log('pdf-part-2!')
var loadingTask = pdfjsLib.getDocument({data: pdfData});
loadingTask.promise.then(function (pdf) {
console.log('PDF loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function (page) {
console.log('Page loaded');
var scale = 1.5;
var viewport = page.getViewport({scale: scale});
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
console.log('Page rendered');
});
});
}, function (reason) {
// PDF loading error
console.error(reason);
});
}
The workers js (/documents/pdfjs_worker) i inserted from a controller because of mime type conflicts. This can be made nicer but it runs now.
This runs well on desktop but doesnt show anything on Mobile (iPhone 11 / Safari)
Has anyone experience with mozilla/pdfjs on Mobile?
thanks,
Chris
found it
i had to change the way for getting the url to the worker asset:
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf'
import workerUrl from 'pdfjs-dist/legacy/build/pdf.worker.min?url'
...
pdfjsLib.GlobalWorkerOptions.workerSrc = workerUrl;
this replaces the '/documents/pdfjs_worker'
and i had to use the /legacy/ for getting it to run on mobile.
See vite-docs

how to print an element with jspdf / Angular

I found below code and trying to modify it to print an specific div element. Below code opens print dialog but shows empty screen. I dont know where to put my id of div element in the code.
print(){
var doc = new jsPDF("portrait", "mm", "a4");
doc.autoPrint();
const hiddFrame = document.createElement('iframe');
hiddFrame.style.position = 'fixed';
// "visibility: hidden" would trigger safety rules in some browsers like safari,
// in which the iframe display in a pretty small size instead of hidden.
// here is some little hack ~
hiddFrame.style.width = '1px';
hiddFrame.style.height = '1px';
hiddFrame.style.opacity = '0.01';
const isSafari = /^((?!chrome|android).)*safari/i.test(window.navigator.userAgent);
if (isSafari) {
// fallback in safari
hiddFrame.onload = () => {
try {
hiddFrame.contentWindow.document.execCommand('print', false, null);
} catch (e) {
hiddFrame.contentWindow.print();
}
};
}
var blob = doc.output("blob");
window.open(URL.createObjectURL(blob), '_blank');
}

Konva converting stage toDataUrl() do not work in chrome browser,but work well in safari browser

I have Konva Stage with few layers, when I try convert to image all stage - result is OK in safari browser , when I try convert stage in chrome ,firefox etc. - result is failed. I think that toDataUrl() method does
not work well in chrome browser ,firefox browser etc except for safari browser
<button id="save" type="button">save</button>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
function downloadURI(uri, name) {
var link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
function drawImage(imageObj) {
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
// darth vader
var darthVaderImg = new Konva.Image({
image: imageObj,
x: stage.getWidth() / 2 - 200 / 2,
y: stage.getHeight() / 2 - 137 / 2,
width: 200,
height: 137,
name: 'myimg',
draggable: true
});
// add cursor styling
darthVaderImg.on('mouseover', function () {
document.body.style.cursor = 'pointer';
});
darthVaderImg.on('mouseout', function () {
document.body.style.cursor = 'default';
});
layer.add(darthVaderImg);
stage.add(layer);
stage.on('click tap', function (e) {
// if click on empty area - remove all transformers
if (e.target === stage) {
stage.find('Transformer').destroy();
layer.draw();
return;
}
// do nothing if clicked NOT on our rectangles
if (!e.target.hasName('myimg')) {
return;
}
// remove old transformers
// TODO: we can skip it if current rect is already selected
stage.find('Transformer').destroy();
// create new transformer
var tr = new Konva.Transformer();
layer.add(tr);
tr.attachTo(e.target);
layer.draw();
})
document.getElementById('save').addEventListener(
'click',
function () {
var dataURL = stage.toDataURL({ pixelRatio: 3 });
downloadURI(dataURL, 'stage.png');
},
false
);
}
var imageObj = new Image();
imageObj.onload = function () {
drawImage(this);
};
imageObj.src = 'https://www.decanterchina.com/assets/images/article/550/136031_decanter-cava-tasting-1.jpg';
</script>
Any possible reasons or solutions ? Thanks!!
If you look into the console you will see a message:
Konva warning: Unable to get data URL. Failed to execute 'toDataURL'
on 'HTMLCanvasElement': Tainted canvases may not be exported.
You have CORS issue. Take a look here for solutions:
Tainted canvases may not be exported
https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

HTML2Canvas creating multiple divs

I'm trying to create a PDF using jsPDF and HTML2Canvas.
I have multiple DIVs to insert into the PDF.
If I try to put all DIVs into a container and render once then it only puts the first page height into the PDF.
Can't figure out how to render multiple divs and stick them in the same PDF so that it keeps going page by page.
JAVASCRIPT
function genPDF() {
html2canvas(document.getElementById("container"), {
onrendered: function (canvas) {
var img = canvas.toDataURL();
var doc = new jsPDF();
doc.addImage(img, 'PNG');
doc.addPage();
doc.save('test.pdf');
}
});
}
HTML
<div id="container">
<div class="divEl" id="div1">Hi <img src="img1.JPG"> </div>
<div class="divEl" id="div2">Why <img src="img2.PNG"> </div>
</div>
<button onClick="genPDF()"> Click Me </button>
Add each of your images separately.
You need to wait for all the html2canvas renderings are done and added to pdf and then save your final pdf.
One way to achieve this by using JQuery and array of promises, actual code would look like this:
function genPDF() {
var deferreds = [];
var doc = new jsPDF();
for (let i = 0; i < numberOfInnerDivs; i++) {
var deferred = $.Deferred();
deferreds.push(deferred.promise());
generateCanvas(i, doc, deferred);
}
$.when.apply($, deferreds).then(function () { // executes after adding all images
doc.save('test.pdf');
});
}
function generateCanvas(i, doc, deferred){
html2canvas(document.getElementById("div" + i), {
onrendered: function (canvas) {
var img = canvas.toDataURL();
doc.addImage(img, 'PNG');
doc.addPage();
deferred.resolve();
}
});
}
For me it works like that:
$('#cmd2').click(function () {
var len = 4; //$x(".//body/div/div").length
var pdf = new jsPDF('p', 'mm','a4');
var position = 0;
Hide
for (let i = 1;i <= len; i++){
html2canvas(document.querySelector('#pg'+i),
{dpi: 300, // Set to 300 DPI
scale: 1 // Adjusts your resolution
}).then(canvas => {
pdf.addImage(canvas.toDataURL("images/png", 1), 'PNG', 0,position, 210, 295);
if (i == len){
pdf.save('sample-file.pdf');
}else{
pdf.addPage();
}
});
}
});
You could try this, using the follwing javascript references in the HTML. Html2Canvas and jsPDF are quite picky with versions you use.
https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"
https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.0.272/jspdf.debug.js"
var forPDF = document.querySelectorAll(".js-panel-pdf");
var len = forPDF.length;
var thisPDF = new jsPDF('p', 'mm', [240, 210]); //210mm wide and 297mm high
for (var i = 0; i < forPDF.length; i++) {
html2canvas(forPDF[i], {
onrendered: function(canvas) {
thisPDF.addImage(canvas.toDataURL("images/png", 1), 'PNG', 0, 0, 210, 295);
if (parseInt(i + 1) === len) {
thisPDF.save('sample-file.pdf');
} else {
thisPDF.addPage();
}
}
});
}
Stuart Smith - This is not working it does not allow to download the pdf
here is java script code
function generatePDF(){
var imgData;
var forPDF = document.querySelectorAll(".summary");
var len `enter code here`= forPDF.length;
var doc =new jsPDF('p','pt','a4');
for (var i = 0; i < forPDF.length; i++){
html2canvas(forPDF[i],{
useCORS:true,
onrendered:function(canvas){
imgData = canvas.toDataURL('image/jpg',1.0);
var doc =new jsPDF('p','pt','a4');
doc.addImage(imgData,'jpg',10,10,500,480);
if (parseInt(i + 1) === len) {
doc.save('sample-file.pdf');
} else {
doc.addPage();
}
}
});
}
}

Resources