In Rails, onbeforeunload not working consistently for Chrome browser - javascript

I'm trying to get onbeforeunload to work consistently on my page that has a form users are filling out. I'm expecting the following:
When I click a link to another page, it would prompt the user
When I refresh the page, it would prompt the user
I'm currently testing under Google Chrome, and I'm using the following now - though I've tried some variations.
<script>
$(document).on('ready page:load', function () {
$(window).on('beforeunload', function() {
return "You should keep this page open.";
});
});
</script>
I've been able to get the prompt to show up at times but not consistently. I've thought this might point to a conflict with the code above and turbolinks. But haven't been able to find out a fix to get the expected results mentioned above.
--- Update:
Here's the code I eventually used.
<script data-turbolinks-eval="false">
$(document).ready(function() {
form_modified=0;
$('#report-form *').change(function(){
form_modified=1;
});
$("#report-form input[name='commit']").click(function() {
form_modified = 0;
});
});
$(document).on('page:before-change', function() {
if ($("#report-form").length > 0) {
if (form_modified==1) {
if (confirm("There are unsaved changes, click \"Cancel\" to remain on the page.")) {
// clicks "OK", nothing here means
} else {
// clicks "Cancel"
event.preventDefault();
}
}
}
});
</script>
This method doesn't work for page refresh or exiting out by the window "X" however...

Turbolinks offers the page:before-change event for this kind of scenario.
I'm however not sure why you bind your 2nd handler in your first handler. The window object doesn't change when you click on a Turbolinks link.

Related

jQuery working only upon reload

On this WordPress site, I use a site-wide script to add information to outgoing links.
However, it only works if the page is reloaded or the user navigates to any second page.
Assuming it was a jQuery loading time issue, I added a timer to wait for it, but it doesn't make any difference: the message "jQuery loaded!" appears but the click function seems not to be working.
When the page is reloaded, the click function works as expected.
Here is the code:
var jQloaded = setInterval(function() {
if (window.jQuery) {
console.log("jQuery Loaded!");
clearInterval(jQloaded);
jQuery(document).on('click', 'a[href*="/external/"]', (function(e) {
e.preventDefault();
alert('ok');
}));
}
}, 50);
I tried everything I could think of without success. Can you tell me what's wrong?
PS: to replicate the behavior it's necessary to open a fresh incognito/private window. Emptying the cache + hard reload isn't enough.
Try wrapping your code within the document.ready method
$(document).ready(function() {
// code here
});

Prevent back button from going back to previous page for an ID

Using the following function to prevent users from going back to previous page if the page they are on currently has the id #home. But this function doesn't even fire off. No alerts. Nothing wrong with the link to script file as I have other scripts running fine on that file.
document.addEventListener("backbutton", function (e) {
alert("Back button pressed");
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
var activePageId = activePage[0].id;
alert(activePageId);
if (activePageId == 'home') {
e.preventDefault();
}
}, false);
Unless you have created a custom event there is no onbackbutton event I know of. You are after onbeforeunload
Clients don't like it when you block navigation. You should consider other solutions to you problem rather than block navigation. Sure as .... the next thing the client will do is close the tab and a good chance you will never see a session with that client again.

Javascript/jQuery Popup Loop and Add

Firstly, I am quite new to programming, so please be gentle. Stack Overflow has been a wonderful resource for me, so thankyou to all of you contributors.
This one I cannot crack though, and it's a difficult search item, as you can probably tell by the cryptic title...
Anyway, I have a jQuery popup function which gets called from a events.register control. Essentially whenever a user clicks in the map it sends a request to a web service, gets the data back, populates a form which the user can then interact with and save data back to SQL.
It works really well I am happy with its progress.
One of the functions is to change the value in a table, I want the user to get a prompt to ensure they don't accidentally save something they don't intend. It works perfectly the first time after a refresh, but then each time after that it adds one confirm, then again, until eventually after the fifth time there are 5 confirms that appear one after the other. Once the user clicks through them the code runs fine and I get expected results.
I only call the confirm once (I think?) but, yeah, I am lost, here is my function, sorry if it is hard to read or poorly formatted:
function popup() {
j = jQuery.noConflict();
j(document).ready(function() {
//open popup
j("#detailsform").height(250);
j("#detailsform").fadeIn(1000);
positionPopup();
document.getElementById("condition").value = getCondition;
j("#selCatHead").hide();
j("#cats").hide();
//dispose tree
j("#dispose").click(function() {
if (confirm("Are you sure?")) {
disposetree();
}
else { return false; };
});
//save defect
j("#savedef").click(function() {
saveDef();
});
//fade in defects
j("#adddefect").click(function() {
j("#detailsform").height(400);
j("#selCatHead").fadeIn(1000);
j("#cats").fadeIn(1000);
});
//fade out popup
j("#close").click(function() {
j("#detailsform").fadeOut(500);
});
}); // close document ready function
//position the popup at the center of the page
function positionPopup() {
if (!j("#detailsform").is(':visible')) {
return;
}
j("#detailsform").css({
left: (j(window).width() - j('#detailsform').width()) / 2,
top: (j(window).width() - j('#detailsform').width()) / 7,
position: 'absolute'
});
} // close positionPopup function
//maintain the popup at center of the page when browser resized
j(window).bind('resize', positionPopup);
}; // close popup function
EDIT: Thanks to #jfriend00, removed function from popup call and turned off handler each time, eg:
function popup() {
j = jQuery.noConflict();
j(document).ready(function() {
//open popup
j("#detailsform").height(250);
j("#detailsform").fadeIn(1000);
//dispose
j("#dispose").off();
j("#dispose").click(function() {
disposeClickHandle();
});
//save
j("#savedef").off();
j("#savedef").click(function() {
saveDef();
});
});
and then:
function disposeClickHandle() {
if (confirm("Are you sure?")) {
disposetree();
}
else { return false; };
};
You should only install a click handler ONCE. If you install it multiple times, it will trigger multiple times.
So, everytime you call your popup() function it installs yet another click handler. And, then when you click, the click handler will trigger multiple times. You should either move your click handler installation outside the function that you call multiple times and put it in an initialization function that is only called once at the beginning OR you can remove the click handlers after your operation so when you install it again, it will only be installed one time.

How to capture when a user is leaving ASP.Net page unexpectedly

I need to prompt a user when they are leaving my ASP.Net page unexpectedly with a message to ask if they are sure they want to leave. A post back or when the save button is clicked should not fire the warning. There are a bunch of articles covering this but I am brand new to this and appear to have got my wires crossed.
The recommended way appears to be to use the window.onbeforeunload event but behaves unexpectedly for me. This is fired when the page loads as opposed to when the page unloads.
<script language="JavaScript" type="text/javascript">
window.onbeforeunload = confirmExit;
function confirmExit() {
return "You have attempted to leave this page. If you have made any changes to the fields without clicking the Save button, your changes will be lost. Are you sure you want to exit this page?";
}
</script>
If I use the JQuery implementation it fires when the page unloads but the problem is it fires before the code behind is executed. So I cannot set a variable on the client saying don’t fire the event this time as it is a post back or a Save.
$(window).bind('beforeunload', function () {
return 'Are you sure you want to leave?';
});
Can anyone point me in the correct direction as I know I am making basic mistakes/miss-understanding?
Edit:
So I am nearly there:
var prompt = true;
$('a').live('click', function () {
//if click does not require a prompt set to false
prompt = false;
});
$(window).bind("beforeunload", function () {
if (prompt) {
//reset our prompt variable
prompt = false;
//prompt
return true;
}
})
Except the problem is in the above code I need to be able to differentiate between the clicks but I haven't been able to figure that out yet i.e. I am missing a condition here "//if click does not require a prompt set to false".
Any ideas?
Thanks,
Michael
You can try using this:
$(window).unload(function(){
alert('Message');
});
In case people are interested this is the roundabout solution to my problem. How to tell if a page unload in ASP is a PostBack

'onbeforeunload' Fires Twice

I want to send an ajax request when a user leaves a page or closes the window.
Here is my code inside :
<script type="text/javascript">
function sendajax(){
$.ajax({
url: "someurl",
data: mydata,
async : false
});
}
</script>
<script type="text/javascript">
window.onbeforeunload=function(){sendajax();};
</script>
When the event occurs the event fires twice.
Why does in happen?
I know I can prevent it by adding a variable var ajaxSent=true; but may be there is a cleaner way to do it?
UPD:
I replaced the sendajax function content with some other code (without sending ajax) and found out that ajax is not the one causing the problem. It still enters the function twice.
Based on the code in your edit and comments, it looks like it could simply be caused by the broken link you are clicking to leave the page.
Given the following code:
<script>
function doSomething() { console.log('onbeforeunload fired'); }
window.onbeforeunload = doSomething;
</script>
link A
link B
If I click on link A, I get two console log entries, if I click on link B I only get one.
It looks like it could be a quirk of how the browsers handle their internal "This web page has not been found" pages, causing your page to be refreshed and closed again before showing the message, leaving you with two occurrences of the onbeforeunload event.
I had the same problem and it took a while to understand and resolve, sharing the case details:
There was a custom JS within our template that manipulated the menu.
It caused the unload to fire twice, only when clicking on the menu links, not on other links, and only in IE/EDGE.
We eventually stopped the propagation on these links and the problem was resolved.
$('.SELECTOR a[href^="http://"]').on('click', function(e){
e.stopPropagation();
});
It's a specific bug in your application, therefore you won't find too much information on google.
You could try the following code:
<script type="text/javascript"><br>
window.onbeforeunload=function sendajax(){<br>
$.ajax({<br>
url: "someurl",<br>
data: mydata,<br>
async : false<br>
});<br>
};<br>
</script>
or you can define sendajax() {} at some place and the use it like onbeforeunload = "sendajax()" not as onbeforeunload = "function () { sendajax() }"
beforeUnload is cancellable
I know this post is quite old but from the Chrome Pagelifecycle API documentation, browsers can occasionally partially unload pages to save resources. https://developers.google.com/web/updates/2018/07/page-lifecycle-api beforeUnload is not reliable to make sure that the page is closed. This especially happens on android devices when the screen is locked.
There is a jsfiddle that I found somebody wrote that you can test out https://jsfiddle.net/ov6b9pdL/. Keep the screen locked for 5-10 minutes on Chrome android and you'll see that beforeUnload is fired without even closing the tab.
$(document).ready(function() {
window.addEventListener('beforeunload', showLoader);
});
var showLoader = function() {
$('#loader').show();
};
Agree with AlonMichaeli's concept.
In my application there was anchor tag wrapped with in a div together with couple of spans. When Anchor was clicked on a dirty page, there was couple of 'Leave site' notifications.
It worked fine if any other part of menuItem (div or spans) are clicked.
So in custom javascript method I've added stopped propagation and preventDefault only if anchor tag is clicked. Somehow in this case preventDefault is necessary.
function menuItemClicked(event: JQueryEventObject) {
var item = $(event.target);
if (item.is(".anchor-item")) {
event.stopPropagation();
event.preventDefault();
}
href = item.closest(".anchor-item").attr("href");
if (!event.ctrlKey && href) {
window.location.href = href;
}
}

Categories

Resources