I have a documentation type page with an iframe inside. I'm trying to override standard browser print (Ctrl + p) to print contents of an iframe only.
I know how to print an iframe content using javascript:
window.frames['webcontent'].focus();
window.frames['webcontent'].print();
I know how to do run javascript before printing e.g. as described here: Check for when a user has selected to print using javascript
Any advise?
Thanks
It can be easily achieved through CSS: See thisJSfiddle: Tested
<style>
#media print{
body * {display:none;}
.toPrint{display:block; border:0; width:100%; min-height:500px}
}
</style>
Let an HTML File be:
<body>
<h3>I do not want this title Printed</h3>
<p> This paragraph should not be printed</p>
<iframe class="toPrint" src="http://akitech.org"></iframe>
<button onclick="window.print()">Print</button>
</body>
It's not possible (using Javascript). There is some experimental support for user-initiated print events in modern browsers, but those are not cancelable ("simple events") so the entire page will still print even if you interject custom code to print the frame of interest.
Given this limitation, your best bet is probably to offer users a large button that fires your custom frame printing function (see printContentFrameOnly below, fire it without arguments) and hope that they'll use the button instead of ctrl-p.
If it would be possible, this would be the way to do it (based on this answer):
// listener is a function, optionally accepting an event and
// a function that prints the entire page
addPrintEventListener = function (listener) {
// IE 5.5+ support and HTML5 standard
if ("onbeforeprint" in window) {
window.addEventListener('beforeprint', listener);
}
// Chrome 9+, Firefox 6+, IE 10+, Opera 12.1+, Safari 5.1+
else if (window.matchMedia) {
var mqList = window.matchMedia("print");
mqList.addListener(function (mql) {
if (mql.matches) listener(); // no standard event anyway
});
}
// Your fallback method, only working for JS initiated printing
// (but the easiest case because there is no need to cancel)
else {
(function (oldPrint) {
window.print = function () {
listener(undefined, oldPrint);
}
})(window.print);
}
}
printContentFrameOnly = function (event) {
if (event) event.preventDefault(); // not going to work
window.frames['webcontent'].focus();
window.frames['webcontent'].print();
}
addPrintEventListener(printContentFrameOnly);
The idea is to set the iframe content somewhere on the page, and print ONLY that content, by hiding the original content.
This can be done by getting the iframe content when Ctrl+P event is being initiated (via JavaScript), and print only its content (via CSS #media type).
HTML Code:
<div id="dummy_content"><!-- Here goes the iframe content, which will be printed --></div>
<div id="content_wrapper">
<div id="current_content">Current Content that the user see<div>
<iframe id="myIframe" src="iframe.html"></iframe>
</div>
CSS Code:
#media screen {
#dummy_content {
display:none; /* hide dummy content when not printing */
}
}
#media print {
#dummy_content {
display:block; /* show dummy content when printing */
}
#content_wrapper {
display:none; /* hide original content when printing */
}
}
JavaScript Code:
var dummyContent = document.getElementById("dummy_content");
function beforePrint() {
var iFrame = document.getElementById("myIframe");
dummyContent.innerHTML = iFrame.contentWindow.document.body.innerHTML; // populate the dummy content (printable) with the iframe content
}
document.onkeydown = function(e) {
if (e.ctrlKey && e.keyCode == 80) {
beforePrint();
}
}
You can define a css file for printing:
#media print {
* { display: none; }
iframe { display: block; }
}
EDIT
Mybad didnt tested it.
* { display: none; } is somehow overwriting all
But this is working like a charm
http://jsfiddle.net/c4e3H/
#media print {
h1, p{ display: none; }
}
The only way i can think of is hiding all the content in the document except for the iframe and making it fit the whole document.
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style type="text/css">
body.hide *, body #backdrop
{
display: none !important;
}
body.hide #my_print_iframe, body.hide #backdrop
{
background: white;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
border: 0;
width: 100%;
height: 100%;
display: block !important;
}
#media print {
body.hide #backdrop
{
display: none !important;
}
}
</style>
<script>
$(document).on('keydown', function(e){
if (e.keyCode == 80 && ( e.metaKey || e.ctrlKey ) ) {
$("body").addClass('hide');
setTimeout(function(){
$("body").removeClass('hide');
},1000)
}
})
</script>
</head>
<body>
<div>
this is some visible text
</div>
<iframe id="my_print_iframe" src="//example.com"></iframe>
</body>
</html>
I used timeout ( nasty i know ) because at least chrome 38 does not send the keyup event after ctrl+p
Hi might be this code will help you..
function PrintElem(elem)
{
Popup($(elem).html());
}
function Popup(data)
{
var mywindow = window.open('', 'printMe', 'height=400,width=600');
mywindow.document.write('<html><head><title>Print Me</title>');
mywindow.document.write('</head><body >');
mywindow.document.write(data);
mywindow.document.write('</body></html>');
mywindow.print();
mywindow.close();
return true;
}
and call the function PrintElem('iframe') on you page.
Related
```
<div class="maindiv></div>
<div class="printablediv"></div>
function printData()
{
$('#ProductIdModal').modal('hide');
$(".maindiv").css('display','none');
$(".Printablediv").css('display','block');
$('.modal-backdrop').remove();
window.print();
}
window.addEventListener("afterprint", myFunction);
function myFunction() {
$(".maindiv").css('display','block');
$(".Printablediv").css('display','none');
}
```
I have a written a function to print a div on Ajax success named printData().
Ajax call is made from a button which is on the modal named ProductModal
The print preview I get in chrome is fine but the modal gets displayed in mozilla firefox below the div.
Print Preview in chrome :
Print Preview in mozilla :
Try using a print media query. For your case, I'm not sure if you need to apply the styles to the page or the modal.
These CSS styles are automatically applied only when printing, even through the browser. You can change the style or hide things.
/* print styles. put these at the end of your css. */
#media print {
/* some of yours, copied from the js function: */
.modal { display: none; }
.maindiv { display: none; }
.Printablediv { display: block; }
/* other. */
* { color:#333; }
html { height:auto; }
.otherThing { font-size: 20pt; }
}
Hope that works.
Currently trying to finish a Wordpress build but I've ran into a slight problem.
I'm using the following Jquery code:
jQuery( document ).ready( function ($) {
var mobile = $(window).width();
if ( mobile <= 680 ){
$( ".product_title.entry-title" ).insertBefore( ".woocommerce-product-gallery" );
}
} );
So when the screen is less than 680px the class "product_title.entry-title" will be inserted before the "woocommerce-product-gallery" class. This basically moves the title ABOVE the product gallery on my product page.
BUT it's bugging me out because this code is only triggered every time the page is refreshed. So if I load the page and resize the browser nothing will happen until I refresh it. Is there any alternative method I can use to avoid this?
Building off of #Partha Roy's comment you could use a media query like so:
.product_title.entry-title.mobile-only {
display: block;
}
.product_title.entry-title.desktop-only {
display: none;
}
#media (min-width: 680px) {
.product_title.entry-title.mobile-only {
display: none;
}
.product_title.entry-title.desktop-only {
display: block;
}
}
Or in a non mobile responsive first strategy:
.product_title.entry-title.mobile-only {
display: none;
}
.product_title.entry-title.desktop-only {
display: block;
}
#media (max-width: 680px) {
.product_title.entry-title.mobile-only {
display: block;
}
.product_title.entry-title.desktop-only {
display: none;
}
}
And of course you'll need two sets of HTML in positions where you want them.
<div class="product_title entry-title desktop-only">...</div>
<div class="product_title entry-title mobile-only">...</div>
You can refer to this similar question: How to show text only on mobile with CSS?
You can use WordPress built-in “mobile detect” function wp_is_mobile to create a simple shortcode that can hide certain parts of your content from mobile visitors and-/or desktop visitors. The wp_is_mobile function returns true when your site is viewed from a mobile browser. Using this function you can create adaptive-/responsive WordPress themes based on visitor device.
For example,
<?php if( wp_is_mobile()){ ?>
// mobile stuff goes here
<div class="product_title entry-title mobile-only"> << Mobile Text >> </div>
<?php } else { ?>
// desktop stuff goes here
<div class="product_title entry-title desktop-only"> << Desktop Text >> </div>
<?php } ?>
I have a website. When I go on it with desktops and laptops a piece of text says: Click Here.
But when it viewed on mobile I want it to say: Tap here.
Is it possible to do this without creating a new site all together for mobile?
Thanks!
It's much better you "say what the action will do" as described by one of the comments but to answer your question straight, you can do this with just css media queries:
.mobile {
display: block;
}
.desktop {
display: none;
}
#media only screen and (min-width: 768px) {
.mobile {
display: none;
}
.desktop {
display: block;
}
}
<p class= 'mobile'>Tap here</p>
<p class= 'desktop'>Click Here</p>
You can do it using js:
let newText = ""
function changeText() {
if (window.innerWidth> 0 && window.innerWidth < 700) {
newText = "Tap Here!";
} else if (window.innerWidth > 700) {
newText = "Click Here!";
}
document.getElementById("text").innerHTML = newText
}
<body onload="changeText()">
<p id="text"></p>
</body>
Basically you create a function that runs when the page is loaded, in this functions window.innerWidth return the width of the window, if it is bigger the 700 (px) than the text will be "Click here!" but if the window width is beetwen 0 and 700 the text will be "Tap here!"
Edit: i just saw that in the code snippet it doesn't work, you should try doing it on your own and it will works
in my react application I have an iframe which is loaded with HTML document and content of it exceeds 1 page. on pressing Ctrl+p I want to print it in several pages but the print preview only shows one page.
how it should be handled to recognize that the content of iframe is more than one A4 page?
the DOM in chrome devtool looks like
<div class="article-container">
<iframe style="">#document
/* hundreds of <p> tags */
</iframe>
</div>
the structure in react app is like
<div className="article-container">
<FrameText content={content} status={!this.state.editStatus} />
</div>
and the FrameText
class FrameText extends React.Component<Props> {
iframe: HTMLIFrameElement;
compinentDidMount(){
window.addEventListener('beforeprint',(e)=>{console.log(e);})
}
/* other stuff*/
render() {
const { status } = this.props;
return <iframe ref={(ref) => (this.iframe = ref!)} style={!status ? { display: 'none' } : {}} />;
}
so here when the ctrl+p is pressed I get the event and the iframe document is in the event. Also, I have the content of iframe in the local state too.
I could not find anywhere that when this event is triggered what can I do with it to manipulate or somehow tell the print preview that the content is long.
Also, the css is
#media print {
.article-container {
background-color: white;
height: 100%;
width: 100%;
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 15px;
font-size: 14px;
line-height: 18px;
}
}
Your print media query will not work on iframe inner content that is the reason iframe size is ignored while printing If you want to apply specific print styles to iframe then you have to reference from outside via appropriate method(whether js or html) I am writing a sample to reference styles to iframe there may exist other implementations for it to
let cssLink = document.createElement("link");
cssLink.href = "style.css";
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
frames['iframe1'].document.head.appendChild(cssLink);
I was able to print multiple pages in an iframe by capturing the CTRL P event, giving focus to the iframe then initiating printing on the iframe.
<iframe id="iframe" name="iframe" src="2.html"></iframe>
<script src="https://code.jquery.com/jquery.min.js"></script>
<script>
$(document).bind("keyup keydown", function (e) {
if (e.ctrlKey && e.keyCode === 80) {
window.frames["iframe"].focus();
window.frames["iframe"].print();
return false;
}
return true;
});
</script>
I am facing a problem with setting cursor position in a contentEditable div and seek some assistance.
I have already looked at several SO and other online solutions without success, including:
jquery Setting cursor position in contenteditable div, and
Set cursor position on contentEditable <div> and many other online resources.
Basically, we are using a Telerik Editor with the contentAreaMode set to DIV which forces it to use a contentEditable div instead of an iFrame. When a user clicks in the editor, we wish to be able to move the cursor to the click point so the user may enter/edit content wherever they wish in the editor. Using the example code below, I am able to set the cursor position in FF, Chrome, and IE9 to AFTER the inner div. However, in IE8 (which falls into the else if (document.selection) block), I am unable to get the cursor position to move after the div, so any typed text ends up either before or inside the div - never after. I would be GREATLY appreciative of any help.
ADDITIONAL INFO: Need this to work in IE8 standards document mode - NOT in Quirks mode (which does work).
UPDATE: Here is a jsfiddle of the issue to play with: http://jsfiddle.net/kidmeke/NcAjm/7/
<html>
<head>
<style type="text/css">
#divContent
{
border: solid 2px green;
height: 1000px;
width: 1000px;
}
</style>
<script type="text/javascript">
$(document).ready(function()
{
$("#divContent").bind('click', function()
{
GetCursorPosition();
});
$("#divContent").bind('keydown', function()
{
GetCursorPosition();
});
});
function GetCursorPosition()
{
if (window.getSelection)
{
var selObj = window.getSelection();
var selRange = selObj.getRangeAt(0);
cursorPos = findNode(selObj.anchorNode.parentNode.childNodes, selObj.anchorNode) + selObj.anchorOffset;
$('#htmlRadEdit_contentDiv').focus();
selObj.addRange(selRange);
}
else if (document.selection)
{
var range = document.selection.createRange();
var bookmark = range.getBookmark();
// FIXME the following works wrong when the document is longer than 65535 chars
cursorPos = bookmark.charCodeAt(2) - 11; // Undocumented function [3]
$('#htmlRadEdit_contentDiv').focus();
range.moveStart('textedit');
}
}
function findNode(list, node)
{
for (var i = 0; i < list.length; i++)
{
if (list[i] == node)
{
return i;
}
}
return -1;
}
</script>
</head>
<body>
<div id="divContent" contentEditable="true">
<br>
<div style="background-color:orange; width: 50%;">
testing!
</div>
</div>
</body>
</html>
Using Rangy (disclosure: I'm the author) works for me in IE 7 and 8 in the window load event. Trying to move the caret when the user clicks on an editable element is a bad idea: it conflicts with default browser behaviour hence may not work, and does not do what he user expects (which is to place the caret at or near where they clicked).
<html>
<head>
<style type="text/css">
#divContent
{
width: 1000px;
height: 1000px;
border: solid 2px green;
padding: 5px
}
</style>
<script src="http://rangy.googlecode.com/svn/trunk/currentrelease/rangy-core.js"></script>
<script type="text/javascript">
window.onload = function() {
rangy.init();
var el = document.getElementById("divContent");
el.focus();
var range = rangy.createRange();
range.setStartAfter(el.getElementsByTagName("div")[0]);
range.collapse(true);
rangy.getSelection().setSingleRange(range);
};
</script>
</head>
<body>
<div id="divContent" contentEditable="true">
<br>
<div style="background-color:orange; width: 50%;">
testing!
</div>
</div>
</body>
</html>