is there any way to capture the browser's print event and cancel the appearance of the print dialogue?
Example:
User clicks in "File" -> "Print".
Before the print dialog appears, show a confirm() like 'It is possible that not all data is printed, continue anyway? <accept> <cancel>
User clicks <accept> -> Print dialog appears
User clicks <cancel> -> Print dialog doesn't appear
Right now I have this:
var beforePrint = function(ev) {
if (!messageShown) {
var result = confirm('Are you sure?');
if (!result) {
// TODO: Cancel
}
}
};
var afterPrint = function(ev) {
// TODO
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
You don't need to cancel it. Just call window.print() if they click on accept. If they use cntrl-p or file->print that's beyond your control anyway programmatically. BTW it should be noted that you actually can't do anything to prevent the user from manually trying to print. That includes intercepting their attempt to spawn the dialog and stop it from showing. The best you can do is apply a stylesheet to printing by default and then dynamically change that print stylesheet to enable the content's visibility when they use your code to print.
Related
I have a specific problem with page printing in JavaScript. I need to open my page on another tab with all scripts removed (this way: $(document).get(0).documentElement.innerHTML.replace(/<script[^>]+>.*?<\/script>/gi, '') and then call window.print() inside new tab, and close it afterwards.
That's because errors in scripts are causing problems with printing. Code responsible for the whole printing:
var w = window.open();
w.document.write(
$(document).get(0).documentElement.innerHTML.replace(/<script[^>]+>.*?<\/script>/gi,'')
);
w.document.close();
var loadingImagesInterval = setInterval(function() {
var imgs = w.document.querySelectorAll('img');
for (var i = 0; i < imgs.length; i++) {
if (!imgs[i].complete) return;
}
clearInterval(loadingImagesInterval);
w.focus();
w.print();
w.close();
}, 100);
Basically, the problem is, on iOS, w.print() seems not to block code execution until confirm/cancel in printing view and w.close() is called immediately after. All other browsers work just fine: Mac Chrome, Mac Safari, IE11, Mac Firefox. All fine. Just not iOS Safari.
I tried this code, but didn't work as well:
w.matchMedia('print').addListener(function(mql) {
if (!mql.matches) {
w.close();
}
})
Is there a better way to deal with my problem?
EDIT: iOS version 12.2 introduced a "Done" button when opening a page from the Home Screen, so there is no need for a CLOSE button as described below. It is only needed for 12.0 and lower.
I worked around this by:
detecting Safari;
adding print and close buttons and hiding them for the print;
avoiding write() because it opens a new page, and the close button will not return the user to the previous page.
Caveat:
the popup blocker might have to be deactivated in Safari's settings to prevent the alert "This website has been blocked form automaticaly printing."
// detect Safari
if (navigator.userAgent.indexOf("Safari") !== -1) {
// make print button
const print_button = document.createElement('button');
const print_button_text = document.createTextNode("Print");
print_button.appendChild(print_button_text);
print_button.addEventListener(
"click",
function() {
// hide the buttons before printing
print_button.style.display = 'none';
close_button.style.display = 'none';
newWindow.print();
// delay reappearing of the buttons to prevent them from showing on the print
setTimeout(() => {
print_button.style.display = 'block';
close_button.style.display = 'block';
}, 2000);
},
false
);
// make close button
const close_button = document.createElement('button');
const close_button_text = document.createTextNode('Close');
close_button.appendChild(close_button_text);
close_button.addEventListener(
"click",
function() {
newWindow.close();
},
false
);
newWindow.document.body.appendChild(print_button);
newWindow.document.body.appendChild(close_button);
};
And then I added the content I wanted to print. I hope this helps.
Rewriting the question -
I am trying to make a page on which if user leave the page (either to other link/website or closing window/tab) I want to show the onbeforeunload handeler saying we have a great offer for you? and if user choose to leave the page it should do the normal propogation but if he choose to stay on the page I need him to redirect it to offer page redirection is important, no compromise. For testing lets redirect to google.com
I made a program as follows -
var stayonthis = true;
var a;
function load() {
window.onbeforeunload = function(e) {
if(stayonthis){
a = setTimeout('window.location.href="http://google.com";',100);
stayonthis = false;
return "Do you really want to leave now?";
}
else {
clearTimeout(a);
}
};
window.onunload = function(e) {
clearTimeout(a);
};
}
window.onload = load;
but the problem is that if he click on the link to yahoo.com and choose to leave the page he is not going to yahoo but to google instead :(
Help Me !! Thanks in Advance
here is the fiddle code
here how you can test because onbeforeunload does not work on iframe well
This solution works in all cases, using back browser button, setting new url in address bar or use links.
What i have found is that triggering onbeforeunload handler doesn't show the dialog attached to onbeforeunload handler.
In this case (when triggering is needed), use a confirm box to show the user message. This workaround is tested in chrome/firefox and IE (7 to 10)
http://jsfiddle.net/W3vUB/4/show
http://jsfiddle.net/W3vUB/4/
EDIT: set DEMO on codepen, apparently jsFiddle doesn't like this snippet(?!)
BTW, using bing.com due to google not allowing no more content being displayed inside iframe.
http://codepen.io/anon/pen/dYKKbZ
var a, b = false,
c = "http://bing.com";
function triggerEvent(el, type) {
if ((el[type] || false) && typeof el[type] == 'function') {
el[type](el);
}
}
$(function () {
$('a:not([href^=#])').on('click', function (e) {
e.preventDefault();
if (confirm("Do you really want to leave now?")) c = this.href;
triggerEvent(window, 'onbeforeunload');
});
});
window.onbeforeunload = function (e) {
if (b) return;
a = setTimeout(function () {
b = true;
window.location.href = c;
c = "http://bing.com";
console.log(c);
}, 500);
return "Do you really want to leave now?";
}
window.onunload = function () {
clearTimeout(a);
}
It's better to Check it local.
Check out the comments and try this: LIVE DEMO
var linkClick=false;
document.onclick = function(e)
{
linkClick = true;
var elemntTagName = e.target.tagName;
if(elemntTagName=='A')
{
e.target.getAttribute("href");
if(!confirm('Are your sure you want to leave?'))
{
window.location.href = "http://google.com";
console.log("http://google.com");
}
else
{
window.location.href = e.target.getAttribute("href");
console.log(e.target.getAttribute("href"));
}
return false;
}
}
function OnBeforeUnLoad ()
{
return "Are you sure?";
linkClick=false;
window.location.href = "http://google.com";
console.log("http://google.com");
}
And change your html code to this:
<body onbeforeunload="if(linkClick == false) {return OnBeforeUnLoad()}">
try it
</body>
After playing a while with this problem I did the following. It seems to work but it's not very reliable. The biggest issue is that the timed out function needs to bridge a large enough timespan for the browser to make a connection to the url in the link's href attribute.
jsfiddle to demonstrate. I used bing.com instead of google.com because of X-Frame-Options: SAMEORIGIN
var F = function(){}; // empty function
var offerUrl = 'http://bing.com';
var url;
var handler = function(e) {
timeout = setTimeout(function () {
console.log('location.assign');
location.assign(offerUrl);
/*
* This value makes or breaks it.
* You need enough time so the browser can make the connection to
* the clicked links href else it will still redirect to the offer url.
*/
}, 1400);
// important!
window.onbeforeunload = F;
console.info('handler');
return 'Do you wan\'t to leave now?';
};
window.onbeforeunload = handler;
Try the following, (adds a global function that checks the state all the time though).
var redirected=false;
$(window).bind('beforeunload', function(e){
if(redirected)
return;
var orgLoc=window.location.href;
$(window).bind('focus.unloadev',function(e){
if(redirected==true)
return;
$(window).unbind('focus.unloadev');
window.setTimeout(function(){
if(window.location.href!=orgLoc)
return;
console.log('redirect...');
window.location.replace('http://google.com');
},6000);
redirected=true;
});
console.log('before2');
return "okdoky2";
});
$(window).unload(function(e){console.log('unloading...');redirected=true;});
<script>
function endSession() {
// Browser or Broswer tab is closed
// Write code here
alert('Browser or Broswer tab closed');
}
</script>
<body onpagehide="endSession();">
I think you're confused about the progress of events, on before unload the page is still interacting, the return method is like a shortcut for return "confirm()", the return of the confirm however cannot be handled at all, so you can not really investigate the response of the user and decide upon it which way to go, the response is going to be immediately carried out as "yes" leave page, or "no" don't leave page...
Notice that you have already changed the source of the url to Google before you prompt user, this action, cannot be undone... unless maybe, you can setimeout to something like 5 seconds (but then if the user isn't quick enough it won't pick up his answer)
Edit: I've just made it a 5000 time lapse and it always goes to Yahoo! Never picks up the google change at all.
I want that when a user clicks on any external link (identified by either particular id or class) on my site then he should get a popup with a counter of 10 seconds, after 10 seconds the popup should close and the user should be able to access the external URL. How can this be done? I'm able to show a warning like below but I don't know how to add timeout to it, also this is a confirm box, not a popup where I can add some div and more stuff for user to see until the counter stops.
$(document).ready(function(){
var root = new RegExp(location.host);
$('a').each(function(){
if(root.test($(this).attr('href'))){
$(this).addClass('local');
}
else{
// a link that does not contain the current host
var url = $(this).attr('href');
if(url.length > 1)
{
$(this).addClass('external');
}
}
});
$('a.external').live('click', function(e){
e.preventDefault();
var answer = confirm("You are about to leave the website and view the content of an external website. We cannot be held responsible for the content of external websites.");
if (answer){
window.location = $(this).attr('href');
}
});
});
PS: Is there any free plugin for this?
I've put together a little demo to help you out. First thing to be aware of is your going to need to make use of the setTimeout function in JavaScript. Secondly, the confirmation boxes and alert windows will not give you the flexibility you need. So here's my HTML first I show a simple link and then created a popup div that will be hidden from the users view.
<a href='http://www.google.com'>Google</a>
<div id='popUp' style='display:none; border:1px solid black;'>
<span>You will be redirected in</span>
<span class='counter'>10</span>
<span>Seconds</span>
<button class='cancel'>Cancel</button>
</div>
Next I created an object that controls how the popup is displayed, and related events are handled within your popup. This mostly is done to keep my popup code in one place and all events centrally located within the object.
$('a').live('click', function(e){
e.preventDefault();
popUp.start(this);
});
$('.cancel').click(function()
{
popUp.cancel();
});
var popUp = (function()
{
var count = 10; //number of seconds to pause
var cancelled = false;
var start = function(caller)
{
$('#popUp').show();
timer(caller);
};
var timer = function(caller)
{
if(cancelled != true)
{
if(count == 0)
{
finished(caller);
}
else
{
count--;
$('.counter').html(count);
setTimeout(function()
{
timer(caller);
}, 1000);
}
}
};
var cancel = function()
{
cancelled = true;
$('#popUp').hide();
}
var finished = function(caller)
{
alert('Open window to ' + caller.href);
};
return {
start : start,
cancel: cancel
};
}());
If you run, you will see the popup is displayed and the countdown is properly counting down. There's still some tweaks of course that it needs, but you should be able to see the overall idea of whats being accomplished. Hope it helps!
JS Fiddle Sample: http://jsfiddle.net/u39cV/
You cannot using a confirm native dialog box as this kind of dialog, as alert(), is blocking all script execution. You have to use a cutomized dialog box non-blocking.
You can use for example: jquery UI dialog
Even this has modal option, this is not UI blocking.
Consdier using the javascript setTimeout function to execute an action after a given delay
if (answer){
setTimeOut(function(){
//action executed after the delay
window.location = $(this).attr('href');
}, 10000); //delay in ms
}
I have a jsp file which calls another jsp file opening it as a showmodal dialog window.
Say file1.jsp calls file2.jsp through file1.js.
File1.jsp-->File1.js (respective js files)
File2.jsp-->File2.js(respective js files)
Now to handleonclose in File2.jsp I added a function in File2.js.
When I hit close window but choose option as cancel, instead of just showing the old window.
It shows a modal window ontop of the existing modal window. Why is this happening. Am I missing something obvious.
What i expect to happen: When I choose Close but click cancel, nothing should happen.
File2.js function:
function handleOnClose() {
var resultsDoc = document.frames('searchBuffer').document;
if (event.clientY < 0) {
var bool = confirm('Are you sure you want to close the window ?');
if (!bool) { //Issue occurs here
window.showModalDialog("File2.jsp", "", "dialogWidth:1000px;dialogHeight:650px");
}
else {
resultsDoc.all('searchResults').innerText = '';
document.someSearch.submit();
}
}
window.returnValue = 'Discard';
}
Modified File2.js function:
function handleOnClose() {
var resultsDoc = document.frames('searchBuffer').document;
if (event.clientY < 0) {
var bool = confirm('Are you sure you want to close the window ?');
if (!bool) { //Issue occurs here
//*******removed the showmodal dialog window call
window.returnValue = 'Sorry';
}
else {
resultsDoc.all('searchResults').innerText = '';
document.someSearch.submit();
window.returnValue = 'Discard';
}
}
}
On the calling js (file1.js) I check if return value is "Discard" if so I refresh the page.
Otherwise I call the showmodal window again. My result is stored in the buffer so retrieval isn't a problem. Works like a charm
I have a site, now what I want is when user switch to some external site, then an Ad should be popped up, and also when user close the browser window, the Ad should get popup, I have used onunload, but it shows the message on clicking every link, and also I used on beforeunload, it does almost everything, but it do the same as onunload...
Please anyone have some idea how should I achieve this?
This doesn't prevent popup appearing on page refresh, but does this job as requested:
<script>
var isLinkClicked = false;
// Either plain JS solution:
var links = document.getElementsByTagName('a');
var l=links.length;
while (l--) {
links[l].addEventListener("click", function() {
isLinkClicked = true;
}, false);
}
// Or jQuery solution:
$("a").live("click", function() {
isLinkClicked = true;
});
// And then Unload event listener:
window.addEventListener("unload", function(evt) {
if (isLinkClicked) {
isLinkClicked = false;
return false;
}
// here comes the rest of the code
}, false);
</script>