Displaying and downloading a pdf in an iframe - javascript

I am using wix and in order to customize any html you need to use an embed object which creates a sandboxed iframe on the site. I have a decent grasp of how this works and posting messages to it but what I am having difficulties with is generating a pdf into this iframe.
I have done some reading and I think I get the overall concept. While traditionally you would just set the source to some document on a server somewhere I am generating the content dynamically based on user action. So it looks like something like pdfkit and creating a blob is the way to go.
I think I am able to generate the pdf without issues as well as a blob url no problem
[![console image][1]][1]
I can manually open the console and get that URL and paste it in the browser and the document opens exactly how I expect it. However I can't get it to display normally in the browser.
I have tried setting the src of various elements = to the blob url without luck.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
blah
<script src="https://github.com/foliojs/pdfkit/releases/download/v0.11.0/pdfkit.standalone.js"></script>
<script src="https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js">
</script>
</head>
<body>
<script>
const doc = new PDFDocument
const stream = doc.pipe(blobStream())
doc.fontSize(25).text('Testing document', 100, 80);
console.log(doc);
doc.end();
stream.on('finish', function() {
window.src = stream.toBlobURL('application/pdf');
const a = document.createElement('a');
a.href = stream.toBlobURL('application/pdf');
a.download = 'ShoppingList' || 'download';
console.log("download IS",a)
});
</script>
</body>
</html>
In addition to setting the window.src I have tried document.src iframe.src which returns an error.
displaying isn't strictly necessary but a download link would be. Is there some other way I can do this to get this data? I feel I am missing something very simple.
I have had to change the examples as given on [http://pdfkit.org/docs/getting_started.html][2] but I don't think this is any issue as the package is working as expected and the document is being created.
Edit:
I have made some progress on this but am getting stuck in downloading it. What I did was these 2 things.
<input type="button" id = "dload" onclick="location.href='';" value="Download Shopping List" />
document.getElementById("dload").onclick = function(){location.href = stream.toBlobURL('application/pdf')};
the pdf actually shows in the iframe as expected with the full capabilities of a pdf preview however the download doesn't work at all it just says failed - network error and the filetype is not a pdf which makes sense. Is there something else I can add to get this working?
Edit2: Tried one more thing that doesn't work very well since popups are mostly blocked
window.open(stream.toBlobURL('application/pdf'), '_blank');
this, while it technically works is really messy and is causing a number of problems. Also it works differently on mobile vs desktop. There has to be some simple way to just show a pdf but it seems to just result in more questions the more I search.
[1]: https://i.stack.imgur.com/le6o9.png
[2]: http://pdfkit.org/docs/getting_started.html

I have partially solved my question and it is good enough for what I need. Here is what I did.
<html>
<head>
<script src="https://github.com/foliojs/pdfkit/releases/download/v0.11.0/pdfkit.standalone.js"></script>
<script src="https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js"></script>
<script type="text/javascript">
window.onmessage = (event) => {
if (event.data) {
// create a document and pipe to a blob
var doc = new PDFDocument();
var stream = doc.pipe(blobStream());
doc.font('Helvetica');
doc.fontSize(20);
doc.text('Some Text',200,20);
// end and display the document in the iframe to the right
doc.end();
stream.on('finish', function() {
const blob = stream.toBlob('application/pdf')
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = "YourFileName";
a.style.position = 'fixed';
a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
};
};
</script>
</head>
<body>
</body>
</html>
while I can't see the pdf using this method it does download correctly which was the more important piece. Technically I could combine the two but since the download button on the iframe doesn't work I think it would be confusing for someone having a separate button to actually download it. So I have a separate button outside the frame that triggers the "onmessage" it is a function of wix. This triggers all document generation and download.

Related

pdf.js not loading pdf file

I'm very new to pdf.js and am probably making some basic mistake. I'm trying to just copy the "Hello World with document load error handling" example provided here:
https://mozilla.github.io/pdf.js/examples/
I just copy and pasted the code across to new html, css and js files but didn't work. I tried changing the url in pdfjsLib.getDocument(url) to a local file directory on my computer i.e. ./pdf/test.pdf but didn't work. I tried changing the
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
to
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist#2.2.228/build/pdf.min.js"></script>
but that didn't work either.
My console log states two things:
1) Loading failed for the with source “file:///pdf.js/build/pdf.js”
2) TypeError: pdfjsLib is undefined
I understand I am a beginner here but would it be too much to ask the guys who put so much effort into creating it to write a few lines about how to use it for beginners like me? Anyways, if someone can help solve my what I'm sure is a very basic question, it would be much appreciated.
Thanks
Most of these problems are caused by the fact that you are running your test by opening an html file, thus the browser use the file:// instead of http:// or https://.
A quick "hack" to fix the problem in you situation is to insert the <base href="https://mozilla.github.io"> (HTML base tag) inside the head of your test html file (I used the given example as it is, with no changes inside a blank html document) so that you fool the browser and make it search on the Github for the files.
The "correct" way to test such codes and libraries is to install a local web-server and serve the files from there (usually as http://localhost).
An example of the test I created:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<meta name="description" content="Testing pdf.js">
<meta name="author" content="GramThanos">
<!-- hack code -->
<base href="https://mozilla.github.io">
</head>
<body>
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<h1>PDF.js 'Hello, world!' example</h1>
<canvas id="the-canvas"></canvas>
<script type="text/javascript">
// If absolute URL from the remote server is provided, configure the CORS
// header on that server.
var url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.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 = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
// Asynchronous download of PDF
var loadingTask = pdfjsLib.getDocument(url);
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);
});
</script>
</body>
</html>

html5 Image Filters with Canvas

I have download the source from this http://www.storminthecastle.com/projects/imagefilters1/. It is regarding some image manipulation in html5 canvas.
Inside the source, it will load the image located in a local directory...
function reset() {
imageURL = "./sandbox.jpg";
imageFilter = grayscale;
document.querySelector("#filename").innerHTML = "";
update();
}
The above is working in my project. But I am trying to load an image from an url, so I modified it to the following...
function reset() {
imageURL = "http://xxxxxx.jpg";
imageFilter = grayscale;
document.querySelector("#filename").innerHTML = "";
update();
}
When I test it, the image is being displayed correctly. However, all the features are not working anymore and I don't know why. I have no idea why it cannot take in url as the argument and I don't know how to modify it to make it work. Any helps?
Thanks for the link provided. I further read on the COR issue and managed to locate that line of coding to be added.
img.crossOrigin = '';
//img domain different from app domain
img.src = 'http://xxx.jpg';
Simply set the crossOrigin property of the image to make it work. Basically, this will allow cross domain image for manipulation. Without it, any cross domain will be blocked and you will get the security exception. Really thanks for the helps! :)
To add-on, I have only tested using Chrome and is working.

Image resize by Javascript

I've web app running. And it uses ajax upload. The issue is recently users are uploading too big images. So it's taking a bit more time. Users are complaining about that. So what I was thinking is this, 'If I somehow crop and resize the image via js and then send it to the server via ajax upload then the time will be reduced'. So is there any way to do that? Any idea for it?
A solution is to use modern ways like FileReader and Canvas (But this works only on the latest modern browsers).
http://caniuse.com/filereader
http://caniuse.com/canvas
In this example i show how to let the client resize an image before uploading by setting a max width & height mantaining aspect ratio.
In this example max widthHeight = 64;
your final image is c.toDataURL();
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
var h=function(e){
var fr=new FileReader();
fr.onload=function(e){
var img=new Image();
img.onload=function(){
var MAXWidthHeight=64;
var r=MAXWidthHeight/Math.max(this.width,this.height),
w=Math.round(this.width*r),
h=Math.round(this.height*r),
c=document.createElement("canvas");
c.width=w;c.height=h;
c.getContext("2d").drawImage(this,0,0,w,h);
this.src=c.toDataURL();
document.body.appendChild(this);
}
img.src=e.target.result;
}
fr.readAsDataURL(e.target.files[0]);
}
window.onload=function(){
document.getElementById('f').addEventListener('change',h,false);
}
</script>
</head>
<body>
<input type="file" id="f">
</body>
</html>
In the canvas part of the code you can also add a cropping function.
Edit as asked in the comments
c.toDataURL();
is the image base64_string you can store it in a hidden input,append to a new FormData() or wherever you want.
on the server
$data=explode(',',$base64_string);
$image=base64_decode($data[1]);
write to file
$f=fopen($fileName,"wb");
fwrite($f,$image);
fclose($f);
or
$gd=imagecreatefromstring($image);
you can also store the whole base64 image string in the database and always use that.

Play a loaded file in javascript

I'm trying to load a file from the user and want to play it with javascript.
The file is loaded correctly, and I can access it seeing the name, the type and so on, with the FileList API.
What I can't do is to play the obtained file. I tried to do
myFile.play();
like I always do with loaded file, but it doesn't work.
Any idea?
If you only want to play the media content, instead of using FileReader, i suggest you to use the createObjectURL method. It is more efficient since it do not create a string containing the file content.
https://developer.mozilla.org/fr/docs/DOM/window.URL.createObjectURL
Just do :
audio/video.src=window.URL.createObjectURL(myFile);
Don"t forget to revoke your uri when loading another media file to avoid memory leaks :
window.URL.revokeObjectURL(audio/video.src);
You need FileReader API too (API compatibility) and your browser need support HTML5 audio tag.
Something like this:
<body>
<input type='file' id='fileInput' />
<audio id='player' />
<script type='javascript'>
var fileInput = document.getElementById("fileInput");
var freader = new FileReader();
freader.onload = function(e) {
document.getElementById('player').src = e.target.result;
document.getElementById('player').play();
}
fileInput.onchange = function(e) {
var files = e.target.files;
freader.readAsDataURL(files[0]);
}
</script>
</body>
You can read here for more.
My answer based on migerh's solution

how to remove delay in image loading in html?

I create a web page and put an img tag on this page. the img.src is the url of the image from the network IP camera. It works but the stream I get have delays. I understand this delay is because I load the image and loading image takes some time. my question is how can I minize these delay. I do the following;
<script language="Javascript">
x = document.getElementById("stream");
intervalID = setInterval(LoadImage, 0);
function LoadImage()
{
x = document.getElementById("stream");
x.src = "http://IP:PORT/jpg/image.jpg";
}
</script>
<img id="stream"
width="640" height="480"
alt="Press reload if no video displays"
border="0" style="cursor:crosshair; border:medium; border:thick" />
<button type="button" id="btnStartLive" onclick="onStartLiveBtnClick()">Start Live</button>
I've just found your question in the unanswered section and decided to give it a go. The following script creates an internal <img> tag (with new Image()), assigns the necessary attributes, then sets an onload "event handler" attribute, which checks when the image loaded. When that function is called, the #stream is replaced by the new internal image tag.
In case the #stream is not directly inside the body tag (i.e. inside another element like a <div>), edit streamParentElement to point to the image's parent element.
I added a ?nocache query parameter to the string, because while I was testing the code, I found out that the image tag was changing but the visible image stayed the same. I also added a loadDelay, because the images on my client were loading too fast, and it got to the point where it crashed my browser. I advise you to not lower that value below 50. Live demonstration of this code here
<script language="Javascript">
var streamParentElement = document.body, loadDelay = 200;
setTimeout(MakeImage,1);
function MakeImage(){
var img = new Image();
img.src = "http://IP:PORT/jpg/image.jpg?nocahce="+new Date().getTime()+Math.random();
img.width = 640;
img.height = 480;
img.style.border = 0;
img.style.cursor = 'crosshair';
img.id = 'stream';
img.onload = function(){
var stream = document.getElementById("stream");
streamParentElement.insertBefore(img,stream);
stream.outerHTML = '';
setTimeout(MakeImage, loadDelay);
};
}
</script>
<img id="stream" alt="Press reload if no video displays" />
create your html page. eg:
<html>
<head>
<title>
Some Page
</title>
</link rel="stylesheet" href="path to your css file"/>
<script type="text/javascript" src="path to you javasctipt file"></script>
</head>
<body>
<h1 onClick="javascript:someFunction()">
Click here
</h1>
</body>
</html>
you can then create many other "someFunction" functions. They all just reference the AJAX function.this is just to make typing a little less...
The easiest ajax way:
var path;
var div;
var xmlhttp = new XMLHttpRequest();
function someFunction()
{
path = "path to another html file";
div = "the name of the div tag's content you want to change eg. content";
AJAX(path, div);
}
function AJAX(path, div)
{
xmlhttp.open("GET", path, false);
xmlhttp.send();
if (xmlhttp.readyState == 4)
{
document.getElementById(div).innerHTML = xmlhttp.responseText;
}
}
now just include the image in the html file.
ajax allows you to change just the content of the div you gave it, without reloading the whole page.
I would try putting your images into photoshop and making the resolution 72 or less. Also if you save the images as a GIFs they should be much smaller.
maybe handle the image loading in an outside script that runs faster than a web page refreshes, then embed it? like a "videoloader.js" so that it can load separately and not have to wait on the html page to load.
<script src="videoloader.js"></script>
you could also convert the images shown on the fly into lesser quality jpgs using javascript
see if this helps:
Load lower quality image if higher one inst available

Categories