Javascript/jQuery Popup Loop and Add - javascript

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.

Related

In Rails, onbeforeunload not working consistently for Chrome browser

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.

how to run a jQuery function after certain element is displayed

I have a modal that is displayed only once (like a dialog box) after user logged-in firstly. And also I've got a function in that modal file that is supposed to run if modal is displayed.
Here is function:
$('#some_element').(function someFunc() {
console.log("gUM is used now");
//some stuff to do
});
I tried on('click') and it works fine. But I don't need it.
Also, I tried on('load'), but it works before modal is displayed.
Any help will be appreciated. Thanks in advance.
Hello i think you can use events. for example for jquery dialog there is many events and function to know if dialod is open http://api.jqueryui.com/dialog/#method-isOpen and some events like open or beforeClose or you can use jquery to detect if the element is visible $("#SomeElement").is(":visible")
Not an ideal solution but you could start a timer in on load, and have it run a function every half second to check if the modal is visible:
var checkModalTimer;
$(document).ready(function() {
checkModalTimer = setInterval(function() {
if ($('modal').is(':visible')) {
// do your function
clearInterval(checkModalTimer);
}
}, 500);
});

Save before unload

I'm having an application with an interactive canvas and want to save changes on it, before the user exits the page.
My approach
function saveBeforeUnload(){
if (confirm('Do you want to save the current state to clipboard?')) {
/*yes*/ if (canvas.getObjects("rect").length > 0){
localStorage.setItem("clipboard_unfinishedconfig", JSON.stringify(canvas.toJSON(customProperties)));
return;
/*no:*/ } else {
localStorage.setItem("clipboard_unfinishedconfig", "");
return;
}
}
I call it by
window.onbeforeunload = saveBeforeUnload;
What I need to accomplish is a yes/no confirmation, if the user wants to ovverride the localStorage Item with the current configuration.
Problem
With my code, the confirm does not appear. Accordingly the localStorage is empty...
console says "Blocked confirm..."
Approach - I
Explanation:
window.onbeforeload executes whatever is in the handler but it really cares about the return statement which shall be used as confirmation message. And Ofcourse we can't change the button labels. Once the onbeforeunload dialog is shown it blocks everything(that's why your prompt is blocked). So in the following code what we are doing is that we are scheduling a save using a setTimeout by giving 0 milliseconds, so that it is added to the event loop.
Now if the user decides to close the tab anyway that setTimeout handler never runs. If they choose to stay, the handler runs & the changes are saved.
Well, you can do the following:
function saveChanges () {
localStorage.setItem("clipboard_unfinishedconfig", JSON.stringify(canvas.toJSON(customProperties)));
alert("changes saved successfully !");
window.onbeforeunload = null;
}
function exitConfirmation () {
setTimeout( saveChanges, 0 );
return "There are unsaved changes on this canvas, all your changes will be lost if you exit !";
}
window.onbeforeunload = exitConfirmation(); //Basically set this whenever user makes any changes to the canvas. once the changes are saved window.onbeforeunload is set back to null.
So, If the user chooses to stay back, the changes will be saved,
This is a working solution, but not the best user experience in my opinion, so what I suggest is that you keep auto saving the changes as the user makes & give a button to reset the canvas if required. Also you should not save on every single change, but instead keep auto saving in a specific interval of time. If the user tries to close between that interval then show this dialog saying "you have pending changes left".
Approach - II ( Your way )
function saveConfirmation () {
if (confirm('Do you want to save the current state to clipboard?')) {
if (canvas.getObjects("rect").length > 0){
localStorage.setItem("clipboard_unfinishedconfig", JSON.stringify(canvas.toJSON(customProperties)));
} else {
localStorage.setItem("clipboard_unfinishedconfig", "");
return;
}
}
}
function saveBeforeUnload(){
setTimeout( saveConfirmation, 0 );
return "You have unsaved changes";
}
window.onbeforeunload = saveBeforeUnload;
But this will be to many nagging dialogs.
Hope this helps.

How to reset jquery dialog timeout for next dialog?

I have an add-to-bag button used throughout our site and we want a dynamic popup to appear to acknowledge what was just added, and then it goes away. I'm finding that if you click another add button, it has the previous dialog's timeout attached. To fix this so the next dialog has its own 10,000 setTimeout rather than whatever is left over from the last one I have come up with the following code (that doesn't do the trick).
$(document).ready(function ()
{
// Create object for future dialog box - so it's available to the close method
var addToBagDialogVar = $('<div id="addToBagDialogBox"></div>');
var autoCloseTimeout = 10000;
var dialogTimer;
$(".addToBagPU").click(function (e)
{
var result = "";
$.get(this.href, function (data) { SetData(addToBagDialogVar, data); });
return false;
});
// Start listening for the close link click
$(document).on("click", "#bagPUCloseLink", function (event)
{
event.preventDefault();
CloseDialog(addToBagDialogVar);
});
function SetData(addToBagDialogVar, data)
{
result = data;
var regex = data.match("{{(.*)}}");
var bagCount = regex[1];
addToBagDialogVar.html(result).dialog({
open: function ()
{
clearTimeout(dialogTimer);
$(".ui-dialog-titlebar-close").hide();
SetBagCount(bagCount),
dialogTimer = setTimeout(function () { CloseDialog(addToBagDialogVar); }, autoCloseTimeout);
},
show: { effect: "fadeIn", duration: 800 },
close: function () { clearTimeout(dialogTimer); },
width: 320
});
}
function CloseDialog(closeThisDialog)
{
closeThisDialog.dialog("close");
closeThisDialog.dialog("destroy").remove();
}
});
The dialog is loaded with dynamic content from an external .Net page with product data and has a close link inside that page, which is why the dialog is loaded into addToBagDialogVar so it's available to CloseDialog.
All of that works just fine. It's just the reset of the timer that doesn't appear to be happening. If I go down a page of products and add each one to my bag, the 3rd or 4th dialog is only up for a second or so because they have all been using the first dialogs setTimeout.
I've read and read and tried too many different ways to remember and now my brain is mush.
I propose an alternate explanation for the behavior you're observing. When you click the first "add to cart", a timer is started. As you go down the page clicking "add to cart", a new timer is started each time. There's no overlap, just a bunch of separate timers running normally (although incidentally, each new dialog box blows away the timer ID you've previously created; I'll come back to this).
When your first dialog's timer expires, the dialog closes itself via the HTML ID, meaning it closes itself with something like a jquery $('div#addToBagDialogBox').closeOrSomethingLikeThat(), that is, every dialog inside a div with an id of addToBagDialogBox. The first timer expiration is closing all of your dialogs, because they all use that same HTML ID. The other timers are running perfectly, but when they expire there's nothing left for them to do.
You can fix the early-close problem by assigning a unique HTML ID to each dialog you create. And you'll want to manage your timer IDs on a per-dialog basis as well, such that each dialog has its own timer ID.
Edit: Just for nerdy grins, think about the details of the scenario you described. Your first timer is running, counting down normally, and you start four other timers while the first dialog is still there. The ID of the fifth timer is in your variable dialogTimer. So when the first dialog's timer expires, the close processing occurs, and you call clearTimeout with the ID of the fifth dialog's timer. So your first dialog's timer expired, the dialog closed all the other dialogs, and the cleanup cancelled the fifth timer. There are three other timers still running, their IDs lost forever. They finally expire and their shutdown functions run, but they're totally without effect, their companion dialogs long gone. Sorry, bona fide nerd here.

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

Categories

Resources