Rails html file sent as pdf - javascript

I have a printable invoice system on my website. This is done with a print.html.erb version of my invoice show page, which is embedded in an iframe and then printed using javascript $("#print-frame").get(0).contentWindow.print();. So it essentially prints the print.html.erb file.
I want to be able to send the exact same invoice as a pdf in an email from a controller. In other words, it should look exactly like the print preview of this page (which can be previewed using finder in pdf if you use Firefox)
(print.html.erb has inline stylesheets)
How?

We use acts_as_flying_saucer for this - it's a rails wrapper for flying_saucer which is a java app that converts html pages to pdfs.
https://github.com/amardaxini/acts_as_flying_saucer
When you print your page, it will use any stylesheets with media set to "print" or "all". You would set up a template for rendering to pdf which uses the same stylesheets. You can then view the page in the browser with this template - it should look like your print preview. Then you can render the page to pdf confident that what you see is what you get. You don't need to go through this process every time, just when you're first setting it up really, but it's good as you can test the formatting in a web page without having to render to pdf every time.
Couple of potential gotchas:
Your pages need to pass a strict XHTML test. They should anyway, but in the browser you can get away with being a bit sloppy, but not here. xmllint is handy for debugging, there are also various browser plugins for XHTML validation.
when you have locally sourced images in your page, <img> tags will need to be modified to use a filesystem location instead of a path relative to your public folder as you would normally.

Related

What is the best way to display webpage content for a given URL using javascript?

I am developing a small labeling tool that given a URL should display a document hosted on that URL and allow a user to choose a label for that document.
I want to display the contents of the URL for this purpose. As far as I know, I can either get the URL content, parse the contents, and display or use an iframe option.
Without using parser
Iframes are not enabled for the target URL, the contents of which I want to display. Is there any other way to do this using javascript without using parser?
Using parser
I can crawl the contents of the URL, get everything between and dump it in the webpage area.
I'm new to javascript and front end development so I am not sure whether these are the only options.
Are there other options to do this?
If the parser is the only option, Can I dump the HTML that I get from the remote URL? I understand that images and other media that may be within on remote url won't be displayed. Is there any other caveat to this method? More importantly, Is this the best way to do this?
Most sites do it via the iframe like you mentioned like codepen.
Also, you can use Puppeteer ( a headless browser ) to do these sort of things. Get the contents using web scraping or take a screenshot or print a pdf. Pretty nifty library.
Most things that you can do manually in the browser can be done using
Puppeteer! Here are a few examples to get you started:
Generate screenshots and PDFs of pages. Crawl a SPA (Single-Page Application) and generate pre-rendered content (i.e. "SSR"
(Server-Side Rendering)).
Automate form submission, UI testing, keyboard input, etc. Create an up-to-date, automated testing environment.
Run your tests directly in the latest version of Chrome using the latest JavaScript and browser features.
Hope this helps !

ASP.NET: on the server side, create PDF copy of HTML, CSS and Javascript webpage, exactly as it appears in Google Chrome

Is it possible to use C# to render an ASP.NET view on the server side and save it as a PDF, preserving all the visual elements that involve CSS and Javascript, exactly as it renders in Chrome? The Javascript includes the latest versions of the standard Bootstrap and d3 libraries, as well as code using d3 to draw SVG charts. The page's CSS heavily uses Bootstrap.
I've tried a few things including IronPdf, but it completely destroys the formatting no matter what options I have tried. The only good results I've been able to get are by actually viewing the web page in Chrome, trying to print it, and saving it as a PDF that way. I'm trying to basically get exactly the same results using backend C# code to generate the PDF, without any user interaction needed. Can this be done? If it's impossible to render perfectly as a PDF I would also be open to other visual file formats that preserve the appearance of the web page.
You can run any install of chrome in headless mode and send it a command to print:
chrome --headless --disable-gpu --print-to-pdf=file1.pdf https://www.google.co.in/
I did this a couple of years ago. I created a microservice that took a URI, a test javascript, and a massage script then returned a pdf.
Test Script:
The test script is injected into the page and is called repeatedly until it returns true. The script should verify that components are in a properly loaded state. (This could be skipped by simply using a long delay prior to printing the pdf)
Massage Script:
The massage script is not required. It is injected into the page to alter the javascript or HTML prior to printing the pdf.
I used this heavily to load the entire user JOM including all Angular data stores (NGRX) since the user context was not present in the server-side Chrome instance.
Delayed Printing:
Since this is not a feature supported by chrome, I made an endpoint on my server that would hold a GET connection indefinitely. A script referencing the endpoint was injected into each page to be printed. When the Test Script returned ready, the code would cancel the script request by changing the script tag src to an empty script file that would return. This would conclude the last item that Chrome was waiting on and the documentready event would fire thus triggering the chrome print.
In this way, I was able to control Chrome printing on complex authenticated pages at my server.

How to manipulate a local text file from an HTML page

I've generated an HTML file that sits on my local disk, and which I can access through my browser. The HTML file is basically a list of links to external websites. The HTML file is generated from a local text file, which is itself a list of links to the remote sites.
When I click on one of the links in the HTML document, as well the browser loading the relevant site (in a new tab), I want to remove the site from the list of sites in the local text file.
I've looked at Javascript, Flask (Python), and CherryPy (Python), but I'm not sure these are valid solutions.
Could someone advise on where I should look next? I'd prefer to do this with Python somehow - because it's what I'm familar with - but I'm open to anything.
Note that I'm running on a Linux box.
First, Javascript cannot modify the local filesystem from the context of a webpage. To allow that would be a massive security concern.
Any server-side web framework can do this, and Flask is a great one to use because it's so lightweight. The general steps you would want to take are:
When / is requested, load the list of links.
Change each link to point to /goto?line=<line_number>.
Display the list to the user.
Then when you click a link:
When /goto is requested, load the list of links.
Remove the line number from the list.
Save the list of links.
Return status code 302, with the real URL as the Location header.
There is many ways to do this
Here is the easiest 3
Use JavaScript
2 install wampserver or similar and use php o modify the file
3 don't use te browser to delete and instead use a bat file to open the browser and remove the link from the text file

Open local html file in current window with Javascript Bookmarklet

I'm trying to build a sample bookmarklet to grab current webpage source code and pass it to a validator. Validator is not a an online website, but a folder with bunch of javascript and html files. I'm trying to open file:///C:/Users/Electrifyings/Desktop/Validator/Main.html file with the help of javascript bookmarklet code and put the source code in the textarea in the newly opened window, but it is not working for some reasons that I'm not aware of.
Here is the sample code with algorithm:
javascript:(function(){var t = document.body.innerHTML;window.open('file:///C:/Users/RandomHero/Desktop/test.html',_self);document.getElementById("validator_textarea")=t;})()
Here are the steps:
Grab current web page source code in a variable.
Open locally stored HTML web page in current or new window or new tab (either way is fine with me, but no luck)
Put the source code from the variable into the validator textarea of the newly opened HTML file.
I have tried above code with a lot of variations, but got stuck on the part where it opens the new window. Either it's not opening the new window at all or it is opening blank window without loading the file.
Would love to get some help with this issue, thanks a lot.
Oh and btw,
Windows 7 x64, Tried IE, Firefox and Chrome. All latest and stable builds. I guess it's not a browser side issues, but something related to javascript code not opening the URI with file:/// protocol. Let me know if any more details are needed. :)
You wouldn't want a webpage you visit to be able to open up file://c:/Program Files/Quicken/YourSensitiveTaxInfo right? Because then if you make a mistake and go to a "bad" website (either a sleazy one or a good one that's been compromised by hackers), evil people on the intarweb would suddenly have access to your private info. That would suck.
Browser makers know this, and for that reason they put VERY strict limits to prevent Javascript code from accessing files on a user's local computer. This is what is getting in the way of your plan.
Solutions?
build the whole validator in to the bookmarklet (not likely to work unless it's really small)
put your validator code up on the web somewhere
write a plug-in (because the user has to choose to install a plug-in, they get much more freedom than webpages ... even though for Firefox, Chrome, etc. plug-ins are basically just Javascript)
* * Edit * *
Extra bonus solution, if you don't limit yourself to a purely-client-side implementation:
Have your bookmarklet add a normal (HTML) form to the page.
Also add an iframe to the page (it's ok if you hide it with CSS styling)
Set the form's target attribute to point to the iframe. This will make it so that, when the user submits the form and the server replies back to that submission, the server's reply will go to the (hidden) iframe, instead of replacing the page as it normally would.
Add a file input to your form - you won't be able to access the file within that input using Javascript, but that's ok because your server will be doing the accessing, not your bookmarklet.
Write a server-side script which takes the form submissions, reads the file that came with it, and then parrots that file back as the response. In other words, you'll have a URL that you can POST to, and when it sees a file in the POST's contents, it will respond back with the contents of that file.
Now that you've got all that the user can pick their validator file using the file input, upload it to your server, your server will respond back with the file it just got, and that file will appear as the contents of the iframe.
And now that you finally have the file that you worked so hard to get (inside your iframe) you can do $('#thatIframe').html() and viola, you have access to your file. You can save the current page's source and then replace the whole page with that uploaded file (and then pass the saved page source back to the new validator page), or you can do whatever else you want with the contents of the uploaded validator file.
Of course, if the file doesn't vary from computer to computer, you can make all of that much simpler by just having a server that sends the validator file back; this could be a pure Apache server with no logic whatsoever, as all it would have to do is serve a static file.
Either way though, if you go with this approach and your new file upload script is not on the same server as your starting webpage, you will have a new security problem: cross-domain script limitations. However, these limitations are much less strict than local file access ones, so there are ways to work around them (JSONP, cross-site policy files, etc.). There are already tons of great Stack Overflow posts explaining these techniques, so I won't bother repeating them here.
Hope that helps.

HTML5 / JavaScript: open text file, load into textarea / save textarea content to text file

I want to do two things in my browser:
Load a text file into a textarea (has to be choosen via dialog box)
Save the content of a textarea into a text file (has to be choosen via dialog box again)
Load a video file and grab the file path to use it with a video player (1)
I've been looking around for a while on the internet. There are some solutions for IE only via ActiveXObjects, which I can't use (IE, seriously?). HTML5 file API has limited usability because I can't access the selected file's path.
I also found save dialogs for textareas, but they ignored line breaks for some strange reason and I don't know how to fix that, if possible at all.
So here are my requirements and options:
Support for FF and Chrome
JavaScript, HTML5 (and PHP, if it has to be)
possibly Silverlight, but I'm not very familiar with it and may only copy and paste :-/
it has to work on Mac as well
There is a dirty hack that gets the job done without resorting to Flash or Silverlight, or using a server, and it works in most browsers:
var uriContent = "data:application/octet-stream," + encodeURIComponent(fileContentsAsString);
window.open(uriContent, 'Save Your File');
JS runs in a sandbox. That means: no access to files on the filesystem. HTML5 file API is the first „native” (as in not flash nor activex) attempt to grant limited access to the users file system.
The File API is HTML that would allow you to access data, after which you can manipulate binary blobs in JavaScript, but as written this is not possible in pure JS and HTML based on your requirements.
The big blocker is "saving to a text file." The only way I've been able to do this is by opening up an iFrame that calls a server side language (such as PHP) to set the content type in the header to a type that prompts a download.
Flash and Silverlight are "client" technologies that run outside of the sandbox, which sounds like your only option at this point.
My ideas:
Load a text file: Use a normal HTML upload form (if you want to script, maybe submit it via AJAX)
Save a text file: Use a textarea and upon submitting, create the file server-side and then offer it to download. (As mentioned before, client-side scripts do not have access to the computer's file system)
Load a video file: Is the video on the server already? Otherwise will need an upload just like the text file. Then use a flash plugin to play the file from the server (the URI should be known to you then)
All of these are relatively simple to achieve using PHP. Line breaks from a textarea stay as \n in PHP.
Tutorials: Form handling in PHP, File upload in PHP
Edit: Since PHP runs server-side you should not run into a lot of problems because of browser diversity. Alternatively, you can do all of these in Flash or Silverlight as well, although from my point of view that takes more learning and is less comfortable for the user.

Categories

Resources