I have prepared a simple test case demonstrating my problem -
I use a jQuery UI button to open a jQuery UI dialog:
However this works only once. On subsequent button clicks I get the error:
Uncaught Error: cannot call methods on dialog prior to initialization;
attempted to call method 'open'
Even though I do initialize the dialog before the button in my code -
HTML-code:
<BUTTON ID="newBtn">New game</BUTTON>
<DIV ID="newDlg" TITLE="New game">
Select game board:
<BUTTON value="1">Winter</BUTTON>
<BUTTON value="2" DISABLED>Spring</BUTTON>
<BUTTON value="3" DISABLED>Summer</BUTTON>
<BUTTON value="4" DISABLED>Autumn</BUTTON>
</DIV>
JavaScript:
var newDlg = $('#newDlg').dialog({
modal: true,
autoOpen: false,
close: function(e, ui) {
var bid = parseInt($(this).data('bid'));
$(this).removeData();
if (1 <= bid && bid <= 4) {
alert('selected board id: ' + bid);
}
},
buttons: {
'Close': function() {
$(this).dialog('close');
}
}
});
$('#newDlg button').button().click(function(e) {
e.preventDefault();
var bid = this.value;
newDlg.data('bid', bid);
newDlg.dialog('close');
});
var newBtn = $('#newBtn').button().click(function(e) {
e.preventDefault();
newDlg.dialog('open'); // also tried $('#newDlg') here!
});
I have tried using jQuery UI 1.11.4 and 1.12.1 but the problem persists.
Funny story, the issue is:
$(this).removeData();
This is removing all data attributes, including those used to define the dialog. This can be fixed by defining the specific data you want to remove:
$(this).removeData('bid');
Then it works as expected.
Forked working example: https://jsfiddle.net/Twisty/dz8krbye/
Related
Just adding the bootstrap-confirmation extension for Bootstrap popover to some buttons on a project. I'm having issues with the options not being respected. I'm trying to get the popups to work as singletons and dismiss when the user clicks outside of them singleton and data-popout options, respectively - both set to true. I'm also not seeing any of my defined callback behavior happening.
I defined the options both in the HTML tags and in a function and neither works. Still getting multiple boxes and they don't dismiss as expected.
My JS is loaded after all other libraries and is in my custom.js file in my footer.
JS is as follows:
$(function() {
$('body').confirmation({
selector: '[data-toggle="confirmation"]',
singleton: true,
popout: true
});
$('.confirmation-callback').confirmation({
onConfirm: function() { alert('confirm') },
onCancel: function() { alert('cancel') }
});
});
An example of the box implemented on a button in my HTML is the following:
<a class="btn btn-danger" data-toggle="confirmation" data-singleton="true" data-popout="true"><em class="fa fa-trash"></em></a>
Any pointers would be appreciated. I even changed the default options in the bootstrap-confirmation.js file itself to what I want and still no luck.
Turns out I needed to rearrange a couple things to get this to work. I've left in the last_clicked_id etc stuff as I needed to add that to get the id value of what I'd just clicked.
// Product removal popup logic
var last_clicked_id = null;
var last_clicked_product = null;
$('.btn.btn-danger.btn-confirm').click(function () {
last_clicked_id = $(this).data("id");
last_clicked_product = $(this).data("product");
});
$('.btn.btn-danger.btn-confirm').confirmation({
singleton: true,
popout: true,
onConfirm: function () {
alert("DEBUG: Delete confirmed for id : " + last_clicked_product);
// TODO: Add AJAX to wipe entry and refresh page
},
onCancel: function () {
alert("DEBUG: Delete canceled for id : " + last_clicked_product);
}
});
I was a step ahead of myself with the callback logic which was not getting executed. Fixed by simply adding it to onConfirm: and onCancel: key values in the .confirmation() function. A bit of a RTFM moment there but this was unfortunately not very clear in the documentation.
This question is an ongoing learning / discovery of these three questions. This issue for me started here:
First Post
Second Post
Now this post is regarding #StephenMuecke post about attaching the event handler dynamically. This was new to me so I had to read up but now I see that it does make sense.
Well after reading documentation and numerous SO posts I still can't seem to get the click event handler to fire??
This time I decided to take a different approach. I created a jsfiddle demonstrating the problem. http://jsfiddle.net/ramjet/93nqs040/17/
However the jsfiddle I had to change somewhat from reality to get it to work within their framework. Below is the actual code.
Parent Window script that launches modal...the alert Bound does fire.
<script>
$(document).ready(function ()
{
$("#new").click(function (e)
{
e.preventDefault();
var ischanging = false;
var financierid = 0;
var detailsWindow = $("#window").data("kendoWindow");
if (!detailsWindow)
{
// create a new window, if there is none on the page
detailsWindow = $("#window")
// set its content to 'loading...' until the partial is loaded
.html("Loading...")
.kendoWindow(
{
modal: true,
width: "800px",
height: "400px",
title: "#T("...")",
actions: ["Close"],
content:
{
url: "#Html.Raw(Url.Action("ActionName", "Controller"))",
data: { financierId: financierid, isChanging: ischanging }
}
})
.data("kendoWindow").bind('refresh', function (e)
{
alert('Bound');
$('document').on("click", "#save", function () { alert("i work");});
}).center();
}
detailsWindow.open();
});
</script>
The modal full html I didn't think was needed but if it is I will update it. This is just the element I am trying to dynamically bind to.
<input type="button" id="save" style="margin-right:10px;" value="Save Record" />
document doesn't need quotes:
$(document).on("click", "#save", function () { alert("i work");});
"document" searches for an element of document, not the actual document
$("document").length; //0
$(document).length; //1
Using JQuery Dialog http://jqueryui.com/dialog/#modal-confirmation
The dialog box appears whenever the page loads I only want it to appear when 'Remove Invoice' is clicked.
i've tried:<input id="RemoveInvoice" type="button" value="Remove Invoice" onclick="ConfirmDeleteInvoice()" />
then putting the actual JS inside a ConfirmDeleteInvoice function:
function ConfirmDeleteInvoice() {
// $(function () { //removed this line and added the above line
$("#dialog-confirm").dialog({
resizable: false,
height: 140,
modal: true,
buttons: {
"Are you sure you want to delete this invoice": function () {
$(this).dialog("close");
},
Cancel: function () {
$(this).dialog("close");
}
}
});
});
}
ERROR: JavaScript runtime error: 'ConfirmDeleteInvoice' is undefined
Sorry still a beginner at JS so please bear with.
Thanks
You've got an extra trailing }); right before your last closing brace, take that out and it'll work.
Also, in my fiddle you'll see I've added the click event in jQuery, as onclick inside HTML is considered bad practice. I did this by adding:
$("#RemoveInvoice").click(ConfirmDeleteInvoice);
See here: http://jsfiddle.net/P4VHw/
Since jquery UI dialog does not support returning true/false, I need some other way to replace a javascript confirm.
It has to return true/false, so that my validation processes in javascript will run:
var where_to_coupon = confirm(pm_info_msg_013);
if (where_to_coupon== true) {
doSubmit=true;
return doSubmit;
The only way I know of doing that is passing a callback to the function.
The problem you face is that JQuery UI will not block the execution like confirm to wait for user input so you need to open the dialog and when the user clicks an answer act accordingly.
If you use Jquery UI dialog you can bind the callback functions to the buttons.
For instance:
myConfirm("Are you sure?", function(){ [YES CODE] }, function(){ [NO CODE] });
Your custom confirm will look like this:
var myConfirm = function(msg, yesAction, noAction){
$.dialog{
[CODE],
buttons: {
yes: yeasAction,
no: noAction
}
};
};
jQuery UI can do what you want, you simply have to adjust your code to work in an async way. Ariel Popovosky gave an answer which attempts to wrap a dialog call into a simple function call, and would work well but would require the same basic sync/async code modifications that any change from window.confirm would require.
Using window.confirm we use a synchronous way of doing things--program halts while user makes a decision. See example: http://jsfiddle.net/9jY7E/
Using UI's dialog, we simply move the behavior which should happen on confirm into the behavior assigned to one of the UI buttons. The dialog shows, and the program continues to run. But because you moved your "ok" code into the functionality bound to the button, that code doesn't run until the user clicks it. The following link is the same example I showed with window.confirm, but has been modified to use UI dialog: http://jsfiddle.net/9jY7E/1/
I don't know of any replacement for window.confirm which works just like window.confirm but allows for your own styling. All dialog systems I know of work somewhat similar to UI.
Additional: At the following link you will find a 3rd example of the same external link confirmation using the methodology Ariel gave in his answer: http://jsfiddle.net/9jY7E/2/
This is a little convoluted, but it works for me. It sets a "global" variable and tests that value to see if the dialog should be displayed.
I know it probably isn't the most efficient method.
The confirmIt funciton returns true or false.
The reason for the setTimeout("confirmItConfirmed=false;",500); near the end is to reset the variable so the next time the function is called it won't just return true.
Some browsers do better at handling the auto height and width than others.
The notice function is a replacement for alert and confirmIt replaces confirm.
<html>
<head>
<title>jQuery Confirm & Alert Replacements</title>
<link type=text/css href=http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/redmond/jquery-ui.css rel=stylesheet />
<script type=text/javascript src=https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js></script>
<script type=text/javascript src=https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js></script>
<script type=text/javascript>
var confirmItConfirmed = false;
var jq = $.noConflict();
function notice(message,title,height,width) {
if (!title)
var title = document.title+' says...';
jq('body').append('<span id=noticeDialogSpan style=display:none></span>');
jq('#noticeDialogSpan').html('<div id=noticeDialog title="'+title+'">'+message+'</div>');
if (!width)
var width = jq('#noticeDialogSpan').width()+40;
if (!height)
if (jq('#noticeDialogSpan').height() > jq(window).height()-100)
var height = jq(window).height()-100;
else
var height = 'auto';
jq('#navMenu').hide();
jq('#noticeDialog').dialog ({
height: height,
width: width,
modal: true,
close: function(event,ui) {
jq(this).dialog('destroy');
jq('#noticeDialog').remove();
jq('#noticeDialogSpan').remove();
jq('#navMenu').show();
},
buttons: {
'Close': function() { jq(this).dialog('close'); }
}
});
}
function confirmIt(e,message,title,height,width) {
if (!confirmItConfirmed) {
if (!title)
var title = document.title+' says...';
jq('body').append('<span id=confirmationDialogSpan style=display:none></span>');
jq('#confirmationDialogSpan').html('<div id=confirmationDialog title="'+title+'">'+message+'</div>');
if (!width)
var width = jq('#confirmationDialogSpan').width()+40;
if (!height)
if (jq('#confirmationDialogSpan').height() > jq(window).height()-100)
var height = jq(window).height()-100;
else
var height = 'auto';
jq('#navMenu').hide();
jq('#confirmationDialog').dialog ({
height: height,
width: width,
modal: true,
close: function(event,ui) {
jq('#confirmationDialog').remove();
jq('#confirmationDialogSpan').remove();
jq(this).dialog('destroy');
jq('#navMenu').show();
},
buttons: {
'Confirm': function() {
jq(this).dialog('close');
confirmItConfirmed = true;
e.click();
},
'Cancel': function() { jq(this).dialog('close'); }
}
});
}
setTimeout("confirmItConfirmed=false;",500);
return confirmItConfirmed;
}
function testIt(e) {
if (confirmIt(e,'Are you sure you want to continue?','My Title'))
notice('You clicked Confirm','My Title');
}
</script>
</head>
<body>
<br />
<br />
Click HERE to test a link.
<br />
<br />
Click this button to test it too <input value='Click Me' type=button onclick="testIt(this)" />
</body>
</html>
This could also be done using boopup + callbacks:
Boopup.confirm("This is a boopup confirm!", function(agree) {
console.log(agree);
})
https://github.com/petruisfan/boopup
I'm working on fixing up a legacy web application with jQuery.
I have a form that has 40 buttons that each have some type of confirmation that use javascript confirm. I want to switch these over to use the jquery modal dialog.
I have programmed several of them like below and they work fine. Problem is that there is 40 of them on the form - so don't want to have to program 40 separate modal boxes. The only thing that is really changing is the javascript that is called when the Yes button is clicked
Any suggestions?
Code called on button:
$("#confirm1dialogTitle").html("Approve?");
$("#confirm1dialogText").html("Do you want to approve this request?");
$('#confirm1dialog').dialog('open');
Embedded javascript:
<script type="text/javascript">
$(function() {
$("#confirm1dialog").dialog({
bgiframe: true,
autoOpen: false,
width: 350,
height: 350,
modal: true,
buttons: {
'Yes': function() {
window.document.forms[0].FDDStatus.value = "Approved";
window.document.forms[0].DivisionApproval.value = "Yes";
window.document.forms[0].setApprovalFields();
},
'No': function() {
$(this).dialog('close');
}
}
});
});
</script>
Embedded HTML:
<div id="confirm1dialog" title="<span id='Title'>Title</span>">
<div id="users-contain" class="ui-widget">
<form>
<span id="confirm1Text"></span>
</form>
</div>
</div>
you can put the javascript that is changing in a function object, then reuse it..
lets assume that you you from looks like this:
<form><input id='btn1' /><input id='btn2' /></form>
then you make a helper function:
var confirmHelper = function(id, yesCallback) {
$(id).click(function() {
$(function() {
// the code from you example
$("#confirm1dialog").dialog({
bgiframe: true,
autoOpen: false,
width: 350,
height: 350,
modal: true,
buttons: { 'Yes': yesCallback, 'No': function() { } }
}
}
}
}
then you apply it to your buttons:
confirmHelper('btn1' function() {
// your callback from before
window.document.forms[0].FDDStatus.value = "Approved";
window.document.forms[0].DivisionApproval.value="Yes";
window.document.forms[0].setApprovalFields();
});
confirmHelper('btn2' function() {
// your other javascript code
});
like so for the 40 buttons :)
You can write 40 functions in javascript (the ones that have to be executed when the yes button is pressed) and use only one modal box.
I donĀ“t know what your click() function looks like, but it is easy to add a variable there using for example a rel attribute on the link you're clicking, a class, etc. Depending on the variable, you could execute the required function.