Here is the task: make images on a page printable. Not really challenging unless the images are fetched via ajax from an external server and loaded in a lightbox (Mootools MediaboxAdvanced), that makes this task a little more challenging and worthy to write about.
So the basic JS solution to print something would be to use the print() method (window.print()). Since it’s a method of the whole window object and we only want our image printed we have to open it in another window and then call print() method like this:
printWindow = window.open( "http://www.domain.com/path/to/image.jpg", '_blank' ); printWindow.window.print();
Now to put the same in the project’s context (MooTools and MediaBox Advanced):
$('mbImage').addEvent('click',function(e){ e.preventDefault(); printWindow = window.open(e.target.src, '_blank'); printWindow.window.print(); });
Here we add a click event to every image to open it in a new window and print it. We can make a fancy icon later. Functions and IDs might change from framework to framework and from script to script but not the logic.
The whole thing should work, but it doesn’t, it just prints an empty page. That must have something to do with the picture not being loaded yet and there is no DOM so the onLoad event wouldn’t be triggered. Anyway there is a quick, if a little hacky fix for that:
$('mbImage').addEvent('click',function(e){ e.preventDefault(); printWindow = window.open(e.target.src, '_blank'); setTimeout("printWindow.window.print()", 1000); });
Basically the same, but we call print() method after waiting for one second, since the image will already be cached that should always be enough and still not too long to get annoying. And it works, as far as I can tell it’s a legitimate solution for printing local images.
The problem is, it doesn’t work with external ones, so we have to think of something else. What would help here is a real DOM with one image as its content and a load event. Something like this:
<html> <body onload="window.print();"> <img src="http://www.domain.com/path/to/image.jpg" /> </body> </html>
Totally doable, just one question remains – how to dynamically send the image URL from our real page to this one. GET would be complicated because of all the special characters and POST would require a form which is kinda too much extra code.
So COOKIE looks like our best option, we just have to set the cookie on click, then open the dummy page the same way, make it read the url from the cookie and put it into the img tag. The last thing can be accomplished via JavaScript as well as PHP, PHP might be a little better since it’s not that public and we might want to validate our image url, just in case…
Here is the final version of the code, frontend part that saves the image url on click, it also injects an extra anchor tag with “print-image” class to add the fancy icon mentioned above (couple of lines in css file). For production we wrap the code in “load” event to make sure the lightbox script is loaded and ready to go:
window.addEvent('load', function() { var printLink = new Element('a', { href: '#', 'class': 'print-image', html: '', events: { click: function(e){ e.preventDefault(); var src = $('mbImage').getElement('img').src; Cookie.write("printurl", src, {duration: 1}); printWindow = window.open("/print-image.php", '_blank'); } } }); printLink.inject($('mbBottom')); });
Again say in jQuery we would have to load Cookie library but the code would remain very similar. It creates an element with onClick event and injects it into lightbox code, on click the current open image is saved in a cookie and the print-image.php opens in a new window. Here is what happens there:
<?php // external file /print-image.php $size = getimagesize($_COOKIE['printurl']); if ($size) {$src = $_COOKIE['printurl'];} else {$src = "http://www.domain.com/path/default.jpg";} ?> <html> <body onload="window.print();"> <img src="<?php echo $src; ?>" /> </body> </html>
It picks up the url from cookie and checks if it’s an image with getimagesize() function (yeah, just in case, should there be some evil stuff instead of our image, we just show the default image). It then puts the url into the img tag. After the page is loaded “onload” event fires and prints the image, in this case it doesn’t matter if it’s an external image or local.
It is valuable script. I use this script.
nice to hear 🙂
Nice blog….So useful for me ………….
Good article. I’m going through a few of these issues as well..