My script is a Firefox addon so has access to sensitive code like access to filesystem etc.
I display a Panel populated with html content, I could easily send input to the addon code using postMessage
When I run the code below a pdf is generated and a download prompt is shown so i can select directory to place file, but I'd like to save the file using javascript directly to a file in background without the download prompt showing.
Something like: doc.saveToFile("/path/to/file") // custom method in my addon code
Would this be possible using the jsPDF object?
<html>
<head>
<script type='text/javascript' src='jspdf.source.js'></script>
</head>
<body>
Hey
<script>
var doc = new jsPDF();
doc.text(20, 20, 'Hello bob');
doc.save('test.pdf');
</script>
</body>
</html>
This should work on your Firefox add-on code:
const { OS } = require("resource://gre/modules/osfile.jsm");
var pathToFile = OS.Path.join("path", "to", "file.pdf");
var doc = new jsPDF();
doc.text(20, 20, 'Hello bob');
var ab = doc.output('arraybuffer');
var u8 = new Uint8Array(ab);
OS.File.writeAtomic(pathToFile, u8).then(
function()
{
alert('File written!');
},
function(e)
{
alert('Error ' + e);
}
);
If you aren't using the Add-On SDK, but rather a normal extension, replace the first line with:
const { OS } = Components.utils.import("resource://gre/modules/osfile.jsm", {});
Check this out for further info on OS.File: https://developer.mozilla.org/en-US/docs/JavaScript_OS.File/OS.File_for_the_main_thread
But why you don't wanna use your add-on? I think that you don't be able to access the filesystem or things like that, with jsPDF or pdf.js (http://mozilla.github.io/pdf.js/, which is a mozilla project), you will be able to print something that is being displayed on the window, but not sure if you can access some local files.
Related
I am trying to make a simple web API that outputs the base64 encoded image string of a Desmos graph of the provided equation. (I included the code below) It works fine except for the fact that when a GET request is sent to the website, it returns the code of the website that was used to create the image, with the base64 image nowhere to be found.
<!DOCTYPE html>
<html>
<body>
<div id="calculator" style="width: 100%; height: 100vh;"></div>
<script src="https://www.desmos.com/api/v1.5/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6"></script>
<script>
const urlParams = new URLSearchParams(window.location.search);
console.log(urlParams)
const formula = urlParams.get('formula')
const step = urlParams.get('step')
const image = urlParams.get('image')
const api = urlParams.get('api')
console.log(formula)
console.log(step)
console.log(image)
var options
var imageMode = ({
expressions: false,
settingsMenu: false,
border: false,
zoomButtons: false,
});
if(image === "true") {
options = imageMode
}
var elt = document.getElementById('calculator');
var calculator = Desmos.GraphingCalculator(elt,options);
calculator.setExpression({ id: 'graph1', latex: formula });
console.log(calculator.screenshot())
if(api === "true") {
results = (`<pre>${calculator.screenshot()}</pre>`)
document.body.innerHTML = results
}
</script>
</body>
</html>
When everything is said and done, I want this page to return the plain base64 encoded image string (ideally) or HTML that actually has the string in it could work as well. I would appreciate any and all help.
This API only seems to only operate within the context of an HTML DOM (such as a browser). To work around this and generate images with NodeJS code, you'd need to have a server-side DOM. Puppeteer is one option. It allows you to run a headless Chromium browser which you can manipulate via a NodeJS API. So at a high level, your API code could:
Start a puppeteer browser
Open a puppeteer page to the HTML for generating the graph
Call the puppeteer API to generate a screenshot
Send the screenshot image in the API response
Other headless browsers like PhantomJS also exist as well, so you'll want to look around at what options are available to you.
Below are my codes in extension.js. If you look at the codes, I tried different ways to load the file to my extension. No matter what, I always getting
VM3051:15 Uncaught ReferenceError: PDFJS is not defined
Tried with putting the file in different locations.
appAPI.ready(function($) {
console.log("pdf min js loading");
appAPI.resources.includeJS('jspdf.js');
// appAPI.resources.includeJS('js/jspdf.js');
// appAPI.resources.includeRemoteJS('//cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js');
//$.globalEval(appAPI.resources.get('//cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js'));
console.log("done");
setTimeout(function(){
alert(window.location.href);
if(window.location.href.indexOf(".pdf") > -1) {
console.log("its a pdf");
alert("pdf");
var doc = new jsPDF();
}else{
alert($.trim($('div').find('h1,h2,h3,h4,h5,p,span').text()));
}
},6000);
});
Here is the file structure
I cannot modify manifest.json because the extension should be unique for all the browsers not just for chrome.
I'm confused, the two CloudFlare URLs in your code reference the project jsPDF. I would assume the local pdf.js does the same too.
In your code, you're using
PDFJS.getDocument();
This syntax comes from PDF.js which is a totally different project from Mozilla.
If you're sticking with jsPDF, your code should be something like:
var doc = new jsPDF();
doc.text(20, 20, 'Hello world.');
doc.save('Test.pdf');
Or you'll need to include the correct library for PDF.js.
After the edits you've made and your comments, it seems you've switch completely over to jsPDF but you're still getting the same error which clearly mentions PDF.js.
Are you sure you're debugging the correct and last version of your app which is only using jsPDF?
I've setup a small reproduction example on Crossrider using only jsPDF.
The extension.js code is the following:
appAPI.ready(function($) {
console.log("pdf min js loading");
appAPI.resources.includeJS('jspdf.js');
console.log("done");
var doc = new jsPDF();
console.log(doc);
});
When debugging the extension, I'm getting this result:
doc is an object containing an instance of jsPDF which I can later use.
There should be no mention of PDF.js whatsoever. My only guess could be that you're running / debugging a version of your extension still containing references to this project.
i have use docx.js for generate docx file, but generaeted docx doenot open. my generated docx file output is
i have included following js file into my Html page
<script type="text/javascript" src="js/Docx/jszip.js"></script>
<!-- Include main js lib -->
<script type="text/javascript" src="js/Docx/DOCX.js"></script>
and javascript function is
function test() {
//alert("test fn call");
var doc = new DOCXjs();
doc.text('DOCX.js is a free open source library for generating Microsoft Word Documents using pure client-side JavaScript.');
//doc.text('It was developed by James Hall at Snapshot Media.');
var output = doc.output('datauri');
}
when i click button this function will be calling, and also i want to add datatable as a content of word document so how to add content using Docx.js?
Probably you are trying to use the docx.js without server, that will not work because it can't load the necessary files.
if you are executing the code on a server then edit the path of '/blank/' somewhere in the docx.js file
$.ajax({
url: '/blank/' + files[file],
complete: function(r) {
//file_data[this.url.replace(/blank_/, '')] = r.responseText;
zip.add(this.url.replace('/blank/', ''), r.responseText);
file_count_current ++;
if (file_count == file_count_current) {
doOutput();
}
}
});
EDIT: I'm trying to read all the files in a specific folder and list the files in there, not read the content of a specific file. I just tried to simply create an FileSystemObject and it doesn't do anything either. I show an alert (which pops up) beforfe making the FileSystemObject, and one after it (which isn't shown). So the problem is in simply creating the object.
Original:
I am trying to read all the files in a folder by using JavaScript.
It is a local HTML file, and it will not be on a server, so I can't use PHP I guess.
Now I'm trying to read all the files in a specific given folder, but it doesn't do anything on the point I make a FileSystemObject
Here is the code I use, The alert shows until 2, then it stops.
alert('1');
var myObject, afolder, date;
alert('2');
myObject = new ActiveXObject("Scripting.FileSystemObject");
alert('3');
afolder = myObject.GetFolder("c:\\tmp");
alert('4');
date = afolder.DateLastAccessed;
alert("The folder"+name+" is a temporary folder.");
Am I doing this the right way?
Thanks!
The method I found with a Google search uses HTML5 so if you are using a modern browser you should be good. Also the tutorial page seems to check if the browser you are using supports the features. If so you should be good to follow the tutorial which seems pretty thorough.
http://www.html5rocks.com/en/tutorials/file/dndfiles/
This solution only works on IE11 or older since it is MS based
<script type="text/javascript">
var fso = new ActiveXObject("Scripting.FileSystemObject");
function showFolderFileList(folderspec) {
var s = "";
var f = fso.GetFolder(folderspec);
// recurse subfolders
var subfolders = new Enumerator(f.SubFolders);
for(; !subfolders.atEnd(); subfolders.moveNext()) {
s += ShowFolderFileList((subfolders.item()).path);
}
// display all file path names.
var fc = new Enumerator(f.files);
for (; !fc.atEnd(); fc.moveNext()) {
s += fc.item() + "<br>";
}
return s;
}
function listFiles() {
document.getElementById('files').innerHTML = showFolderFileList('C:');
}
</script>
<input type='button' onclick='listFiles()' value='List Files' />
<div id="files" />
is it possible to create a file on localhost with javascript?
Not in a webpage. If you're using Windows Script Host then yes you can through ActiveX, but I presume you're not doing that. You can however, send data back to the webserver through AJAX and have it store it for you.
You can create cookies to store data on the local machine, which pretty much is the only way to create files on the local machine.
I assume you have the content of the file ready. Then you can prompt a "save as" dialog like this:
var exportText; // this variable needs to contain your content
var targetFilename = "myfilename.ext"
function presentExportFile() {
var download = document.createElement('a');
// you need to change the contenttype to your needs in the next line.
download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(exportText));
download.setAttribute('download', targetFilename);
download.style.display = 'none';
document.body.appendChild(download);
download.click();
document.body.removeChild(download);
}
2017 addendum: Since I wrote this, I had one exotic browser (xombrero) reject it. So, I can't say for certain that this is The Way.
no, this would be a security issue.
You can create a file through a plugin, see https://developer.mozilla.org/en/Code_snippets/File_I%2F%2FO
<html>
<head>
<title>Create File</title>
<! This function will create a file named 'newfile' on the same directory as the HTML unless path is given>
<script language="javascript">
function openFile()
{ var filePath = 'c:/filename.txt';
var fileSysObj = new ActiveXObject('Scripting.FileSystemObject');
fileSysObj.CreateTextFile(filePath);
}
</script>
</head>
<body>
This will create a file called "filename.txt" on your c:\ drive.
You must accept the ActiveX control or disable prompting to create a file.
<button type=submit name=button onClick="openFile();">create file</button>
</body>
</html>