Custom Confirmation dialog doesn't work properly - javascript

I have created custom dialogs like Alert and ConfirmDialog with Bootstrap and Jquery.
Here is sample : http://jsfiddle.net/eb71eaya/
Problem - in the callback I make an ajax call, and if it returns true - I show an alert with status success else - error. But this alert doesn't show while request makes delete. (In the example I don't make an ajax request, just show alert, but that also doesn't work.)
function getEsrbAlertDialog(title, msg, callBack, obj) {
var esrbAlertDialog = $('#esrb-dialog');
if (esrbAlertDialog.length == 0) {
esrbAlertDialog = getEsrbDialog(title, msg);
} else {
$('.modal-title', esrbAlertDialog).html(title);
$('.modal-body', esrbAlertDialog).html(msg);
}
$('.modal-footer div', esrbAlertDialog).empty();
$('.modal-footer div', esrbAlertDialog).append('<button class="btn btn-primary pull-right close-btn">Close</button>');
$('.close-btn', esrbAlertDialog).unbind('click').click(function () {
if (typeof callBack === "function") {
todo = callBack(obj);
}
esrbAlertDialog.modal('hide');
});
return esrbAlertDialog;
};
I want to execute callback when confirmation dialog become closed.
UPDATE : I understand logic like this : When user click on "Ok"-button, dialog must be closed. And when it is already closed then fire event 'hidden.bs.modal' which must execute callBack. But CallBack executes before confirm dialog finish hiding.

This line:
esrbConfirmationDialog.modal('hide');
Is hiding the second dialog.
EDIT:
Both dialogs use the same div as there reference:
var esrbAlertDialog = $('#esrb-dialog');
Create seperate dialogs one for the alert and one for confirmation.

Just replace this.Alert function to below code, i.e. just add e.preventDefault();
this.Alert = function (dialogMsg, callBack, obj) {
var dlg = getEsrbAlertDialog('Alert', dialogMsg, callBack, obj);
e.preventDefault();
dlg.modal('show');
};

Related

ajax call causing fits with hiding a modal

EDIT: Found an un-elegant solution here:
How do I close a modal window after AJAX success
using location.reload(), though I have to say that I think there is a bug in the modal handling in jquery. I do not think my code below was wrong yet it doesn't work. :(
When a user clicks a button it calls a method :
onClick(GroupInformationDialog(true)) ... etc
So that calls a method to see if we should hide or open a modal first based on what is passed and second based on what the result of another method that does an ajax call has:
function GroupInformationDialog(open) {
if (open) {
if (GetProviderInfo() == true) {
$("#groupinfo-dialog").modal("show");
} else {
// we got no real data so let's not show the modal at all
$("#groupinfo-dialog").modal("hide");
}
} else {
$("groupinfo-dialog").modal("hide");
}
return false;
}
and the ajax call:
function GetProviderInfo() {
event.preventDefault();
gid = $('#group_info option:selected').val()
pid = $("#provider_id").val()
$.ajax({
url: '{% url 'ipaswdb: get_group_info_data' %}',
data: "group_id=" + gid + "&prov_id=" + pid,
success: function (resp) {
if (resp['response'] == 'NOGROUP') {
alert("You must first select a group");
$("groupinfo-dialog").modal('hide'); //arg this doesn't work either
return false;
}
else if (resp['response'] == 'OK') {
//fill out form with data.
$("#gi_date_joined_group").val(resp['date_joined_group']);// = resp['credentialing_contact'];
$("#gi_provider_contact").val(resp['provider_contact']);
$("#gi_credentialing_contact").val(resp['credentialing_contact']);
return true;
}
else {
$("#gi_date_joined_group").val('');// = resp['credentialing_contact'];
$("#gi_provider_contact").val('');
$("#gi_credentialing_contact").val('');
return true;
}
}
});
}
The problem is, the return true, or false in GetProviderInfo() is ignored, it is like GroupInformationDialog is evaluated all the way before GetProviderInfo is, so the result is a modal dialog that always pops up.
I even tried to have the
$("#groupinfo-dialog").modal('hide');
in the if(resp['response']=='NOGROUP') code section, with no dice.
It is almost like I need a wait function, I thought success was a call back function was going to take care of it, but alas it did not.
You're mixing synchronous and async code here; you can't synchronously use if (GetProviderInfo() == true) since what you want to return from that function depends on an asynchronous ajax call.
The return statements you currenty have will go to the success handler they're contained within; they will not set the return value for getProviderInfo itself. By the time that success handler runs, getProviderInfo has already returned.
You could have that function return a promise (using return $.ajax({...})) and have the caller handle the results asynchronously -- but it looks like in this case it might be simpler to just hide / show the modal from within the ajax call's success handler. (It looks like the sole reason that isn't working currently is just a typo: there are a couple spots where you have $("groupinfo-dialog") when you mean $("#groupinfo-dialog")

JavaScript Callback being kept in memory and excuted with new callback

I'm working on a CMS type project using ajax. My problem occurs with the notify.js javascript library located here https://notifyjs.com/.
With my local copy I realized that I can create confirm buttons sleekly designed without using Javascript's built in alert() or confirm() methods and make it look like this:
.
Seeing that the source code provided no way to explicitly add callbacks from outside the library I modified it to my will, where the "callback" parameter is my custom parameter
I.E.
//confirmation notification
Notification.prototype.confirm = function (style, position, title, text, callback) {
var icon = "fa fa-adjust";
if (style == "error") {
icon = "fa fa-exclamation";
} else if (style == "warning") {
icon = "fa fa-warning";
} else if (style == "success") {
icon = "fa fa-check";
} else if (style == "info") {
icon = "fa fa-question";
} else {
icon = "fa fa-adjust";
}
$.notify({
title: title,
text : text + '<div class="clearfix"></div><br><a id="yesConfirmBtn" class="btn btn-sm btn-default yes">Yes</a><a id="noConfirmBtn" class="btn btn-sm btn-danger no">No</a>',
image: "<i class='" + icon + "'></i>"
}, {
style : 'metro',
className : style,
globalPosition: position,
showAnimation : "show",
showDuration : 0,
hideDuration : 0,
autoHide : false,
clickToHide : false
});
//listen for click events from this style
$(document).on('click', '.notifyjs-metro-base .no', function () {
// turn off event listener on yes click
$(document).off("click", '.notifyjs-metro-base .yes');
//programmatically trigger propogating hide event
$(this).trigger('notify-hide');
});
var yesClick = function () {
//callback when user clicks
callback();
// callback is assigned empty closure because on
// the next confirm request this callback and
// the new one will be called
callback = function(){
};
//hide notification
$(this).trigger('notify-hide');
};
$(document).on('click', '.notifyjs-metro-base .yes', yesClick);
}
In the click listeners my problem occurs the yesClick listener mainly as it continue to add the callbacks one on top the other so each time a callback is created and triggered the old one is triggered then the rest till the newest callback.
To by pass this problem I made the callback point to a empty anonymous function so when the old one's are executed it wouldn't do anything but this way still doesn't solve my problem as the callbacks will still be in memory.
The callback passed in performs an Ajax request to delete a row in the database.
This is what the callback looks like
var self = this;
// triggers notify.js confirmDelete() method passing in the
// body, title, and callback
this.notif.confirmDelete("Are you sure?", "Delete this Item?", function () {
// creates a notification to show user their
// transaction is being processed
self.notif.info("Deleting");
// callback for if the ajax request was successful
var successCB = function (text) {
if (text.indexOf("true") !== -1) {
self.notif.success("Item has been deleted", "Successfully Deleted");
var form = new Validate(),
table = new Table();
form.resetForm();
table.removeRow(data.id);
} else {
self.notif.error("Could not be deleted...");
}
// callback if ajax request failed
}, failCB = function () {
// this key word refer's to a method called
//Success which is the same as successCB as they
//are placed in the same object literal
this.Success("false");
};
self.ajaxRequest(successCB, failCB, data);
});
self.ajaxRequest looks like this (this is a custom ajax library I made if it seems strange)
var self = this;
var dataToProcess = data || {};
// basic set up for ajax request
Ajaxify({
host : self.hostName + "Backend/manage/" + self.processFile,
data : [dataToProcess],
responseType: "text",
method : "POST",
execute : true,// executes request right away
Success : successCallback,
Failure : failureCallback
});
What am I doing wrong?
How can I solve this?
What is the cause of it?
(Note: if any further info is needed let me know)
You need to remove click events with off, because you're adding global click with on
function noClick() {
//programmatically trigger propogating hide event
$(this).trigger('notify-hide');
removeEvents();
}
function removeEvents() {
$(document).off('click', '.notifyjs-metro-base .no', noClick);
$(document).off('click', '.notifyjs-metro-base .yes', yesClick);
}
$(document).on('click', '.notifyjs-metro-base .no', no);
function yesClick () {
//callback when user clicks
callback();
//hide notification
$(this).trigger('notify-hide');
removeEvents();
};
$(document).on('click', '.notifyjs-metro-base .yes', yesClick);

re-execute javascript after log-in

I have a series of buttons that execute different functions when clicked. The function checks whether the user is logged in, and if so proceeds, if not it displays an overlay with ability to log in/create account.
What I want to do is re-execute the button click after log-in, without the user having to reclick it.
I have it working at the moment, but I'm pretty sure that what I'm doing isn't best practice, so looking for advice on how I can improve...
Here's what I'm doing: setting a global variable "pending_request" that stores the function to be re-run and in the success part of the log-in ajax request calling "eval(pending_request)"
Example of one of the buttons:
jQuery('#maybe_button').click(function() {
pending_request = "jQuery('#maybe_button').click()"
var loggedin = get_login_status();
if (loggedin == true) {
rec_status("maybe");
}
});
.
success: function(data) {
if(data === "User not found"){
alert("Email or Password incorrect, please try again");
}else{
document.getElementById('loginscreen').style.display = 'none';
document.getElementById('locationover').style.display = 'none';
eval(pending_request);
pending_request = "";
}
}
Register a function to handle the click and then invoke that func directly without eval().
jQuery('#maybe_button').on('click', myFunction)
This executes myFunction when the button is clicked. Now you can "re-run" the function code every time you need it with myFunction().
And btw since you are using jQuery you can do $('#loginscreen').hide() where $ is an alias for jQuery that's auto defined.
EDIT
Please, take a look at the following code:
var pressedButton = null;
$('button1').on('click', function() {
if (!isLoggedIn()) {
pressedButton = $(this);
return;
}
// ...
});
And, in your success handler:
success: function() {
// ...
if (pressedButton) pressedButton.trigger('click');
// ...
}

jquery beforeunload when closing (not leaving) the page?

How can I display "Are you sure you want to leave the page?" when the user actually tries to close the page (click the X button on the browser window or tab) not when he tries to navigate away from the page (click on another link).
My client wants a message to appear when the user tries to close the page "Are you sure you want to leave the page? You still have items in your shopping cart."
Unfortunately $(window).bind('beforeunload') doesn't fire only when the user closes the page.
jQuery:
function checkCart() {
$.ajax({
url : 'index.php?route=module/cart/check',
type : 'POST',
dataType : 'json',
success : function (result) {
if (result) {
$(window).bind('beforeunload', function(){
return 'leave?';
});
}
}
})
}
You can do this by using JQuery.
For example ,
click here
Your JQuery will be,
$(document).ready(function(){
$('a').on('mousedown', stopNavigate);
$('a').on('mouseleave', function () {
$(window).on('beforeunload', function(){
return 'Are you sure you want to leave?';
});
});
});
function stopNavigate(){
$(window).off('beforeunload');
}
And to get the Leave message alert will be,
$(window).on('beforeunload', function(){
return 'Are you sure you want to leave?';
});
$(window).on('unload', function(){
logout();
});
This solution works in all browsers and I have tested it.
Try javascript into your Ajax
window.onbeforeunload = function(){
return 'Are you sure you want to leave?';
};
Reference link
Example 2:
document.getElementsByClassName('eStore_buy_now_button')[0].onclick = function(){
window.btn_clicked = true;
};
window.onbeforeunload = function(){
if(!window.btn_clicked){
return 'You must click "Buy Now" to make payment and finish your order. If you leave now your order will be canceled.';
}
};
Here it will alert the user every time he leaves the page, until he clicks on the button.
DEMO: http://jsfiddle.net/DerekL/GSWbB/show/
Credit should go here:
how to detect if a link was clicked when window.onbeforeunload is triggered?
Basically, the solution adds a listener to detect if a link or window caused the unload event to fire.
var link_was_clicked = false;
document.addEventListener("click", function(e) {
if (e.target.nodeName.toLowerCase() === 'a') {
link_was_clicked = true;
}
}, true);
window.onbeforeunload = function(e) {
if(link_was_clicked) {
return;
}
return confirm('Are you sure?');
}
As indicated here https://stackoverflow.com/a/1632004/330867, you can implement it by "filtering" what is originating the exit of this page.
As mentionned in the comments, here's a new version of the code in the other question, which also include the ajax request you make in your question :
var canExit = true;
// For every function that will call an ajax query, you need to set the var "canExit" to false, then set it to false once the ajax is finished.
function checkCart() {
canExit = false;
$.ajax({
url : 'index.php?route=module/cart/check',
type : 'POST',
dataType : 'json',
success : function (result) {
if (result) {
canExit = true;
}
}
})
}
$(document).on('click', 'a', function() {canExit = true;}); // can exit if it's a link
$(window).on('beforeunload', function() {
if (canExit) return null; // null will allow exit without a question
// Else, just return the message you want to display
return "Do you really want to close?";
});
Important: You shouldn't have a global variable defined (here canExit), this is here for simpler version.
Note that you can't override completely the confirm message (at least in chrome). The message you return will only be prepended to the one given by Chrome. Here's the reason : How can I override the OnBeforeUnload dialog and replace it with my own?
Try this, loading data via ajax and displaying through return statement.
<script type="text/javascript">
function closeWindow(){
var Data = $.ajax({
type : "POST",
url : "file.txt", //loading a simple text file for sample.
cache : false,
global : false,
async : false,
success : function(data) {
return data;
}
}).responseText;
return "Are you sure you want to leave the page? You still have "+Data+" items in your shopping cart";
}
window.onbeforeunload = closeWindow;
</script>
You can try 'onbeforeunload' event.
Also take a look at this-
Dialog box runs for 1 sec and disappears?

Javascript - Custom Confirm Dialog - replacing JS confirm

This may be a easy answer-
In my JS I've replaced JS's confirm function with my own. Which basically and simply looks like this:
function confirm(i){
var options = '<br/><br/><input class="button1" value="Yes" type="button" onclick="return true"> <input class="button1" value="No" type="button" onclick="return false">';
$('#text').html(i+options);
$('#confirmDiv').fadeIn('fast');
}
Obviously the return true / false didn't work, or else I wouldn't be asking!
In another function i've got (So you get the picture):
var con = confirm("Are you sure you'd like to remove this course?");
if(!con){return;}
How can I get confirm to return the value directly? I'd assume it's return {this.value} or so?
Thanks!
Your problem is that your custom confirm isn't modal. That means that when your confirm is shown, the code runs on. There is no chance for you to wait for the user's choice within confirm() and return it from there.
As far as I know, there is no way to emulate the behaviour of a modal confirmation dialog in Javascript (except for the non-standard ShowModalDialog().)
The usual way of doing this is adding a function() { ... } callback to each button's click event, and doing whatever the "ok" click is supposed to do in there.
My way around this problem was to add some arbitrary data to the object, and check for that data on click. If it existed, proceed with the function as normal, otherwise confirm with a yes/no (in my case using a jqtools overlay). If the user clicks yes - insert the data in the object, simulate another click and wipe the data. If they click no, just close the overlay.
Here is my example:
$('button').click(function(){
if ($(this).data('confirmed')) {
// Do stuff
} else {
confirm($(this));
}
});
And this is what I did to override the confirm function (using a jquery tools overlay):
window.confirm = function(obj){
$('#dialog').html('\
<div>\
<h2>Confirm</h2>\
<p>Are you sure?</p>\
<p>\
<button name="confirm" value="yes" class="facebox-btn close">Yes</button>\
<button name="confirm" value="no" class="facebox-btn close">No</button>\
</p>\
</div>').overlay().load();
$('button[name=confirm]').click(function(){
if ($(this).val() == 'yes') {
$('#dialog').overlay().close();
obj.data('confirmed', true).click().removeData('confirmed');
} else {
$('#dialog').overlay().close();
}
});
}
I found another hacked solution to emulate the modale dialog like mentioned from Pekka 웃 before. If you break the JS execution there is no need to loop in a while(true). After retrieving the users input (click) we can go on with JS execution while calling the origin method again with eval and returning the users choice as boolean.
I created a small jsfiddle with jquery and notyjs to simply show my solution:
jsfiddle: Overriding native modal confirm alert
Here again the important code:
/** confirm as noty.JS **/
var calleeMethod2 = null;
var returnValueOfConfirm = null;
var args = null;
var calleeMethod = null;
var refreshAfterClose = null;
var savedConfirm = window.confirm;
window.confirm = function(obj) {
// check if the callee is a real method
if (arguments.callee.caller) {
args = arguments.callee.caller.arguments;
calleeMethod = arguments.callee.caller.name;
} else {
// if confirm is called as if / else - rewrite orig js confirm box
window.confirm = savedConfirm;
return confirm(obj);
}
if (calleeMethod != null && calleeMethod == calleeMethod2) {
calleeMethod2 = null;
return returnValueOfConfirm;
}
noty({
text: obj,
buttons: [{
text: 'Yes',
onClick: function($noty) {
$noty.close();
noty({
text: 'YES',
type: 'success'
});
}
}, {
text: 'No',
onClick: function($noty) {
$noty.close();
noty({
text: 'NO',
type: 'error'
});
}
}]
});
throw new FatalError("!! Stop JavaScript Execution !!");
}
function runConfirmAgain() {
calleeMethod2 = calleeMethod;
// is a method
if (calleeMethod != null) {
var argsString = $(args).toArray().join("','");
eval(calleeMethod2 + "('" + argsString + "')");
} else {
// is a if else confirm call
alert('confirm error');
}
}

Categories