Auto close window after print PDF within IFrame - javascript

I am working on a web application that requires the user be able to run a report and have it automatically display the print dialog on the client machine for printing.
I have got that all working fine.
When the user clicks the print button an RDLC LocalReport is generated and returned as a pdf document with the assistance of iTextSharp in a new window/form and the print dialog is displayed.
I would like to be able to automatically close the form after the user either prints or cancels from the print dialog.
The aspx is currently as below (slightly stripped down version):
<body>
<form id="form1" runat="server">
<div>
<iframe id="frmPrint" name="IframeName" width="500" height="200" runat="server"> </iframe>
</div>
</form>
</body>
The code within the aspx.cs:
FileStream LFileStream = new FileStream(HttpContext.Current.Server.MapPath(Session[LReportNameSrcString].ToString()), FileMode.Create);
LFileStream.Write(LResult, 0, LResult.Length);
LFileStream.Close();
//Open existing PDF
Document LDocument = new Document(PageSize.A4);
PdfReader LPdfReader = new PdfReader(HttpContext.Current.Server.MapPath(Session[LReportNameSrcString].ToString()));
//Getting a instance of new PDF writer
PdfWriter LPdfWriter = PdfWriter.GetInstance(LDocument, new FileStream(HttpContext.Current.Server.MapPath(Session[LReportNameString].ToString()), FileMode.Create));
LDocument.Open();
PdfContentByte LPdfContentByte = LPdfWriter.DirectContent;
int LPageNumber = 0;
int LNumberOfPages = LPdfReader.NumberOfPages;
//Add Page to new document
while (LPageNumber < LNumberOfPages)
{
LDocument.NewPage();
LPageNumber++;
PdfImportedPage LPdfImportedPage = LPdfWriter.GetImportedPage(LPdfReader, LPageNumber);
LPdfContentByte.AddTemplate(LPdfImportedPage, LLocalReport.GetDefaultPageSettings().Margins.Left, LLocalReport.GetDefaultPageSettings().Margins.Top);
}
//Attach javascript to the document
//PdfAction LPdfAction = PdfAction.JavaScript("alert('loaded');parent.beginPrint();\r", LPdfWriter);
PdfAction LPdfAction = PdfAction.JavaScript("this.print();\r", LPdfWriter);
LPdfWriter.AddJavaScript(LPdfAction);
LDocument.Close();
//Attach pdf to the iframe
frmPrint.Attributes["src"] = Session[LReportNameString].ToString();
I have tried various methods using JavaScript to close the window but have been so far unsuccessful.
Any ideas would be greatly appreciated.

I found the solution myself in the end.
Using some code I found elsewhere for handling messages from the PDF document. This enabled me to add a listener for the PDF printed event and fire a message at the host container which can be picked up by the JavaScript.
In the ASPX:
// Acrobat JavaScript event handler to handle messages returned from Acrobat document
function messageFunc(messageArray) {
window.close();
}
// Waits until the HTML objects ready / loaded state has been reached
// then add a listener for JavaScript messages being returned from Acrobat document
function loadListener() {
var pdfObject = document.getElementById("pdfObj");
if (typeof pdfObject.readyState === 'undefined') { // ready state only works for IE, which is good because we only need to do this for IE because IE sucks in the first place
pdfObject.messageHandler = { onMessage: messageFunc };
return;
}
if (pdfObject.readyState == 4) {
pdfObject.messageHandler = { onMessage: messageFunc };
} else {
setTimeout(loadListener, 500);
}
}
// Wait until main HTML document has loaded then call function to set up JavaScript event listeners
jQuery(document).ready(function() {
loadListener();
});
In the Code behind:
// Add event listener to detect when the print has begun then return a message (in this case an empty string) to the browser
// window to be picked up by a JavaScript event listener which can then close the window
const string LPostMessageString = "try { this.hostContainer.postMessage(['']); } catch(e) {app.alert(e.message);}";
LPdfAction = PdfAction.JavaScript(LPostMessageString, LPdfWriter);
LPdfWriter.SetAdditionalAction(PdfWriter.DID_PRINT, LPdfAction);
This works well apart from if the user clicks cancel in the print dialog, of which I found no way to detect.

Related

Safari Extension insert HTML Code into Webpage with onclick event

I'm creating my own Safari Extension which inserts 2 buttons into my DOM to improve the user experience on some websites.
I created an Extension using Safari Extension Builder. I created a script called end.js which is loaded after every finished HTTP request. In this script I check my DOM if a specific element exists and insert my buttons next to this element.
The buttons are created like this:
var headerElements = window.document.getElementsByClassName("headers");
if (headerElements.length > 0) {
var header = headerElements[0];
if (header.getElementsByClassName("button1").length == 0) {
var div = window.document.createElement("div");
div.setAttribute("class", "buttons-div");
var button1 = window.document.createElement("button");
button1.setAttribute("class", "button1");
button1.setAttribute("style", "width: 150px;");
button1.innerHTML = "allen folgen";
button1.onclick = function() {
alert("click button1");
};
div.appendChild(button1);
header.appendChild(div);
}
}
As soon as I press the button only an error message is displayed on the console:
onclick — end.js (Zeile 27) TypeError: alert is not a function. (In 'alert("button pressed")', 'alert' is undefined)
Why do I have access to all functions "outside" the onclick event, but as soon as the function is entered I can't access any of those functions? Even if I create my own function
function click() {
alert("test");
}
and set the button's onclick to this:
button1.onclick = click;
I get the same error message.
What am I doing wrong?

Can Zombie.js/Phantom.js be used to get HTML of newly open window by window.open?

I am trying to get html of newly open window after activating a link that uses javascript by zombie.js.
Here is the html code
<html>
<head>
<script type="text/javascript">
function newin(id)
{
var url="page.php?id="+id;
window.open(url,id,"toolbar=no,location=top,directories=no,status=no,scrollbars=yes,hscroll=no,resizable=yes,copyhistory=no,width=1025,height=1250");
}
</script>
</head>
<body>
<div>
123<br/>
234<br/>
345<br/>
</div>
</body>
The Script I am using is:
var Browser = require("zombie");
var browser = new Browser();
browser.visit("http://localhost:8000/testpage.html", function () {
browser.wait(function(){
var selector = "a[href*='newin']";
var elements = browser.queryAll(selector);
for (var e=0;e<elements.length;e++){
browser.clickLink(elements[e],function(){
browser.wait(function(){
console.log(browser.html());
});
});
}
});
});
I am not able to get HTML of any window.Any ideas what is wrong in this code ? Or is this possible with phantomjs??
Finally I come to know that if a link contains JavaScript directly in the href or action, Zombie seems to understand that as opening a new page like a normal hyperlink would. While the JavaScript is still executed correctly, the DOM is lost as a result of Zombie trying to load the invalid target as a new page.
A problematic link would be e.g.
test
There’s no support for javascript:links, it is still an open issue:
https://github.com/assaf/zombie/issues/700

Load scripts after page load - Firefox extension

I am creating a Firefox extension. I want load my external js file for all web pages on load time using Firefox extension. I can successfully load all js file on load event in my html file. But how can i execute into my extension.
window.onload = load;
function load()
{
var filerefs=document.createElement('script')
filerefs.setAttribute("type","text/javascript")
filerefs.setAttribute("src", 'http://code.jquery.com/jquery-1.9.1.min.js')
var head = doc.getElementsByTagName( "head" )[ 0 ].appendChild( filerefs );
}
Please guide me.
If you want to detect page load and not application load, you should do it like this (this first part should be in your main overlay file):
// do not try to add a callback until the browser window has
// been initialised. We add a callback to the tabbed browser
// when the browser's window gets loaded.
window.addEventListener("load", function (event) {
// Add a callback to be run every time a document loads.
// note that this includes frames/iframes within the document
gBrowser.addEventListener("load", load(event), true);
}, false);
Reference from here
I added the event to the load function because the event fires not only on the load itself, but also on other elements, so you have to validate that you are doing it only once (reference here ):
function load(event) {
if (event.originalTarget.nodeName == "#document") {
var htmlns = "http://www.w3.org/1999/xhtml";
var doc = gBrowser.selectedBrowser.contentDocument;
var filerefs = doc.createElementNS(htmlns,'script');
filerefs.setAttribute("type","text/javascript");
filerefs.setAttribute("src", "http://code.jquery.com/jquery-1.9.1.min.js");
doc.getElementsByTagName("head")[0].appendChild(filerefs);
}
}
Instead of using document.getElement..., we have to position on the content of the page, otherwise you are getting elements from your addon (using gBrowser.selectedBrowser.contentDocument gives you access to the current page's dom). And on the createlement, we want to create html elements, so you define and use the html namespace (reference here ).
This should do the trick:

Get instance of child object in iframe

I need to automate a web form which uses iframes to embed child 'forms' which can be considered as separate html pages.
So you get a parent document which contains what they call view fields which are iframes. Within the iframes are the 'child' embedded web pages.
A simple example:
I have cut out a lot off the html to reduce it to a reasonable size
<html>
<body>
<div id="123" arid=123 artype="View" ardbn="vfMyChild"
class="arfid123 ardbnvfMyChild"
STYLE="top:49 left:75 width:1038 height:322" arvfframe="<iframe style="top:0 left:0 width:1038; height:322&quot name="VF123" title="View Field" src="javascript:&quot;&lt;HTML&gt;&lt;/HTML&gt;&quot;" >
</iframe>">
</div>
</body>
</html>
Then the embedded child html could be simple like this:
<html>
<body>
<div id="321" arid=321 artype="Char" ardbn="txtRegister">
<label id="label321" class="label f6">Register:</label>
<textarea id="arid_321" cols="20" maxlen=255 rows=1></textarea>
</div>
</body>
</html>
The html contained in the STYLE= looks a bit odd - not sure why it is like that. But I can see it is sort of an iframe.
I have an instance of the top level document object and I have an instance of the div with id=123. I need to automate the textarea object in the child. I tried the following which did not work.
var viewfields; //is a ref to the div with id=123
if(viewfields) {
window.alert("viewfields.length=" + viewfields.length); //prints len=1 as expected
// line below get Caught exception: Unable to get value of the
// property 'document': object is null or undefined
var innerDoc = viewfields[0].contentDocument || viewfields[0].contentWindow.document;
if(innerDoc) {
window.alert("Wohoo we have an innerDoc");
}
} else
window.alert("no view fields found");
I am testing this using IE9.
Will I be able to get an instance of the inner web page with this html? If so, how?
EDIT
If it helps, here is the actual, unedited html for the div in question.
<div id="WIN_0_536870915" arid=536870915 artype="View" ardbn="vfCubaChildren" class="arfid536870915 ardbnvfCubaChildren" STYLE="top:49; left:75; width:1038; height:322;z-index:1001;background-color:transparent;" arvfframe="<iframe style="top:0&#59; left:0&#59; width:1038&#59; height:322&#59;background-color: transparent&#59;" name="VF536870915" frameborder=1 scrolling="auto" allowtransparency="true" title="View Field" src="javascript:&quot;&lt;HTML&gt;&lt;/HTML&gt&#59 ;&quot;" onload="DVFol&#40;&#41;">
</iframe>">
</div>
That div holds the child form. The child form is like another html web page. It has standard html input fields and textarea's. I need to post text to the textarea's in the child (from the parent). But the problem is I cannot yet access the child html object from the parent.
If you are trying to get the data from the parent looking into the iframe then this is what you are looking for. Bare in mind that this only works if the iframe source is a page from the same domain, otherwise you wouldn't have the permission to access its contents.
http://jsfiddle.net/wao20/Ja54y/19/
First make sure your iframe is loaded, then you can call this to access to your iframe dom.
$('#iframe_id_123').contents().find('#element_inside_your_iframe');
Update:
If you want a pure js solution you can try this:
var f = document.getElementById('f123');
if (f != undefined){
var doc = f.contentDocument || f.contentWindow.document;
var txt = doc.getElementById('secret');
alert(txt.value);
}
else {
alert('No iframe, no secret!');
}
http://jsfiddle.net/wao20/Ja54y/34/
It is possible that the contents of the iframe are not loaded. You can try checking if the iframe is loaded, and if it is, then try to access its document element.
For example, the code to access the document element of the iframe is split into function AfterFrameLoads() which is called during the onload event of the iframe.
var viewfields; //is a ref to the div with id=123`
if(viewfields) {
window.alert("viewfields.length=" + viewfields.length); //prints len=1 as expected
// Check if iframe loading is complete, attach rest of code to onload event
if (viewfields[0].addEventListener){ // for Mozilla, FF, Chrome, etc...
viewfields[0].addEventListener("onload",AfterFrameLoads());
}
else if (viewfields[0].attachEvent){ // for IE and Opera
viewfields[0].attachEvent("onload",AfterFrameLoads());
}
}
// Attempt to access document after iframe loads.
function AfterFrameLoads(){
var innerDoc = viewfields[0].contentDocument || viewfields[0].contentWindow.document;
if(innerDoc) {
window.alert("Wohoo we have an innerDoc");
}
else {
window.alert("no view fields found");
}
}
var viewfields; //is a ref to the div with id=123`
if(viewfields) {
window.alert("viewfields.length=" + viewfields.length); //prints len=1 as expected
// Check if iframe loading is complete, attach rest of code to onload event
if (viewfields[0].addEventListener){ // for Mozilla, FF, Chrome, etc...
viewfields[0].addEventListener("onload",AfterFrameLoads());
}
else if (viewfields[0].attachEvent){ // for IE and Opera
viewfields[0].attachEvent("onload",AfterFrameLoads());
}
}
// Attempt to access document after iframe loads.
function AfterFrameLoads(){
var innerDoc = viewfields[0].contentDocument || viewfields[0].contentWindow.document;
if(innerDoc) {
window.alert("Wohoo we have an innerDoc");
}
else {
window.alert("no view fields found");
}
}

ZeroClipboard user script adding in mouse over, working in firefox, but not chrome

I am using zeroclipboard to add a "copy" link to each row in a fairly large list, within a user script. To accomplish that, I using a method similar to the one listed on this page, where the ZeroClipboard.Client() element for each row is created when the user mouses over the row. This is working great in FireFox, but not in Chrome.
Also as a note: I copied the contents of the ZeroClipboard.js file into the user script itself instead of including it in an external file.
Here is the markup that creates the copy button for each element
<span style="color:blue; text-decoration:underline; cursor:pointer" id="copy_'+id+'" class="CopyLink" link="'+url+'" onmouseover="clipboard.add(this)">Copy</span>
Here is the code segment that adds the clipboard's client object:
function main(){
window.clipboard = {
load: function (){
if(!clipboard.initialized){
ZeroClipboard.setMoviePath("http://www.swfcabin.com/swf-files/1343927328.swf");
clipboard.initialized=true;
console.log("Clipboard intialized");
}
},
add: function(element){
clipboard.load();
var clip = new ZeroClipboard.Client();
console.log('Clipboard client loaded: ' + element.id);
clip.glue(element, element.parentNode);
console.log('Clipboard glued: ' + element.id);
clip.setText(element.getAttribute('link'));
console.log('Clipboard text set: ' + element.getAttribute('link'));
clip.addEventListener('complete',function(client,text) {
console.log('Clipboard copied: ' + text);//doesn't fire in chrome
});
clip.addEventListener('load',function(client) {
console.log('Clipboard loaded: ' + element.getAttribute('link'));
});
}
}
//other code in user script including injecting above markup
//as well as contents of ZeroClipboard.js
window.ZeroClipboard = { ... }
}
var script = document.createElement("script");
script.appendChild(document.createTextNode('('+main+')()'));
(document.head || document.body || document.documentElement).appendChild(script);
In this block, every console.log fires in FireFox when I mouse over and click the copy span, but in chrome, all except the 'complete' listener fire. I was able to verify that ZeroClipboard is working in my Chrome by using the example on this page. I am also able to verify that the flash object is being added to the page in the correct location, but it is simply not responding to a click.
Since the zeroclipboard code is no longer being maintained according to the site, I'm hoping someone out there can help me out. I'm thinking there is possibly some issue with dynamically adding the embedded flash objects in chrome on mouseover, or perhaps some difference between user scripts in chrome vs firefox with greasemonkey? Any help would be greatly appreciated, thanks
I'm not sure the reason behind it but I have been running into this on Chrome as well. I had two zeroclipboard implementations, one that was visible on page load, and one that was only visible when the user opened a dialog. The one that was visible on page load worked as expected, but the other one didn't. In order to "solve" the issue, I had to render the zeroclipboard link, set its absolute position to be off the screen (-500 px), then add some javascript to move the link into place when the dialog opens. This is an ugly solution but I think is the only way to get it to work in Chrome. Your case is particularly hairy since you have lots of dynamic zeroclipboards on your page whereas I only had one, but it seems to me that there's no reason this won't work for you.
<!-- <script type="text/javascript" src="http://davidwalsh.name/demo/ZeroClipboard.js"></script> -->
function copyText(fieldName,buttonName){
var fieldNameTemp =fieldName;
var buttonNameTemp =buttonName;
var val = "";
try{
val = navigator.userAgent.toLowerCase();
}catch(e){}
var swfurl = "js/ZeroClipboard.swf";
setTimeout(function () {
ZeroClipboard.setMoviePath(swfurl);
var clip = new ZeroClipboard.Client();
clip.addEventListener('mousedown', function () {
clip.setText(document.getElementById(fieldNameTemp).value);
});
clip.addEventListener('complete', function (client, text) {
try{
if(val.indexOf("opera") > -1 || val.indexOf("msie") > -1 || val.indexOf("safari") > -1 || val.indexOf("chrome") > -1){
alert('Your text has been copied');
}
}catch(e){
alert('Please alert not use on fireFox');
}
});
clip.glue(buttonNameTemp);
}, 2000);
}

Categories

Resources