Printing a (part of) webpage with Javascript - javascript

I am aware of two ways of calling the "print" dialog of browser (I used the Search, of course):
document.print()
document.execCommand('print', false, null)
What is the difference between them? Support across browsers? Papers, docs or standards? Which is more correct thing to use?
Another question: what is the most straight way to print given part of a webpage? I know we can create new window or iframe to call any of two print methods above. Which one has less pitfalls?

I've tested different ways of printing part of webpage across browsers:
Chrome, Firefox, Opera (12 and new), IE11, 10, 9 and 8. I've tried to create new window, new iframe, or use existing iframe on the page. And then tried .print() and .execCommand('print').
Note: Keep in mind that .print() is called on window, and .execCommand() is called on document.
Code used for testing can be found here
Correct me if my testing code is wrong, I just wanted to find the clearest way to do the job. My conclusions:
Opera 12 can not print part of a webpage (?)
IEs don't print() iframes and windows, except current window.
Calling print() on documents inside iframes or created windows in IEs breaks the print() on current document. Be careful!
jQuery plugin printThis uses tricks for IE to do the job, and it just works. The only exception is Opera 12. By the way, this plugin uses print().
execCommand('print') works almost everywhere and with any approach (iframes, window). It's not supported by Firefox though.
execCommand() returns false if call was unsuccessful, so if you don't want to use plugins and magic tricks, create window or iframe, call execCommand('print') and if it returns false, call print().
One more thing:
Creating an iframe is tricky: you can't access its window or document directly (yes, you have ContentDocument property, which behaves differently across browsers). You should name it and then call window.frames[name] to get window object from that iframe. Do not try to call window.frames(id) - it will return the iframe.

That last method mentioned in the accepted answer, then, ends up looking like this:
iframe = document.getElementById('iframe-id');
var printed = iframe.contentWindow.document.execCommand('print', false, null);
if (!printed) window.print();
alternative:
try {
iframe = document.getElementById('iframe-id');
iframe.contentWindow.document.execCommand('print', false, null);
}
catch(e) {
window.print();
}
similar method used by printThis
if (document.queryCommandSupported("print")) {
$iframe[0].contentWindow.print();
$iframe[0].contentWindow.document.execCommand("print", false, null);
} else {
$iframe[0].contentWindow.focus();
$iframe[0].contentWindow.print();
}

You can use the combination of window.open and execComand (saveas
exemple:
<script type= "text/javascript">
function saveas() {
var oPrntWin = window.open("","_blank","width=1,height=1,left=1,top=1,menubar=yes,toolbar=yes,resizable=yes,location=no,scrollbars=yes");
oPrntWin.document.open();
oPrntWin.document.write(editeur.innerHTML);
oPrntWin .document.execCommand("SaveAs",true,"C:\\My Documents\\Saved Content.html");
oPrntWin.document.close();
}
</script>
editeur.html is a part of my document
you can do same for your frame
replace the writting in a new Window by the property "src" for the body

Related

Why does this simple login script work in Tampermonkey but not Greasemonkey?

I have this tiny little script that I run inside Chrome using Tampermonkey and works great.
However, when I use it in Firefox with Greasemonkey, it shows up on the active list, meaning its matching the page but it doesn't actually execute the code. I know it has to be a simple something I am overlooking but its not hitting me.
var myVar=setInterval(function(){myTimer();},100);
function myStopFunction()
{
clearInterval(myVar);
}
function myTimer()
{
var p1 = "Login";
var p2 = "mode=login";
var x = document.body.innerHTML;
if (x.match(p1) && x.match(p2)){
document.documentURI = "/ucp.php?mode=login";
}
myStopFunction();
}
Script Logic/Function
I am using a timer to prevent the script from triggering over and over in a permanent loop.
It simply detects if I am logged into a phpBB forum or not, if not send me to the login page so I can log in.
I am using document URI so that the location of the original is preserved so upon login, it takes me right back to it.
Often phpBB when you log in, it will take you back to the index page so this preserves my original intent of going to the actual link.
This script works perfectly and as expected on Chrome using TM but on Firefox using GM it doesn't trigger, am I missing something here?
From the Firefox spec:
(document.documentURI)
Returns the document location as string. It is read-only per DOM4 specification.
And, indeed, the latest spec still specifies that this attribute must be read only.
If Chrome lets you write this property, then that is non-standard behavior and maybe a bug.
Use location.assign(), or location.replace(), or just programmatically click the login button -- which often preserves the target page.

Cannot Call a Flash Function from Javascript

I've been all over here and can't find an answer. I have a .swf sitting in an HTML page and I am trying to call a function inside of it from javascript. I can talk out from flash to the javascript but I can't get it to talk back in. I know I am targeting the object properly because I use console.log() on it and confirms what it is targeting.
I'm triggering the test from flash, calling a javascript function from inside the .swf, and having that function call the internal Flash function.
Flash Code:
//adds callback
ExternalInterface.addCallback("sendToFlash", flashTalkedTo);
//function called by the callback
public function flashTalkedTo():void{
//runs another function in javascript to log a string
ExternalInterface.call("callMe")
}
//calls javascript that tries to talk to Flash
ExternalInterface.call("catchFromFlash")
Javascript Code:
//function called by Flash that initiates
function catchFromFlash(){
talkToFlash()
}
//function that tries to talk to flash
function talkToFlash(){
document.getElementById('Noodleverse').sendToFlash()
}
//function called by Flash in the end to confirm call made
function callMe(){
console.log("Call Me")
}
Any help works, thanks!
Flash, and plugins in general, are a little bit fiddly. They don't behave quite like normal elements, and their functions don't behave quite like normal functions. For example, you can't save the element into a value and call a function from that. You also need to be careful because in some browsers the object is used and in others the embed is used.
The best way to call a function is to use swfobject (https://code.google.com/p/swfobject/) to abstract everything. Personally though, I use this (based on experience, maybe somebody can offer improvements):
HTML:
<object id="myplugin" ...>
...
<embed name="myplugin" ... />
</object>
JavaScript:
var o1=document.myplugin;
if(o1&&!!o1.myFlashFunction){
return document.myplugin.myFlashFunction(); // DO NOT USE o1 here. It will fail.
}
var o2=window.myplugin;
if(o2&&!!o2.myFlashFunction){
return window.myplugin.myFlashFunction(); // DO NOT USE o2 here
}
The first case (document) is for most new browsers. For example, Chrome will find the embed object. The second (window) is for IE and finds the object (IE, at least old IE, ignores embed). I'm not 100% sure the second is needed, because IE might also work with document, so call that voodoo code. Also window.myplugin will give an array of all matching elements in Chrome, FireFox, etc. (but we expect those to already be taken care of)

Accessing the window object in Firefox addon content script?

I can't seem to access the window object in a content script. Is this normal?
For example, this does nothing:
window.onload = function() {
console.log("Hello from the onload");
};
Instead, I have to use the unsafeWindow object.
unsafeWindow.onload = function() {
console.log("Hello from the onload");
};
I must be missing something simple right?
Don't use window.onload, instead write:
window.addEventListener("load", function() {
console.log("Hello from the onload");
}, false);
window.onload has the limitation that there can only be one event listener, setting a different listener replaces the existing one - that's already a reason why you should never use it. In case of the Add-on SDK things get more complicated because the content script has a different view of the DOM then the web page. So just use addEventListener.
Oh, and please don't use unsafeWindow - it is (as the name already says) inherently unsafe.
The window object available to you in a content script is actually a proxy - hence unsafeWindow works and window does not. I did some tests and document.addEventListener does not work either:
https://builder.addons.mozilla.org/package/150362/latest/
jQuery seems to work fine though, I imagine there is some magic they do to ensure that they fire no matter what.
The workaround is simply set contentScriptWhen to 'end' and run your code immediately - this should always work as the content script is attached when the document is finished loading.
I did log this bug regarding what I like to think of as the 'wtf?' aspect of this behaviour - I think the result is surprising to web developers and we should try to be less surprising:
https://bugzilla.mozilla.org/show_bug.cgi?id=787063

Why is javascript saying that addcallback function is not defined?

my first time on here.
My problem is with AS3, Javascript and possibly the browsers Firefox and IE.
I have done so much searching for an answer so i will print my code:
i am using this line to call the flash application and in all browsers its combatible and actually traces in firebug to hold an OBJECT->FLASH_ID so thats not the problem.
var obj = document.getElementById('test');
then i use addcallback:
obj.sendStatus(loggedIn);
now whats weird is that i trace all individual elments in chrome and
-obj = flash object
-sendStatus = flash->function
-loggedIn = either false or true;
everything works great but when i am on firefox or ie
it traces differently
-obj = flash object
-sendStatus = undefined
-loggedIn = either true or false;
now what am i missing??????????
i tried embedding rather than object insertion
i made sure that the id's were all unique
i checked to make sure i had the right flash object selected with getElementById
im so confused.. and it feels like something simple.
I know about some browser - dependent timing problems, making the interface of the flash object available...
A timer could help, try this:
var obj = document.getElementById('test');
setTimeout(function(){obj.sendStatus(loggedIn);}, 500);
500 is a bit to long, but just to be sure. If it works you can try to lower it to 200 - 300.
make sure you declared allowScriptAccess = sameDomain both in embed tag and object tag
in case you don't use swfObject
Maybe the way you get a reference to the swf is wrong, try this
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html
The problem is that using ExternalInterface requires both parties (browser and flash) to be ready.
You can have the flash poll a method in the page which just returns true so that you know its ready to receive calls from flash.
On the flip side if the page is cached, it can sometimes happen that the page wants to send to flash before flash is ready, so I use a callback to the page telling it flash is ready, so its like a handshake, once both parties are ready, then we can start sending data back and forth.
This has been my approach since Firefox 3.

IE 7 error writing to a document

I am using the prototype JavaScript library to read the contents of a text area (which is often the complete mark-up for another HTML page), create a new window and then set the new window content to be that same mark-up, like so:
var htmlContent = $("msHTML").value;
var win = window.open("preview.cfm", "Preview HTML", "left=20,top=20,width=500,height=500,toolbar=0,resizable=1,scrollbars=1");
win.document.write(htmlContent); //TODO - throwing an error in IE 7 - Error Invalid Argument
win.document.close();
This works just fine in Firefox but as mentioned in the comment, it's giving an Illegal Argument exception in IE7.
Can anyone help?
I couldn't find anything in the prototype library that might get around browser differences when setting document content. I know there might be another windowing library built on prototype that might work, but that seems like overkill for this issue I think.
Thanks in advance!
The 2nd parameter for
window.open(url, name, features);
"name" in IE, MUST NOT CONTAIN SPACES. (affects all versions of IE)
//works
window.open('page.html', 'mypage', '');
//FAILS in IE
window.open('page.html', 'my page', '');
Remove URL and Title from window.open() - it's a security related issue. You don't need to specify URL anyway since your overwriting window's content on the next line of your code.
This works:
var win = window.open('', '', 'left=20,top=20,' +
'width=500,height=500,toolbar=0,resizable=1,scrollbars=1');
win.document.write($("msHTML").value);

Categories