Working with variables outside of jquery UI dialog - javascript

I have a .each that loops through table rows and compares information already entered to what the user is currently attempting to add. I have conditionals in the loop that look for duplicate entries across each of the s in the row. Depending on how many match, there's a yes/no decision for the user to make. If the user chooses yes, the current row needs to be removed. I am using jQuery UI and am having problems getting the dialog box to know what row to remove, or having the .each loop know what was selected in the dialog.
The .each loop looks like this:
$('#tblSelectedList > tbody > tr').each(function() {
Here's the code for the dialog (within in the for loop):
$('<div></div>').appendTo('body')
.html('<div><h6>Delete duplicate?</h6></div>')
.dialog({
modal: true,
title: 'Delete message',
zIndex: 10000,
autoOpen: true,
width: 'auto',
resizable: false,
buttons: {
Yes: function () {
removeThis = 1;
blnAdd = 1;
$(this).dialog("close");
},
No: function () {
blnAdd = 0;
$(this).dialog("close");
}
},
close: function (event, ui) {
$(this).remove();
}
});
and the method I am using to remove rows:
var id = $(this).attr('id').substring(7,$(this).attr('id').length);
$('#tblSelectedList #row-'+id).remove();
Everything works independently, but I can't get the dialog and its containing .each loop to know what the other is doing.

I think the first thing you need to do is to set an id for each row in your table. That way you can know how to find a row later on. That can be easily done using jQuery if it is not possible to do it when creating the actual table.
Here is an example:
var rowsCount = 0;
$('#tblSelectedList > tbody > tr').each(function() {
//setting the row ids to be something like: tblSelectedList_row0,tblSelectedList_row1,...,tblSelectedList_rown
$(this).attr("id","tblSelectedList_row" + (rowsCount++));
}
So then in your foreach loop for your actuall row dupplicate detaction logic you just do something like this:
$('#tblSelectedList > tbody > tr').each(function() {
//determine here is this row should be deleted
var rowShouldBeDeleted = true;
if ( rowShouldBeDeleted ){
//here we invoke our promt for delete function passing the row identifier
//which is explained below
promptForDelete(this.id);
}
}
Then I would suggest using two functions:
One that will ask the question "promtForDelete".
Another one that actually deletes the row.
So for the first one you need to pass all the information required to identify which row should be deleted "the row id", in case the user selects "Yes", along with any other data that you want to display in the prompt.
Here is example:
function promptForDelete(rowId){
$('<div></div>').appendTo('body')
.html('<div><h6>Delete duplicate?</h6></div>')
.dialog({
modal: true,
title: 'Delete message',
zIndex: 10000,
autoOpen: true,
width: 'auto',
resizable: false,
buttons: {
Yes: function () {
deleteRow(rowId);
blnAdd = 1;
$(this).dialog("close");
},
No: function () {
blnAdd = 0;
$(this).dialog("close");
}
},
close: function (event, ui) {
$(this).remove();
}
});
}
Now for the second function "deleteRow" all you have to do is find the row that matches that id and remove it.
Here is an example:
function deleteRow(rowId){
$(rowId).remove();
}
And that's it.... I hope this makes sense to you.

Related

Using Kendo Grid - onclick requires an extra click to call a jquery method

I have 7 columns (using html Kendo Grid), and the ID column is a PK of each row and its visible(false).
So.. When you click on any "Name" data, it grabs a PK(the ID that is invisible) of the row you selected, and a modal screen will pop up so you can see more detailed information.
Currently, it is working as expected, however, when the page loads for the first time, I have to double click it to make the modal screen display. Once the modal screen displays, after that, onclick event works as intended.
But I just noticed that when I hit the F12 key to see the log, the number of click increments(like... x2 x3 etc.) everytime onclick event calls.
When I Debug, it hits the debug point in my code but disappears right away so its really hard for me to investigate.
Thank you for your help.
------Column that has the onclick event--------
Columns(columns => {columns.Bound(o => o.SiteID).Visible(false);
columns.Bound(o => o.Name).Title("Your Name").HeaderHtmlAttributes(new {title = "Name(s)"}).ClientTemplate("<a class='nameLink' onclick=\"EditSite(#:SiteID#);\" style='cursor:pointer;' SiteID=\'#=SiteID#\'>#=Name#</a>");
----Jquery onclick event ------
function EditSite(SiteID) {
debugger;
$('.nameLink').on('click', function () {
$('#popUpEdit').dialog({
width: 1000,
height: 920,
show: 'fadein',
hide: 'fadeout',
buttons: { "Close": function () { $(this).dialog("close"); } },
close: function () {
$("#popUpEdit input").val("");
$('#popUpEdit input').prop('checked', false);
$('#statusMessage').html("");
}
});
NameDetails(SiteID);
});
};
You are binding an onClick function every time the EditSite function is called. Try using .off() to unbind any existing handlers.
$('.nameLink').off().on('click', function () { }
Also try wrapping your function so you can pass your SiteID parameter.
(not sure the proper syntax for this)
onclick="EditSite(#:SiteID#)"
Wrapping the function
function EditSite(SiteID) {
return function() {
$('#popUpEdit').dialog({
width: 1000,
height: 920,
show: 'fadein',
hide: 'fadeout',
buttons: { "Close": function () { $(this).dialog("close"); } },
close: function () {
$("#popUpEdit input").val("");
$('#popUpEdit input').prop('checked', false);
$('#statusMessage').html("");
}
});
NameDetails(SiteID);
}
}

jquery dialog with zero to many child jquery dialogs

I have a "parent" jQuery dialog that could span one to many jQuery dialogs when the OK button is pressed. It also might not create any child dialogs.
I also want to take the user to a confirmation page when the OK button is pressed in the parent.
I have used the stack option in the child to get "stacked" dialogs to work. My problem is when the OK button is pressed on the "parent", code continues to execute and the browser is taken to the confirmation page before the user has a chance to answer the "child" dialog.
Is there any way for the parent to wait till the child dialogs are answered before the code continues to take the user to the confirmation page from the parent's OK event?
My only other thought was to actually have the "child" OK button take the user to the confirmation page put that could complicate the code a bit since I would need code for letting the child know it is the last child so i can take the user to the confirmation page.
function getDeclineReason(appName) {
$("#dvDeclineReason")
.dialog({
modal: true,
stack: true,
title: 'Decline Reason',
open: function() {
$('.ui-widget-content').css('background', 'white');
$('.ui-widget-header').css('background', '#0072C6');
$('.ui-widget-header').css('border', '1px solid #0072C6');
},
buttons: {
OK: function() {
$(this).dialog("close");
return;
},
Cancel: function() {
$(this).dialog("close");
return;
}
},
zIndex: 10000,
autoOpen: true,
width: 'auto',
resizable: false,
draggable: false,
});
}
function reviewRequest() {
getDeclineReason("Test");
$("#dvReview")
.dialog({
modal: true,
title: 'Review Request',
open: function() {
$('.ui-widget-content').css('background', 'white');
$('.ui-widget-header').css('background', '#0072C6');
$('.ui-widget-header').css('border', '1px solid #0072C6');
},
buttons: {
OK: function() {
var numChecked = 0;
$('input[name="apps"]').each(function() {
if (NWF$(this).is(':checked'))
numChecked++;
});
if (numChecked == 0) {
if (!confirm("You have not approved any applications. If this was you intent then press OK to confirm the deny of all applications. Otherwise press cancel to try again."))
return;
}
var totalApps = $('input[name="apps"]').length;
var countApps = 0;
$('input[name="apps"]').each(function() {
var decision;
if (NWF$(this).is(':checked'))
decision = "Approved";
else {
decision = "Declined";
getDeclineReason($(this).text());
}
switch (status) {
case "Pend Mgr Review":
updateFields["Title"] = "Manager Decision";
break;
case "Pend App Owner Review":
updateFields["Title"] = "App Owner Decision";
break;
}
countApps++;
/*
updateFields["RequestNumber"] = requestNum;
updateFields["Application"] = $(this).text(); // Get value from current check box item
updateFields["AppStatusID"] = $(this).val();
updateFields["Decision"] = decision;
if (countApps == totalApps)
updateFields["LastDecision"] = "Y";
else
updateFields["LastDecision"] = "N";
addListItem("Decision",updateFields);
*/
});
$(this).dialog("close");
//window.location.href = "/apps/TAI/SitePages/Decisioned.aspx";
return;
},
Cancel: function() {
$(this).dialog("close");
return;
}
},
zIndex: 10000,
autoOpen: true,
width: 'auto',
resizable: false,
draggable: false,
});
}
You could keep track of all the open dialogs and everytime the user clicks "OK" to close one of then substract one to the count and check if there are no more dialogs remaining. Then you can redirect the user to the other site.

find a element in jQuery dialog after it opens

I'm creating a dialog on the fly. What I'm trying to do next is to bind some of the inputs with .datepicker(), but I can't seem to find the inputs at all. What I'm I missing here?
JSFIDDLE
function createDialog(top, dialog_width, data) {
$('<div></div>')
.addClass('add-dialog')
.appendTo('body')
.dialog({
title: 'test',
closeText: '<i class="fa fa-times"></i>',
close: function () {
$(this).remove();
},
open: function (event, ui) {
//has the full html with the inputs
console.log(this);
//trying to get them
var inputs = $(this).find('input');
console.log(inputs.length);
//also tried this, no luck
//$(this).parent().promise().done(function() {
// var t = $(this).find('input');
//});
},
modal: true,
width: dialog_width,
position: ['center', (top - 12)],
draggable: false,
resizable: false
}).html(data);
}
Simply change the initialization order.... add the html, then initialize the dialog
$('<div></div>').html(data).dialog({ /*opts*/})
You are adding the html after the dialog is initialized so the open event has already occurred and there is no element yet to be found
DEMO
You can asign a class to each element you need, something like:
<input type='text' class='needIt'/>
and then use:
$(this).find('.needIt')
You need to save reference to the jquery object after it has been inserted into DOM, then get reference to jquery UI dialog instance. And this instance has many useful properties. Example:
$('form').append($body); // I've appended dialog as last element inside form in my document, $body is markup, received from AJAX
$body.dialog({...}); // I've turned markup into jquery UI dialog
var dialogInstance = $body.dialog('instance'); // I receive reference to jquery UI dialog instance in any place, for instance, button click event
dialogInstance.uiDialogButtonPane.hide(); // I can access button pane in the dialog and many other objects, like caption area, etc.
try this add html after appendTo()
function createDialog(top, dialog_width, data) {
$('<div></div>')
.addClass('add-dialog')
.html(data)// added html here
.appendTo('body')
.dialog({
title: 'test',
closeText: '<i class="fa fa-times"></i>',
close: function () {
$(this).remove();
},
open: function (event, ui) {
//has the full html with the inputs
console.log(this);
//trying to get them
var inputs = $(this).find('input');
console.log(inputs.length);
//also tried this, no luck
//$(this).parent().promise().done(function() {
// var t = $(this).find('input');
//});
},
modal: true,
width: dialog_width,
position: ['center', (top - 12)],
draggable: false,
resizable: false
});
}

jQuery hidden field not getting set more than once

I'm trying to allow users to delete multiple records, they click a link "delete" and a dialog shows saying are you sure? On clicking OK it should delete.
It works for the first time I do it, but for any other delete buttons I click it doesn't work. I'm setting a hidden field to store some information then getting that information in the dialog.
I have identified the problem see comment in code, but not sure why its a problem.
This is for the delete buttons:
$(".delete-item").click(function () {
$(this).css('font-weight', 'bold');
var delId = $(this).attr("id");
$("#hidden-itemid").val(delId);
$("#dialog-delete-sure").dialog("open");
});
heres the dialog:
$("#dialog-delete-sure").dialog({
autoOpen: false,
resizable: false,
height: 140,
modal: true,
buttons: {
Ok: function () {
var hiddenId = $("#hidden-itemid").val();//*** This comes back undefined the second time***//
var itemId = $("#hidden-itemid").val().split('-')[1];
var iType = $("#hidden-itemid").val().split('-')[0];
$.post('/User/Delete/', { id: itemId, itemType: iType }, function (json) {
if (json.success) {
$("#" + iType + "-row-" + itemId).hide('slow', function () { $("#hidden-itemid").remove(); });
$("#dialog-success-delete").dialog("open");
} else {
if (json.error == "unknown") {
$("#dialog-unknown-error").dialog("open");
}
if (json.error == "unauthenticated") {
$("#dialog-unauthenticated").dialog("open");
}
}
});
$("#hidden-itemid").css('font-weight', 'normal');
$(this).dialog("close");
},
Cancel: function () {
$(this).dialog("close");
}
}
});
a typical delete button looks like this:
<a id="event-63" class="delete-item">Delete</a>
any ideas?
You are running
$("#hidden-itemid").remove();
on json.success so you remove the element from the DOM .. next time it does not exists and thus you get an error..

JQuery UI: Accordion callbacks

I need my javascript to only do the callback when I OPEN a section on the accordion, as of right now it does a callback when I open OR close a section because I'm only using a click function. Is there a way I can modify my existing click function to only run when the given section is activated?
My current click function:
$("a#mimetypes").click(function() {
$("span#mimetypesthrobber").loading(true, { max: 1500 })
$.getJSON("../mimetypes", function(data) {
//callback
});
});
Thanks!
EDIT:
I already tried this with another part of the accordion and it wasn't working properly:
$('.ui-accordion').bind('accordionchange', function(event, ui) {
if (ui.newHeader == "Encoders") {
EncodersGet();
}
});
you can use the the "change event"
$('.ui-accordion').bind('accordionchange', function(event, ui) {
ui.newHeader // jQuery object, activated header
ui.oldHeader // jQuery object, previous header
ui.newContent // jQuery object, activated content
ui.oldContent // jQuery object, previous content
});
and access the "newHeadert" for example and do your processing
EDIT
according to the new info {collapsible: true, active: false}
$(document).ready(function() {
var $acc = $('#accordion').accordion({ collapsible: true,
active : false ,
change : function (event, ui)
{
var index = $acc.accordion( "option", "active");
if( index === false){
// all are close
}
else{
// 0-based index of the open section
}
}
});
});
the "option, active" would return you the index of the open section or "false" if all sections are closed
One improvement on undertakerors answer: use triple equals when comparing index to false to avoid the first accordion element to match.
if (index === false) {
// All are closed
} else {
// 0-based index of the open section
}
Please remember that double equals will perform type conversion when evaluating conditions.
If all the accordion sections are closed by dfault you could replace the click event with toggle and have the second function simple do nothing.
$("a#mimetypes").toggle(function() {
$("span#mimetypesthrobber").loading(true, { max: 1500 });
$.getJSON("../mimetypes", function(data) {
//callback
});
},
function() {
//do nothing
});
The better solution would be to add a class to the active section and check for that class before calling the load.
$("a#mimetypes").click(function() {
if ($(this).hasClass("active")) {
$(this).removeClass("active");
}
else {
$(".active").removeClass("active"); //Edit - remove all active classes to account for this section being closed by the opening of another
$(this).addclass("active");
$("span#mimetypesthrobber").loading(true, { max: 1500 });
$.getJSON("../mimetypes", function(data) {
//callback
});
}
});

Categories